diff --git a/example/src/gpufont/font.hpp b/example/src/gpufont/font.hpp index d73f9e7..eee6793 100644 --- a/example/src/gpufont/font.hpp +++ b/example/src/gpufont/font.hpp @@ -61,6 +61,22 @@ class Font { }; public: +/// A structure to model a given axis of a variable font. + struct FontVariationAxisParameters { + /// The name of the variation axis. + const char * name; + /// The axis's minimum coordinate value. + double minValue; + /// The axis's maximum coordinate value. + double maxValue; + /// The axis's default coordinate value. FreeType computes meaningful default values for Adobe MM fonts. + double defaultValue; + }; + + struct FontVariationAxis { + const char * name; + double value; + }; static bool setFontVariationAxis(FT_Library & library, FT_Face & face, const char * name, double coordinate){ bool success = false; @@ -89,24 +105,34 @@ class Font { return success; } -//bool listFontVariationAxes(std::vector &axes, FreetypeHandle *library, FontHandle *font) { - //if (font->face->face_flags&FT_FACE_FLAG_MULTIPLE_MASTERS) { - //FT_MM_Var *master = NULL; - //if (FT_Get_MM_Var(font->face, &master)) - //return false; - //axes.resize(master->num_axis); - //for (FT_UInt i = 0; i < master->num_axis; i++) { - //FontVariationAxis &axis = axes[i]; - //axis.name = master->axis[i].name; - //axis.minValue = master->axis[i].minimum; - //axis.maxValue = master->axis[i].maximum; - //axis.defaultValue = master->axis[i].def; - //} - //FT_Done_MM_Var(library->library, master); - //return true; - //} - //return false; -//} + bool setFontVariationAxis(FT_Library & library, const std::string & name, float coordinate){ + return Font::setFontVariationAxis(library, face, name.c_str(), coordinate); + } + + static bool listFontVariationAxes(std::vector & axes, FT_Library & library, FT_Face & face){ + if(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS){ + FT_MM_Var * master = NULL; + if(FT_Get_MM_Var(face, &master)){ + return false; + } + axes.resize(master->num_axis); + for(FT_UInt i = 0; i < master->num_axis; i++){ + FontVariationAxisParameters & axis = axes[i]; + axis.name = master->axis[i].name; + axis.minValue = F16DOT16_TO_DOUBLE(master->axis[i].minimum); + axis.maxValue = F16DOT16_TO_DOUBLE(master->axis[i].maximum); + axis.defaultValue = F16DOT16_TO_DOUBLE(master->axis[i].def); + } + FT_Done_MM_Var(library, master); + return true; + } + return false; + } + + bool listFontVariationAxes(std::vector & axes, FT_Library & library){ + return Font::listFontVariationAxes(axes, library, face); + } + static FT_Face loadFace(FT_Library library, const std::string & filename, std::string & error){ FT_Face face = NULL; @@ -291,10 +317,16 @@ class Font { uploadBuffers(); } - void prepareGlyphsForText(const std::string & text){ + void prepareGlyphsForText(const std::string & text, bool forceChange = false){ // TODO: do not duplicate glyphs bool changed = false; + if(forceChange){ + bufferGlyphs.clear(); + bufferCurves.clear(); + glyphs.clear(); + } + for(const char * textIt = text.c_str(); *textIt != '\0';){ uint32_t charcode = decodeCharcode(&textIt); @@ -328,9 +360,6 @@ class Font { // dynamic, the buffers could be overallocated and only the added // data could be uploaded. uploadBuffers(); - //cout << "glyphs changed" << endl; - }else{ - //cout << "glyphs not changed" << endl; } } diff --git a/example/src/ofApp.cpp b/example/src/ofApp.cpp index 419b831..2aa3aa8 100644 --- a/example/src/ofApp.cpp +++ b/example/src/ofApp.cpp @@ -5,6 +5,7 @@ #include "ofRectangle.h" #include "ofTexture.h" #include "ofUtils.h" +#include #ifdef TARGET_EMSCRIPTEN #include @@ -36,9 +37,9 @@ bla bla bla void ofApp::setup(){ mainText_full = "A"; mainText = R"DONE(abcdefghijklmnopqrstuvqxyz -ABCDEFGHIJKLMNOP)DONE"; -//QRSTUVWXYZ -//0123456789",.!@#$%^&*()_+=-[]{})DONE"; +ABCDEFGHIJKLMNOPQRSTUVWXYZ +0123456789",.!@#$%^&*()_+=-[]{})DONE"; + mainText = "something is a sentence if words are being concerning which"; mainText_full = R"DONE(Some things are hard to write about. Take soil, for instance. Soil, Oxford dictionary reads, “is the upper layer of earth in which plants grow, a black or @@ -106,6 +107,15 @@ start. I hope to capture something essential.)DONE"; font, bb); + font->listFontVariationAxes(fontVariationAxesParameters, library); + cout << currentFontPath << " : 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(); @@ -135,7 +145,20 @@ start. I hope to capture something essential.)DONE"; //-------------------------------------------------------------- void ofApp::update(){ - + float animationSpeed = ofMap(sin(ofGetElapsedTimef() * 0.01), -1, 1, 0.0, 2); + float threshold = 5.0; + for(int i = 0; i < fontVariationAxes.size(); i++){ + Font::FontVariationAxis & axis = fontVariationAxes[i]; + 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); + } + } } //-------------------------------------------------------------- diff --git a/example/src/ofApp.h b/example/src/ofApp.h index 3319e5e..785fab8 100644 --- a/example/src/ofApp.h +++ b/example/src/ofApp.h @@ -89,6 +89,7 @@ class ofApp : public ofBaseApp { string currentFontPath; string mainText; string mainText_full; + string mainText_hitch; float helpFontBaseSize = 20.0f; @@ -150,4 +151,8 @@ class ofApp : public ofBaseApp { "data/celines-fonts/tonkaflowers-Regular.otf", "data/celines-fonts/Version-3-var.ttf" }; + + std::vector fontVariationAxesParameters; + std::vector fontVariationAxes; + };