make LayerComposition more flexible ... unstable implementation

This commit is contained in:
jrkb 2023-04-06 11:17:22 +02:00
parent 207e2537b1
commit e6a1ecd971
8 changed files with 527 additions and 253 deletions

View file

@ -1,173 +1,3 @@
#include "Layer.h" #include "Layer.h"
#include "conversion.h"
#include "ofAppRunner.h"
#include "ofGraphics.h"
#include "ofUtils.h"
namespace ofxVariableLab { // Layer is virtual
Layer::Layer(){
}
Layer::~Layer(){
}
MsdfLayer::MsdfLayer(){
}
MsdfLayer::~MsdfLayer(){
}
void Layer::update(){
if(isDirty){
isDirty = false;
}
}
void MsdfLayer::draw(glm::vec3 position) const {
const ofImage & atlasImage = atlas->getAtlasImage();
ofDisableAlphaBlending();
ofEnableDepthTest();
float pixelRange = 2;
int atlas_w = atlasImage.getWidth();
int atlas_h = atlasImage.getHeight();
int atlas_x = 0;
int atlas_y = 0;
glm::vec2 unitRange = glm::vec2(pixelRange) / glm::vec2(atlas_w, atlas_h);
shader->begin();
shader->setUniformTexture("msdf", atlasImage.getTexture(), 0);
shader->setUniform4f("fontColor", ofFloatColor::white);
shader->setUniform2f("unitRange", unitRange);
shader->end();
ofPushMatrix();
ofTranslate(position);
ofPushStyle();
ofSetColor(ofColor::pink);
ofDrawLine(glm::vec2(0, 0), glm::vec2(ofGetWidth(), 0));
ofPopStyle();
char previous_c;
bool firstLetter = true;
// set variation axis
const float swing_sin = sin(ofGetElapsedTimef() * 1);
const float swing_01 = ofMap(swing_sin, -1, 1, 0, 1);
const vector <ofxMsdfgen::FontVariationAxis> & variationAxisAvailable = atlas->getVariationAxesAvailable();
const string var_name = variationAxisAvailable[0].name;
const float var_value = ofMap(swing_01, 0, 1,
variationAxisAvailable[0].minValue,
variationAxisAvailable[0].maxValue);
int i = 0;
for(const char c : propsBuffer[0].text){
float mix = -1;
ofxMsdfgen::GlyphGeometry gg_a;
ofxMsdfgen::GlyphGeometry gg_b;
bool success = atlas->getGlyphGeometryPair(c,
{var_name, var_value},
gg_a,
gg_b,
mix);
if(!success){
ofLogError("MsdfLayer::draw") << "could not get glyphGeometryPair" << endl;
}
int x_a, y_a, w_a, h_a;
int x_b, y_b, w_b, h_b;
gg_a.getBoxRect(x_a, y_a, w_a, h_a);
gg_b.getBoxRect(x_b, y_b, w_b, h_b);
if(y_a < 0 || y_b < 0){
// FIXME: make sure this does not happen
ofLogError("MsdfLayer::draw") << "y smaller 0, this is not good" << endl;
}
ofPushStyle();
double pl_a, pb_a, pr_a, pt_a;
double pl_b, pb_b, pr_b, pt_b;
gg_a.getQuadPlaneBounds(pl_a, pb_a, pr_a, pt_a);
gg_b.getQuadPlaneBounds(pl_b, pb_b, pr_b, pt_b);
double advance_a = gg_a.getAdvance();
double advance_b = gg_b.getAdvance();
float x = glm::mix(float(x_a), float(x_b), mix);
float y = glm::mix(float(y_a), float(y_b), mix);
float w = glm::mix(float(w_a), float(w_b), mix);
float h = glm::mix(float(h_a), float(h_b), mix);
float pl = glm::mix(float(pl_a), float(pl_b), mix);
//float pb = glm::mix(float(pb_a), float(pb_b), mix);
//float pr = glm::mix(float(pr_a), float(pr_b), mix);
float pt = glm::mix(float(pt_a), float(pt_b), mix);
double advance = glm::mix(advance_a, advance_b, mix);
ofPushMatrix();
float magic = atlas->settings.scale;
ofSetColor(ofFloatColor(1, 1, 1, 1));
ofTranslate(pl * magic, 0, 0);
ofTranslate(0, -1 * pt * magic, 0);
//msdf_atlas::unicode_t a = static_cast <msdf_atlas::unicode_t>(previous_c);
//msdf_atlas::unicode_t b = static_cast <msdf_atlas::unicode_t>(c);
if(!firstLetter){
//cout << "this is being printed" << endl;
auto & fontGeometry = atlas->getFontGeometry();
const std::map <std::pair <int, int>, double> kerning = fontGeometry.getKerning();
ofxMsdfgen::GlyphGeometry gg_previous = atlas->getGlyphGeometry(c);
std::map <std::pair <int, int>, double>::const_iterator it = kerning.find(std::make_pair <int, int>(gg_previous.getIndex(), gg_a.getIndex()));
if(it != kerning.end()){
advance += it->second;
ofDrawBitmapStringHighlight(ofToString(it->second), 0, 200, ofColor::black, ofColor::pink);
}
}
glm::vec2 translation_a = glm::vec2(float(x_a) / float(atlas_w),
float(y_a) / float(atlas_h));
glm::vec2 scale_a = glm::vec2(float(w_a) / float(atlas_w),
float(h_a) / float(atlas_h));
glm::vec2 translation_b = glm::vec2(float(x_b) / float(atlas_w),
float(y_b) / float(atlas_h));
glm::vec2 scale_b = glm::vec2(float(w_b) / float(atlas_w),
float(h_b) / float(atlas_h));
//if(firstLetter){
//cout << "translation_a: " << ofToString(translation_a) << endl;
//cout << "scale_a: " << ofToString(scale_a) << endl;
//}
shader->begin();
shader->setUniform4f("fontColor", ofFloatColor::yellow);
shader->setUniform2f("translation_a", translation_a);
shader->setUniform2f("scale_a", scale_a);
shader->setUniform2f("translation_b", translation_b);
shader->setUniform2f("scale_b", scale_b);
shader->setUniform1f("msdf_mix", mix);
atlasImage.draw(0, 0, w, h);
shader->end();
ofPopMatrix();
ofPopStyle();
ofTranslate(advance * magic, 0, 0);
ofTranslate(-1 * pl * magic, 0, 0);
previous_c = c;
if(firstLetter){
firstLetter = false;
}
i++;
}
ofPopMatrix();
ofDisableDepthTest();
ofEnableAlphaBlending();
}
void Layer::setProps(const Props & props){
while(propsBuffer.size() > max(0, int(settings.maxBufferSize - 1))){
propsBuffer.pop_back();
}
propsBuffer.push_front(props);
}
const Layer::Props & Layer::getProps() const {
return propsBuffer[0];
}
void Layer::clearPropsBuffer(){
propsBuffer.clear();
}
void Layer::setId(const string & id){
this->id = id;
}
const string & Layer::getId(){
return id;
}
}

