add rudimentary variation animation

This commit is contained in:
jrkb 2023-04-04 11:30:54 +02:00
parent 3be6c9ddb5
commit 2fdec44c3a
3 changed files with 83 additions and 26 deletions

View file

@ -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<FontVariationAxis> &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 <FontVariationAxisParameters> & 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 <FontVariationAxisParameters> & 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;
}
}

View file

@ -5,6 +5,7 @@
#include "ofRectangle.h"
#include "ofTexture.h"
#include "ofUtils.h"
#include <iomanip>
#ifdef TARGET_EMSCRIPTEN
#include <GLES/gl.h>
@ -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);
}
}
}
//--------------------------------------------------------------

View file

@ -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 <Font::FontVariationAxisParameters> fontVariationAxesParameters;
std::vector <Font::FontVariationAxis> fontVariationAxes;
};