ofxVariableLab/src/GPUFontAtlasLayerCombo.cpp

261 lines
9.8 KiB
C++
Raw Normal View History

2023-04-12 10:58:53 +02:00
#include "GPUFontAtlasLayerCombo.h"
2023-04-12 13:59:09 +02:00
#include "Utils.h"
2023-04-13 17:15:35 +02:00
#include "font.hpp"
2023-04-12 13:59:09 +02:00
#include "ofColor.h"
2023-04-12 15:47:40 +02:00
#include "ofEvents.h"
2023-04-12 16:25:43 +02:00
#include "ofGraphics.h"
#include "ofUtils.h"
2023-04-12 10:58:53 +02:00
namespace ofxVariableLab {
2023-04-13 17:15:35 +02:00
void GPUFontAtlasLayerCombo::setup(const ComboIdentifier & identifier,
AtlasLayerComboSettings settings){
2023-04-12 13:59:09 +02:00
this->identifier = identifier;
2023-04-13 17:15:35 +02:00
this->settings = static_cast <GPUFontAtlasLayerComboSettings &>(settings);
2023-04-12 13:59:09 +02:00
#ifdef TARGET_EMSCRIPTEN
string shaderDir = "data/ofxGPUFont/shaders/DEBUG_ES3";
#else
string shaderDir = "data/ofxGPUFont/shaders/GL3";
#endif
shaderCatalog = std::make_unique <ofxGPUFont::ShaderCatalog>(shaderDir);
//backgroundShader = shaderCatalog->get("background");
fontShader = shaderCatalog->get("font");
{
FT_Error error = FT_Init_FreeType(&library);
if(error){
std::cerr << "ERROR: failed to initialize FreeType" << std::endl;
ofExit();
}
}
ofxGPUFont::initializeFont(library,
this->identifier.fontPath,
font,
this->settings.gpuTextureOffset);
2023-04-12 13:59:09 +02:00
font->listFontVariationAxes(fontVariationAxesParameters, library);
2023-04-13 17:15:35 +02:00
cout << this->identifier.fontPath << " : fontVariationAxes :" << endl;
2023-04-12 13:59:09 +02:00
for(const auto & axis : fontVariationAxesParameters){
cout << std::fixed << std::setprecision(10) << axis.name << " :\n"
<< "\tmin: " << std::to_string(axis.minValue)
<< "\tmax: " << std::to_string(axis.maxValue)
<< "\tdefault: " << std::to_string(axis.defaultValue) << endl;
fontVariationAxes.push_back({axis.name, axis.defaultValue});
}
transform = Transform();
auto & r = ofGetCurrentRenderer();
cout << "Render type " << r->getType() << endl;
2023-04-12 10:58:53 +02:00
}
void GPUFontAtlasLayerCombo::update(){
2023-04-13 17:15:35 +02:00
//float animationSpeed = 1.0;
//float threshold = 1.0;
//for(int i = 0; i < fontVariationAxes.size(); i++){
//ofxGPUFont::Font::FontVariationAxis & axis = fontVariationAxes[i];
//ofxGPUFont::Font::FontVariationAxisParameters & axisParams = fontVariationAxesParameters[i];
//double newValue = ofMap(sin(ofGetElapsedTimef() * animationSpeed),
//-1, 1,
//axisParams.minValue, axisParams.maxValue);
//if(abs(newValue - axis.value) > threshold){
//font->setFontVariationAxis(library, axis.name, newValue);
//axis.value = newValue;
//font->prepareGlyphsForText(mainText, true);
//}
2023-04-13 17:15:35 +02:00
//}
2023-04-14 16:55:15 +02:00
for(const auto & layer : layers){
if(layer->isDirtyDirty()){
isDirty = true;
break;
}
}
2023-04-13 17:15:35 +02:00
if(isDirty){
2023-04-14 16:55:15 +02:00
std::string text = "";
totalCharacters = 0;
std::vector <ofxGPUFont::GlyphIdentity> _variationText;
2023-04-14 16:55:15 +02:00
for(const auto & layer : layers){
std::string layerText = layer->getProps().text;
totalCharacters += layerText.length();
_variationText.insert(_variationText.end(),
layer->getVariationText().begin(),
layer->getVariationText().end());
2023-04-14 16:55:15 +02:00
text += layerText;
layer->setDirtyDirty(false); // technically not clean yet
// but this is synchronous
// and will happen, so we can avoid
// another loop
}
removeDuplicateCharacters(text);
mainText = text;
variationText = std::move(_variationText);
font->prepareGlyphsForText(variationText,
library,
true);
2023-04-13 17:15:35 +02:00
isDirty = false;
2023-04-12 16:25:43 +02:00
}
2023-04-12 10:58:53 +02:00
}
void GPUFontAtlasLayerCombo::careForChild(shared_ptr <Layer> layer){
2023-04-13 17:15:35 +02:00
if(layer->getType() == Layer::GPUFONT){
shared_ptr <GPUFontLayer> gpuFontLayer = static_pointer_cast <GPUFontLayer>(layer);
layers.push_back(gpuFontLayer);
std::string oldText = mainText;
std::string layerText = gpuFontLayer->getProps().text;
std::string text = oldText + layerText;
totalCharacters += layerText.length();
removeDuplicateCharacters(text);
// check if we added any characters
// TODO: check for variation variations
if(text.length() != oldText.length()){
mainText = text;
isDirty = true;
}
}else{
ofLogError("GPUFontAtlasLayerCombo::careForChild()") << __LINE__ << ": child is not recognized as Layer::GPUFONT";
}
}
void GPUFontAtlasLayerCombo::abandonChild(shared_ptr <Layer> layer){
// TODO: handle removing child text from buffer
shared_ptr <GPUFontLayer> gpuFontLayer = static_pointer_cast <GPUFontLayer>(layer);
layers.erase(
std::remove_if(
layers.begin(),
layers.end(),
[gpuFontLayer](shared_ptr <GPUFontLayer> const & l)
{
return l == gpuFontLayer;
}), layers.end());
// update the text
// this doesn't happen very often, so let's just
// iterate over all layers and calculate fresh
std::string text = "";
totalCharacters = 0;
for(const auto & layer : layers){
std::string layerText = layer->getProps().text;
totalCharacters += layerText.length();
text += layerText;
}
removeDuplicateCharacters(text);
mainText = text;
// NOTE: we do not want to update buffers now,
// as it's probably more costly than just keeping
// the old glyphs around...
2023-04-12 10:58:53 +02:00
}
const ComboIdentifier & GPUFontAtlasLayerCombo::getIdentifier() const {
return identifier;
}
2023-04-12 13:59:09 +02:00
void GPUFontAtlasLayerCombo::setVFlip(VFlipState vFlipState){
vFlip = vFlipState;
}
2023-04-12 10:58:53 +02:00
const vector <shared_ptr <GPUFontLayer> > & GPUFontAtlasLayerCombo::getLayers(){
return layers;
}
2023-04-12 13:59:09 +02:00
void GPUFontAtlasLayerCombo::draw(){
GLuint location;
int width = ofGetWidth();
int height = ofGetHeight();
2023-04-12 15:47:40 +02:00
glm::vec2 mouse = glm::vec2(ofGetMouseX(), ofGetMouseY());
//glm::mat4 projection = transform.getProjectionMatrix((float)width / height);
2023-04-12 16:06:51 +02:00
glm::mat4 projection = transform.getOrthoProjectionMatrix(width,
height,
Transform::TOP_LEFT);
//Transform::CENTERED);
2023-04-12 13:59:09 +02:00
glm::mat4 view = transform.getViewMatrix();
glm::mat4 model = glm::mat4(1.0f);
//{ // Draw background.
//GLuint program = backgroundShader->program;
//glUseProgram(program);
//glBindVertexArray(emptyVAO);
//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//glBindVertexArray(0);
//glUseProgram(0);
//}
// Uses premultiplied-alpha.
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2023-04-12 16:25:43 +02:00
ofDisableDepthTest();
ofEnableAlphaBlending();
2023-04-12 13:59:09 +02:00
int currentProgram;
glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
float cx = FLT_MAX;
float cy = FLT_MAX;
if(font){
fontShaderProgram = fontShader->program;
glUseProgram(fontShaderProgram);
font->program = fontShaderProgram;
font->drawSetup();
location = glGetUniformLocation(fontShaderProgram, "projection");
glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection));
location = glGetUniformLocation(fontShaderProgram, "view");
glUniformMatrix4fv(location, 1, false, glm::value_ptr(view));
location = glGetUniformLocation(fontShaderProgram, "model");
glUniformMatrix4fv(location, 1, false, glm::value_ptr(model));
float z = 0;
location = glGetUniformLocation(fontShaderProgram, "z");
glUniform1f(location, z);
location = glGetUniformLocation(fontShaderProgram, "color");
glUniform4f(location, 1.0f, 1.0f, 1.0f, 0.5f);
2023-04-12 13:59:09 +02:00
location = glGetUniformLocation(fontShaderProgram, "antiAliasingWindowSize");
glUniform1f(location, (float)antiAliasingWindowSize);
location = glGetUniformLocation(fontShaderProgram, "enableSuperSamplingAntiAliasing");
glUniform1i(location, enableSuperSamplingAntiAliasing);
location = glGetUniformLocation(fontShaderProgram, "enableControlPointsVisualization");
glUniform1i(location, enableControlPointsVisualization);
//mouse.x = 0;
//mouse.y = 0;
std::vector <ofxGPUFont::Font::BufferVertex> vertices;
std::vector <int32_t> indices;
2023-04-13 17:15:35 +02:00
for(const auto & layer : layers){
font->collectVerticesAndIndices(glm::vec3(layer->getProps().x,
layer->getProps().y,
0),
layer->getVariationText(),
2023-04-13 17:15:35 +02:00
vertices, indices, true,
layer->getProps().fontSize_px);
}
2023-04-13 17:15:35 +02:00
vertices.resize(totalCharacters * 4);
indices.resize(totalCharacters * 6);
//cx = 0.5f * (bb.minX + bb.maxX);
//cy = 0.5f * (bb.minY + bb.maxY);
font->draw(vertices, indices);
2023-04-12 13:59:09 +02:00
//ofRectangle rectangle(0, 0, width, height);
//ofDrawRectangle(rectangle);
//font->draw(mouse.x, mouse.y - (200 * sin(ofGetElapsedTimef() * 0.25)), 0, "what", vFlip == V_FLIP_ON, 42.0f);
//location = glGetUniformLocation(fontShaderProgram, "color");
//glUniform4f(location, 0.0f, 1.0f, 0.0f, 0.5f);
//font->draw(mouse.x, mouse.y, 0, "ever", vFlip == V_FLIP_ON, 420.0f);
2023-04-12 13:59:09 +02:00
glUseProgram(currentProgram);
}
glDisable(GL_BLEND);
2023-04-12 15:47:40 +02:00
//ofDrawBitmapStringHighlight(
//(ofToString("and we know:") + ofToString("everything"))
//, 100 + mouse.x, mouse.y, ofFloatColor::pink, ofFloatColor::black);
2023-04-12 13:59:09 +02:00
ofDrawBitmapStringHighlight(
"fps: " + ofToString(ofGetFrameRate()) + "\n"
2023-04-13 17:15:35 +02:00
+ "font: " + this->identifier.fontPath + "\n"
2023-04-12 13:59:09 +02:00
, 20, 20);
}
2023-04-12 10:58:53 +02:00
}