View file

@ -1,25 +1,20 @@
#pragma once #pragma once
#include "Atlas.h"
#include "ofMain.h" #include "ofMain.h"
//uuid //uuid
#include "random_id.h" #include "random_id.h"
#include "ofxMsdfgen.h" #include "ofxMsdfgen.h"
#include <memory>
namespace ofxVariableLab { namespace ofxVariableLab {
class Layer { class Layer {
protected:
Layer();
public: public:
~Layer(); enum Type {
enum TransformOrigin { MSDFGEN = 0,
TOP_LEFT, GPUFONT
TOP_RIGHT,
CENTER,
BOTTOM_LEFT,
BOTTOM_RIGHT
}; };
struct Props { struct Props {
float x = 0; float x = 0;
@ -27,54 +22,31 @@ class Layer {
float rotation = 0; float rotation = 0;
float fontSize_px = 24; float fontSize_px = 24;
float * color[4]; float * color[4];
TransformOrigin transformOrigin = TransformOrigin::CENTER;
bool mirror_x = false; bool mirror_x = false;
float mirror_x_distance = 0; float mirror_x_distance = 0;
bool mirror_y = false; bool mirror_y = false;
float mirror_y_distance = 0; float mirror_y_distance = 0;
float letterDelay = 0; float letterDelay = 0;
string text = "Variable Font Editor"; string text = "abcdefghijklmnoprstuvqxyzABUIWERJSD";
}; };
struct Settings { struct Settings {
uint32_t maxBufferSize = 100; uint32_t maxBufferSize = 100;
}; };
void update(); virtual void setup(const Settings & settings) = 0;
virtual void update() = 0;
virtual void draw(glm::vec3 position = glm::vec3(0, 0, 0)) const = 0; virtual void draw(glm::vec3 position = glm::vec3(0, 0, 0)) const = 0;
void setProps(const Props & props); virtual void drawCharacter(const char character,
const Props & getProps() const; glm::vec3 position = glm::vec3(0, 0, 0),
//void setProps(float _x, ofxMsdfgen::FontVariation fontVariation = ofxMsdfgen::FontVariation()) const = 0;
//float _y, virtual void setProps(const Props & props) = 0;
//float _rotation, virtual const Props & getProps() const = 0;
//float _wght, virtual void clearPropsBuffer() = 0;
//float _fontSize_px, virtual void setId(const string & id) = 0;
//float * _color[4], virtual const string & getId() = 0;
//int _transformOrigin, virtual void setShader(shared_ptr <ofShader> _shader) = 0;
//bool _mirror_x, virtual shared_ptr <ofShader> getShader() const = 0;
//float _mirror_x_distance, virtual const Type & getType() const = 0;
//bool _mirror_y,
//float _mirror_y_distance,
//float _letterDelay,
//string _text);
void clearPropsBuffer();
void setId(const string & id);
const string & getId();
Settings settings;
std::deque <Props> propsBuffer;
shared_ptr <ofShader> shader;
/// \brief are props updated but not drawn yet
bool isDirty = true;
/// \brief hashed id
string id;
};
class MsdfLayer : public Layer {
public:
MsdfLayer();
~MsdfLayer();
void draw(glm::vec3 position = glm::vec3(0, 0, 0)) const override;
shared_ptr <ofxMsdfgen::Atlas> atlas;
}; };
} }

View file

@ -1,18 +1,26 @@
#include "LayerComposition.h" #include "LayerComposition.h"
#include "Atlas.h"
#include "MsdfLayer.h"
#include "ofUtils.h" #include "ofUtils.h"
#include <memory> #include <memory>
namespace ofxVariableLab { namespace ofxVariableLab {
void LayerComposition::setup(){ void MsdfAtlasLayerCombo::setup(const ComboIdentifier & layerIdentifier){
ofxMsdfgen::AtlasSettings settings; this->identifier = layerIdentifier;
ofxMsdfgen::AtlasSettings atlasSettings;
//settings.characters = "ABCDEFGHIJKL"; //settings.characters = "ABCDEFGHIJKL";
settings.scale = 64; atlasSettings.scale = 64;
settings.characters = ""; atlasSettings.minimumScale = 64;
atlasSettings.characters = "";
//string fontName = "RobotoFlex.ttf"; //string fontName = "RobotoFlex.ttf";
//string fontPath = "data/fonts/" + fontName; //string fontPath = "data/fonts/" + fontName;
//string fontPath = "data/celines-fonts/testing2VF.ttf"; //string fontPath = "data/celines-fonts/testing2VF.ttf";
string fontPath = "data/celines-fonts/Version-2-var.ttf"; string fontPath = "data/celines-fonts/Version-2-var.ttf";
//string fontPath = "data/celines-fonts/Version-2-var.ttf";
//string fontPath = "data/celines-fonts/Version-3-var.ttf";
//string fontPath = "data/celines-fonts/Version-4-var.ttf";
//string fontPath = "data/celines-fonts/Alfarn2.otf"; //string fontPath = "data/celines-fonts/Alfarn2.otf";
//string fontPath = "data/celines-fonts/Cottagecore.ttf"; //string fontPath = "data/celines-fonts/Cottagecore.ttf";
atlas = make_shared <ofxMsdfgen::Atlas>(); atlas = make_shared <ofxMsdfgen::Atlas>();
@ -24,33 +32,92 @@ void LayerComposition::setup(){
msdfShader->load("ofxMsdfgen/shaders/mix/GL3/shader"); msdfShader->load("ofxMsdfgen/shaders/mix/GL3/shader");
#endif #endif
auto layer = make_unique <ofxVariableLab::MsdfLayer>(); atlas->setup(fontPath, atlasSettings);
layer->atlas = atlas; }
layer->shader = msdfShader;
layer->setProps(Layer::Props()); void MsdfAtlasLayerCombo::update(){
if(isDirty){
settings.characters += layer->getProps().text;
layers.push_back(std::move(layer));
atlas->setup(fontPath, settings);
atlas->generate(); atlas->generate();
atlasImage = make_shared <ofImage>(atlas->getAtlasImage()); isDirty = false;
glyphGeometries = atlas->getGlyphGeometries();
}
void LayerComposition::update(){
}
void LayerComposition::draw() const {
for(const auto & layer : layers){
layer->draw(glm::vec3(400, 200, 0));
} }
} }
shared_ptr <ofImage> LayerComposition::getAtlasImage(){ void MsdfAtlasLayerCombo::careForChild(shared_ptr <Layer> layer){
return atlasImage; shared_ptr <MsdfLayer> msdfLayer = dynamic_pointer_cast <MsdfLayer>(layer);
msdfLayer->setAtlas(this->atlas);
msdfLayer->setShader(msdfShader);
auto & as = atlas->settings;
for(const char c : layer->getProps().text){
if(as.characters.find(c) == std::string::npos){
// not found
as.characters += c;
isDirty = true;
}
}
}
const ComboIdentifier & MsdfAtlasLayerCombo::getIdentifier() const {
return identifier;
}
void LayerComposition::setup(){
}
void LayerComposition::update(){
for(const auto & atlasLayerCombo : atlasLayerCombos){
atlasLayerCombo.second->update();
}
}
void LayerComposition::addLayer(const ComboIdentifier & identifier,
const string & text,
const std::vector <FontVariation> & variations){
if(atlasLayerCombos.count(identifier) <= 0){
switch(identifier.type){
case Layer::GPUFONT: {
ofLogError("LayerComposition::addLayer")
<< "GPUFont not implemented" << endl;
break;
}
default:
case Layer::MSDFGEN: {
// TODO: put most stuff in combo setup
auto combo = make_shared <MsdfAtlasLayerCombo>();
combo->setup(identifier); // TODO: add here text and variations
auto layer = make_shared <MsdfLayer>();
auto props = Layer::Props();
props.text = text;
layer->setProps(props);
ofxMsdfgen::AtlasSettings as;
as.characters = "";
//for(const char c : text){
//if(as.characters.find(c) == std::string::npos){
//// not found
//as.characters += c;
//}
//}
combo->atlas->setup(identifier.fontPath, as);
std::vector <ofxMsdfgen::FontVariation> msdfVariations;
for(const auto & v : variations){
msdfVariations.push_back({v.name, v.value});
}
// TODO: do not add Variation to atlas, but to combo,
// so we know it's dirty
combo->atlas->addVariations(msdfVariations);
combo->careForChild(layer);
layers.push_back(layer);
atlasLayerCombos[identifier] = std::move(combo);
break;
}
}
}
}
void LayerComposition::draw() const {
for(const auto & layer_it : layers){
layer_it->draw(glm::vec3(0, 0, 0));
}
} }
} }

View file

@ -1,29 +1,98 @@
#pragma once #pragma once
#include "Utils.h"
#include "ofMain.h" #include "ofMain.h"
#include "ofxMsdfgen.h" #include "ofxMsdfgen.h"
#include "Layer.h" #include "Layer.h"
#include "MsdfLayer.h"
#include "Utils.h"
#include <type_traits>
#include <unordered_map> #include <unordered_map>
namespace ofxVariableLab { namespace ofxVariableLab {
struct ComboIdentifier {
std::string fontPath = "data/celines-fonts/Version-2-var.ttf";
Layer::Type type = Layer::MSDFGEN;
bool operator==(const ComboIdentifier & other) const {
return (this->fontPath == other.fontPath
&& this->type == other.type);
}
};
class AtlasLayerCombo {
public:
virtual void setup(const ComboIdentifier & identifier) = 0;
virtual void update() = 0;
virtual void careForChild(shared_ptr <Layer> layer) = 0;
virtual const ComboIdentifier & getIdentifier() const = 0;
bool operator==(const AtlasLayerCombo & other) const {
return (this->getIdentifier() == other.getIdentifier());
}
};
}
namespace std {
template <>
struct hash <ofxVariableLab::ComboIdentifier> {
std::size_t operator()(const ofxVariableLab::ComboIdentifier & k) const {
using std::size_t;
using std::hash;
using std::string;
size_t seed = 0;
ofxVariableLab::hash_combine(seed, k.fontPath);
ofxVariableLab::hash_combine(seed, k.type);
return seed;
}
};
template <>
struct hash <ofxVariableLab::AtlasLayerCombo> {
std::size_t operator()(const ofxVariableLab::AtlasLayerCombo & k) const {
using std::size_t;
using std::hash;
using std::string;
size_t seed = 0;
ofxVariableLab::hash_combine(seed, k.getIdentifier());
return seed;
}
};
}
namespace ofxVariableLab {
class MsdfAtlasLayerCombo : public AtlasLayerCombo {
public:
void setup(const ComboIdentifier & identifier) override;
void update() override;
void careForChild(shared_ptr <Layer> layer) override;
const ComboIdentifier & getIdentifier() const override;
shared_ptr <ofxMsdfgen::Atlas> atlas;
private:
vector <ofxMsdfgen::GlyphGeometry> glyphGeometries;
shared_ptr <ofShader> msdfShader;
ComboIdentifier identifier;
bool isDirty = false;
};
class LayerComposition { class LayerComposition {
public: public:
void setup(); void setup();
void update(); void update();
void draw() const; void draw() const;
shared_ptr <ofImage> getAtlasImage(); void addLayer(const ComboIdentifier & identifier,
#ifdef TARGET_EMSCRIPTEN const string & text,
#else const std::vector <FontVariation> & variations);
#endif
private: private:
shared_ptr <ofxMsdfgen::Atlas> atlas;
shared_ptr <ofImage> atlasImage;
vector <ofxMsdfgen::GlyphGeometry> glyphGeometries;
shared_ptr <ofShader> msdfShader;
vector <unique_ptr <ofxVariableLab::Layer> > layers; vector <shared_ptr <ofxVariableLab::Layer> > layers;
unordered_map <ComboIdentifier, shared_ptr <AtlasLayerCombo> > atlasLayerCombos;
//unordered_map <LayerIdentifier, shared_ptr <ofxVariableLab::Layer> > layers;
}; };
} }

266
src/MsdfLayer.cpp Normal file
View file

@ -0,0 +1,266 @@
#include "MsdfLayer.h"
namespace ofxVariableLab {
void MsdfLayer::setup(const Settings & settings){
this->settings = settings;
}
void MsdfLayer::update(){
if(isDirty){
isDirty = false;
}
}
void MsdfLayer::draw(glm::vec3 position) const {
const ofImage & atlasImage = atlas->getAtlasImage();
ofDisableAlphaBlending();
ofEnableDepthTest();
float pixelRange = 2;
int atlas_w = atlasImage.getWidth();
int atlas_h = atlasImage.getHeight();
glm::vec2 unitRange = glm::vec2(pixelRange) / glm::vec2(atlas_w, atlas_h);
shader->begin();
shader->setUniformTexture("msdf", atlasImage.getTexture(), 0);
shader->setUniform4f("fontColor", ofFloatColor::white);
shader->setUniform2f("unitRange", unitRange);
shader->end();
ofPushMatrix();
ofTranslate(position);
ofPushStyle();
ofSetColor(ofColor::pink);
ofDrawLine(glm::vec2(0, 0), glm::vec2(ofGetWidth(), 0));
ofPopStyle();
char previous_c;
bool firstLetter = true;
// set variation axis
const float swing_sin = sin(ofGetElapsedTimef() * 1);
const float swing_01 = ofMap(swing_sin, -1, 1, 0, 1);
const vector <ofxMsdfgen::FontVariationAxis> & variationAxisAvailable = atlas->getVariationAxesAvailable();
const string var_name = variationAxisAvailable[0].name;
const float var_value = ofMap(swing_01, 0, 1,
variationAxisAvailable[0].minValue,
variationAxisAvailable[0].maxValue);
int i = 0;
for(const char c : propsBuffer[0].text){
float mix = -1;
ofxMsdfgen::GlyphGeometry gg_a;
ofxMsdfgen::GlyphGeometry gg_b;
bool success = atlas->getGlyphGeometryPair(c,
{var_name, var_value},
gg_a,
gg_b,
mix);
if(!success){
ofLogError("MsdfLayer::draw") << "could not get glyphGeometryPair" << endl;
}
int x_a, y_a, w_a, h_a;
int x_b, y_b, w_b, h_b;
gg_a.getBoxRect(x_a, y_a, w_a, h_a);
gg_b.getBoxRect(x_b, y_b, w_b, h_b);
if(y_a < 0 || y_b < 0){
// FIXME: make sure this does not happen
ofLogError("MsdfLayer::draw") << "y smaller 0, this is not good" << endl;
}
ofPushStyle();
double pl_a, pb_a, pr_a, pt_a;
double pl_b, pb_b, pr_b, pt_b;
gg_a.getQuadPlaneBounds(pl_a, pb_a, pr_a, pt_a);
gg_b.getQuadPlaneBounds(pl_b, pb_b, pr_b, pt_b);
double advance_a = gg_a.getAdvance();
double advance_b = gg_b.getAdvance();
float w = glm::mix(float(w_a), float(w_b), mix);
float h = glm::mix(float(h_a), float(h_b), mix);
float pl = glm::mix(float(pl_a), float(pl_b), mix);
//float pb = glm::mix(float(pb_a), float(pb_b), mix);
//float pr = glm::mix(float(pr_a), float(pr_b), mix);
float pt = glm::mix(float(pt_a), float(pt_b), mix);
double advance = glm::mix(advance_a, advance_b, mix);
ofPushMatrix();
float magic = atlas->settings.scale;
cout << "magic number << " << magic << endl;
ofSetColor(ofFloatColor(1, 1, 1, 1));
ofTranslate(pl * magic, 0, 0);
//ofTranslate(0, -1 * pt * magic, 0);
ofTranslate(0, 1 * pt * magic, 0);
if(!firstLetter){
//cout << "this is being printed" << endl;
auto & fontGeometry = atlas->getFontGeometry();
const std::map <std::pair <int, int>, double> kerning = fontGeometry.getKerning();
ofxMsdfgen::GlyphGeometry gg_previous = atlas->getGlyphGeometry(c);
std::map <std::pair <int, int>, double>::const_iterator it = kerning.find(std::make_pair <int, int>(gg_previous.getIndex(), gg_a.getIndex()));
if(it != kerning.end()){
advance += it->second;
ofDrawBitmapStringHighlight(ofToString(it->second), 0, 200, ofColor::black, ofColor::pink);
}
}
glm::vec2 translation_a = glm::vec2(float(x_a) / float(atlas_w),
float(y_a) / float(atlas_h));
glm::vec2 scale_a = glm::vec2(float(w_a) / float(atlas_w),
float(h_a) / float(atlas_h));
glm::vec2 translation_b = glm::vec2(float(x_b) / float(atlas_w),
float(y_b) / float(atlas_h));
glm::vec2 scale_b = glm::vec2(float(w_b) / float(atlas_w),
float(h_b) / float(atlas_h));
//if(firstLetter){
//cout << "translation_a: " << ofToString(translation_a) << endl;
//cout << "scale_a: " << ofToString(scale_a) << endl;
//}
shader->begin();
shader->setUniform4f("fontColor", ofFloatColor::yellow);
shader->setUniform2f("translation_a", translation_a);
shader->setUniform2f("scale_a", scale_a);
shader->setUniform2f("translation_b", translation_b);
shader->setUniform2f("scale_b", scale_b);
shader->setUniform1f("msdf_mix", mix);
atlasImage.draw(0, 0, w, h);
shader->end();
ofPopMatrix();
ofPopStyle();
ofTranslate(advance * magic, 0, 0);
ofTranslate(-1 * pl * magic, 0, 0);
previous_c = c;
if(firstLetter){
firstLetter = false;
}
i++;
}
ofPopMatrix();
ofDisableDepthTest();
ofEnableAlphaBlending();
}
void MsdfLayer::drawCharacter(const char character,
glm::vec3 position,
ofxMsdfgen::FontVariation fontVariation) const {
const ofImage & atlasImage = atlas->getAtlasImage();
ofDisableAlphaBlending();
ofEnableDepthTest();
float pixelRange = 2;
int atlas_w = atlasImage.getWidth();
int atlas_h = atlasImage.getHeight();
glm::vec2 unitRange = glm::vec2(pixelRange) / glm::vec2(atlas_w, atlas_h);
shader->begin();
shader->setUniformTexture("msdf", atlasImage.getTexture(), 0);
shader->setUniform4f("fontColor", ofFloatColor::white);
shader->setUniform2f("unitRange", unitRange);
shader->end();
ofPushMatrix();
ofTranslate(position);
ofPushStyle();
ofSetColor(ofColor::pink);
float mix = -1;
ofxMsdfgen::GlyphGeometry gg_a;
ofxMsdfgen::GlyphGeometry gg_b;
bool success = atlas->getGlyphGeometryPair(character,
fontVariation,
gg_a,
gg_b,
mix);
if(!success){
ofLogError("MsdfLayer::draw") << "could not get glyphGeometryPair" << endl;
}
int x_a, y_a, w_a, h_a;
int x_b, y_b, w_b, h_b;
gg_a.getBoxRect(x_a, y_a, w_a, h_a);
gg_b.getBoxRect(x_b, y_b, w_b, h_b);
if(y_a < 0 || y_b < 0){
// FIXME: make sure this does not happen
ofLogError("MsdfLayer::draw") << "y smaller 0, this is not good" << endl;
}
ofPushStyle();
double pl_a, pb_a, pr_a, pt_a;
double pl_b, pb_b, pr_b, pt_b;
gg_a.getQuadPlaneBounds(pl_a, pb_a, pr_a, pt_a);
gg_b.getQuadPlaneBounds(pl_b, pb_b, pr_b, pt_b);
double advance_a = gg_a.getAdvance();
double advance_b = gg_b.getAdvance();
float w = glm::mix(float(w_a), float(w_b), mix);
float h = glm::mix(float(h_a), float(h_b), mix);
float pl = glm::mix(float(pl_a), float(pl_b), mix);
float pt = glm::mix(float(pt_a), float(pt_b), mix);
double advance = glm::mix(advance_a, advance_b, mix);
ofPushMatrix();
float magic = atlas->settings.scale;
ofSetColor(ofFloatColor(1, 1, 1, 1));
ofTranslate(pl * magic, 0, 0);
ofTranslate(0, -1 * pt * magic, 0);
glm::vec2 translation_a = glm::vec2(float(x_a) / float(atlas_w),
float(y_a) / float(atlas_h));
glm::vec2 scale_a = glm::vec2(float(w_a) / float(atlas_w),
float(h_a) / float(atlas_h));
glm::vec2 translation_b = glm::vec2(float(x_b) / float(atlas_w),
float(y_b) / float(atlas_h));
glm::vec2 scale_b = glm::vec2(float(w_b) / float(atlas_w),
float(h_b) / float(atlas_h));
shader->begin();
shader->setUniform4f("fontColor", ofFloatColor::yellow);
shader->setUniform2f("translation_a", translation_a);
shader->setUniform2f("scale_a", scale_a);
shader->setUniform2f("translation_b", translation_b);
shader->setUniform2f("scale_b", scale_b);
shader->setUniform1f("msdf_mix", mix);
atlasImage.draw(0, 0, w, h);
shader->end();
ofPopMatrix();
ofPopStyle();
ofTranslate(advance * magic, 0, 0);
ofTranslate(-1 * pl * magic, 0, 0);
ofPopStyle();
ofPopMatrix();
ofDisableDepthTest();
ofEnableAlphaBlending();
}
void MsdfLayer::setShader(shared_ptr <ofShader> _shader){
shader = _shader;
}
shared_ptr <ofShader> MsdfLayer::getShader() const {
return shader;
}
const Layer::Type & MsdfLayer::getType() const {
return type;
}
void MsdfLayer::setAtlas(shared_ptr <ofxMsdfgen::Atlas> _atlas){
atlas = _atlas;
}
shared_ptr <ofxMsdfgen::Atlas> MsdfLayer::getAtlas() const {
return atlas;
}
void MsdfLayer::setProps(const Props & props){
while(propsBuffer.size() > max(0, int(settings.maxBufferSize - 1))){
propsBuffer.pop_back();
}
propsBuffer.push_front(props);
}
const Layer::Props & MsdfLayer::getProps() const {
return propsBuffer[0];
}
void MsdfLayer::clearPropsBuffer(){
propsBuffer.clear();
}
void MsdfLayer::setId(const string & id){
this->id = id;
}
const string & MsdfLayer::getId(){
return id;
}
}

43
src/MsdfLayer.h Normal file
View file

@ -0,0 +1,43 @@
#pragma once
#include "ofMain.h"
#include "ofxMsdfgen.h"
#include "Atlas.h"
#include "Layer.h"
namespace ofxVariableLab {
class MsdfLayer : public Layer {
public:
void setup(const Settings & settings);
void update() override;
void draw(glm::vec3 position = glm::vec3(0, 0, 0)) const override;
void drawCharacter(const char character,
glm::vec3 position = glm::vec3(0, 0, 0),
ofxMsdfgen::FontVariation fontVariation = ofxMsdfgen::FontVariation()) const override;
void setProps(const Props & props) override;
const Props & getProps() const override;
void clearPropsBuffer() override;
void setId(const string & id) override;
const string & getId() override;
void setShader(shared_ptr <ofShader> _shader) override;
shared_ptr <ofShader> getShader() const override;
const Type & getType() const override;
void setAtlas(shared_ptr <ofxMsdfgen::Atlas> _atlas);
shared_ptr <ofxMsdfgen::Atlas> getAtlas() const;
shared_ptr <ofxMsdfgen::Atlas> atlas;
Settings settings;
std::deque <Props> propsBuffer;
shared_ptr <ofShader> shader;
/// \brief are props updated but not drawn yet
bool isDirty = true;
/// \brief hashed id
string id;
private:
Layer::Type type = MSDFGEN;
};
}

25
src/Utils.h Normal file
View file

@ -0,0 +1,25 @@
#pragma once
#include <string>
namespace ofxVariableLab {
struct FontVariationAxis {
char * name;
float minValue;
float maxValue;
float defaultValue;
};
struct FontVariation {
char * name;
float value;
};
template <class T>
inline void hash_combine(std::size_t & seed, const T & v){
std::hash <T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
}

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "random_id.h" #include "random_id.h"
#include "Utils.h"
#include "Layer.h" #include "Layer.h"
#include "MsdfLayer.h"
#include "LayerComposition.h" #include "LayerComposition.h"