#include "GPUFontAtlasLayerCombo.h" #include "Utils.h" #include "font.hpp" #include "ofColor.h" #include "ofEvents.h" #include "ofGraphics.h" #include "ofUtils.h" namespace ofxVariableLab { void GPUFontAtlasLayerCombo::setup(const ComboIdentifier & identifier, AtlasLayerComboSettings settings){ this->identifier = identifier; this->settings = static_cast (settings); #ifdef TARGET_EMSCRIPTEN string shaderDir = "data/ofxGPUFont/shaders/DEBUG_ES3"; #else string shaderDir = "data/ofxGPUFont/shaders/GL3"; #endif shaderCatalog = std::make_unique (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); font->listFontVariationAxes(fontVariationAxesParameters, library); cout << this->identifier.fontPath << " : fontVariationAxes :" << endl; 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; } void GPUFontAtlasLayerCombo::update(){ //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); //} //} for(const auto & layer : layers){ if(layer->isDirtyDirty()){ isDirty = true; break; } } if(isDirty){ std::string text = ""; totalCharacters = 0; std::vector _variationText; for(const auto & layer : layers){ std::string layerText = layer->getProps().text; totalCharacters += layerText.length(); _variationText.insert(_variationText.end(), layer->getVariationText().begin(), layer->getVariationText().end()); 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); isDirty = false; } } void GPUFontAtlasLayerCombo::careForChild(shared_ptr layer){ if(layer->getType() == LayerType::GPUFONT){ shared_ptr gpuFontLayer = static_pointer_cast (layer); gpuFontLayer->setMomsComboIdentifier(identifier); gpuFontLayer->isWithNewMom(); gpuFontLayer->setDirtyDirty(true); 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; } layers.push_back(std::move(gpuFontLayer)); }else{ ofLogError("GPUFontAtlasLayerCombo::careForChild()") << __LINE__ << ": child is not recognized as Layer::GPUFONT"; } } void GPUFontAtlasLayerCombo::abandonChild(shared_ptr layer){ // TODO: handle removing child text from buffer shared_ptr gpuFontLayer = static_pointer_cast (layer); layers.erase( std::remove_if( layers.begin(), layers.end(), [gpuFontLayer](shared_ptr const & l) { return l == gpuFontLayer; }), layers.end()); isDirty = true; // 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... } const ComboIdentifier & GPUFontAtlasLayerCombo::getIdentifier() const { return identifier; } void GPUFontAtlasLayerCombo::setVFlip(VFlipState vFlipState){ vFlip = vFlipState; } const vector > & GPUFontAtlasLayerCombo::getLayers(){ return layers; } void GPUFontAtlasLayerCombo::draw(){ GLuint location; int width = ofGetWidth(); int height = ofGetHeight(); glm::vec2 mouse = glm::vec2(ofGetMouseX(), ofGetMouseY()); //glm::mat4 projection = transform.getProjectionMatrix((float)width / height); glm::mat4 projection = transform.getOrthoProjectionMatrix(width, height, Transform::TOP_LEFT); //Transform::CENTERED); 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); ofDisableDepthTest(); ofEnableAlphaBlending(); int currentProgram; glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); 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); 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 vertices; std::vector indices; for(const auto & layer : layers){ font->collectVerticesAndIndices(glm::vec3(layer->getProps().x, layer->getProps().y, 0), layer->getVariationText(), vertices, indices, true, layer->getProps().fontSize_px); } 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); //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); glUseProgram(currentProgram); } glDisable(GL_BLEND); //ofDrawBitmapStringHighlight( //(ofToString("and we know:") + ofToString("everything")) //, 100 + mouse.x, mouse.y, ofFloatColor::pink, ofFloatColor::black); ofDrawBitmapStringHighlight( "fps: " + ofToString(ofGetFrameRate()) + "\n" + "font: " + this->identifier.fontPath + "\n" , 20, 20); } }