fix wrapping, and textAlignment
This commit is contained in:
parent
73d17b2a03
commit
172711cad3
11 changed files with 302 additions and 97 deletions
|
@ -255,14 +255,6 @@ void GPUFontAtlasLayerCombo::draw(int width, int height){
|
||||||
bb.p2.y = max_y;
|
bb.p2.y = max_y;
|
||||||
bb.p3.x = min_x;
|
bb.p3.x = min_x;
|
||||||
bb.p3.y = max_y;
|
bb.p3.y = max_y;
|
||||||
|
|
||||||
if(ofGetFrameNum() % 600 == 0){
|
|
||||||
cout
|
|
||||||
<< "n_wraps: " << ofToString(n_wraps) << endl
|
|
||||||
<< "layer->getProps().width: " << ofToString(layer->getProps().width) << endl
|
|
||||||
;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
glm::vec4 transformOrigin;
|
glm::vec4 transformOrigin;
|
||||||
getAndApplyTransformOrigin(transformOrigin,
|
getAndApplyTransformOrigin(transformOrigin,
|
||||||
|
@ -373,11 +365,33 @@ void GPUFontAtlasLayerCombo::draw(int width, int height){
|
||||||
min_y = min(min_y, min(mbb.p0.y, min(mbb.p1.y, min(mbb.p2.y, mbb.p3.y))));
|
min_y = min(min_y, min(mbb.p0.y, min(mbb.p1.y, min(mbb.p2.y, mbb.p3.y))));
|
||||||
max_y = max(max_y, max(mbb.p0.y, max(mbb.p1.y, max(mbb.p2.y, mbb.p3.y))));
|
max_y = max(max_y, max(mbb.p0.y, max(mbb.p1.y, max(mbb.p2.y, mbb.p3.y))));
|
||||||
}
|
}
|
||||||
float width = max_x - min_x;
|
float layerWidth = max_x - min_x;
|
||||||
float height = max_y - min_y;
|
float layerHeight = max_y - min_y;
|
||||||
layer->setBoundingBox(Layer::BoundingBox{min_x, min_y, width, height});
|
layer->setBoundingBox(Layer::BoundingBox{min_x, min_y, layerWidth, layerHeight});
|
||||||
|
|
||||||
r = ofRectangle(layer->getProps().x, layer->getProps().y, layer->getProps().width, 800);
|
r = ofRectangle(layer->getProps().x, layer->getProps().y, layer->getProps().width, 800);
|
||||||
|
|
||||||
|
// culling
|
||||||
|
deque <int> removeMe;
|
||||||
|
for(int index : indices){
|
||||||
|
const auto & v0 = vertices[index * 4];
|
||||||
|
const auto & v1 = vertices[index * 4 + 1];
|
||||||
|
const auto & v2 = vertices[index * 4 + 2];
|
||||||
|
const auto & v3 = vertices[index * 4 + 3];
|
||||||
|
if(!isInside(v0.x, v0.y, 0, 0, float(width), float(height))
|
||||||
|
&& !isInside(v1.x, v1.y, 0, 0, float(width), float(height))
|
||||||
|
&& !isInside(v2.x, v2.y, 0, 0, float(width), float(height))
|
||||||
|
&& !isInside(v3.x, v3.y, 0, 0, float(width), float(height))){
|
||||||
|
removeMe.push_front(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int index : removeMe){
|
||||||
|
indices.erase(indices.begin() + index);
|
||||||
|
vertices.erase(vertices.begin() + (index * 4));
|
||||||
|
vertices.erase(vertices.begin() + (index * 4) + 1);
|
||||||
|
vertices.erase(vertices.begin() + (index * 4) + 2);
|
||||||
|
vertices.erase(vertices.begin() + (index * 4) + 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -425,16 +439,11 @@ void GPUFontAtlasLayerCombo::draw(int width,
|
||||||
glm::mat4 view = transform.getViewMatrix();
|
glm::mat4 view = transform.getViewMatrix();
|
||||||
glm::mat4 model = glm::mat4(1.0f);
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
|
||||||
//glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // background color
|
|
||||||
//glClear(GL_COLOR_BUFFER_BIT); // clear background with background color
|
|
||||||
|
|
||||||
// Uses premultiplied-alpha.
|
// Uses premultiplied-alpha.
|
||||||
ofDisableDepthTest();
|
ofDisableDepthTest();
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
//glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
|
||||||
//ofEnableAlphaBlending();
|
|
||||||
|
|
||||||
int currentProgram;
|
int currentProgram;
|
||||||
glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram);
|
glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram);
|
||||||
|
@ -491,16 +500,13 @@ void GPUFontAtlasLayerCombo::draw(int width,
|
||||||
true, layer->getProps().fontSize_px,
|
true, layer->getProps().fontSize_px,
|
||||||
layer->getProps().lineHeight);
|
layer->getProps().lineHeight);
|
||||||
float lineHeight = font->getLineHeight(layer->getProps().fontSize_px) * layer->getProps().lineHeight;
|
float lineHeight = font->getLineHeight(layer->getProps().fontSize_px) * layer->getProps().lineHeight;
|
||||||
if(layer->getProps().width > 0){
|
|
||||||
int n_wraps = wrapBoundingBoxes(bbs,
|
int n_wraps = wrapBoundingBoxes(bbs,
|
||||||
layer->getVariationText(),
|
layer->getVariationText(),
|
||||||
layer->getProps().width,
|
layer->getProps().width,
|
||||||
lineHeight);
|
lineHeight,
|
||||||
// could be optimized by:
|
layer->getProps().textAlignment);
|
||||||
// - min_x = bbs[0].p0.x
|
//if(layer->getProps().width > 0){
|
||||||
// - max_x = min_x + layer->getProps().width
|
{
|
||||||
// - min_y = bbs[0].p0.y
|
|
||||||
// - max_y = lineHeight * (n_wraps + 1)
|
|
||||||
float min_x = FLT_MAX;
|
float min_x = FLT_MAX;
|
||||||
float min_y = FLT_MAX;
|
float min_y = FLT_MAX;
|
||||||
float max_x = -FLT_MAX;
|
float max_x = -FLT_MAX;
|
||||||
|
@ -519,14 +525,6 @@ void GPUFontAtlasLayerCombo::draw(int width,
|
||||||
bb.p2.y = max_y;
|
bb.p2.y = max_y;
|
||||||
bb.p3.x = min_x;
|
bb.p3.x = min_x;
|
||||||
bb.p3.y = max_y;
|
bb.p3.y = max_y;
|
||||||
|
|
||||||
if(ofGetFrameNum() % 600 == 0){
|
|
||||||
cout
|
|
||||||
<< "n_wraps: " << ofToString(n_wraps) << endl
|
|
||||||
<< "layer->getProps().width: " << ofToString(layer->getProps().width) << endl
|
|
||||||
;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
glm::vec4 transformOrigin;
|
glm::vec4 transformOrigin;
|
||||||
getAndApplyTransformOrigin(transformOrigin,
|
getAndApplyTransformOrigin(transformOrigin,
|
||||||
|
@ -637,13 +635,42 @@ void GPUFontAtlasLayerCombo::draw(int width,
|
||||||
min_y = min(min_y, min(mbb.p0.y, min(mbb.p1.y, min(mbb.p2.y, mbb.p3.y))));
|
min_y = min(min_y, min(mbb.p0.y, min(mbb.p1.y, min(mbb.p2.y, mbb.p3.y))));
|
||||||
max_y = max(max_y, max(mbb.p0.y, max(mbb.p1.y, max(mbb.p2.y, mbb.p3.y))));
|
max_y = max(max_y, max(mbb.p0.y, max(mbb.p1.y, max(mbb.p2.y, mbb.p3.y))));
|
||||||
}
|
}
|
||||||
float width = max_x - min_x;
|
float layerWidth = max_x - min_x;
|
||||||
float height = max_y - min_y;
|
float layerHeight = max_y - min_y;
|
||||||
layer->setBoundingBox(Layer::BoundingBox{min_x, min_y, width, height});
|
layer->setBoundingBox(Layer::BoundingBox{min_x, min_y, layerWidth, layerHeight});
|
||||||
|
|
||||||
r = ofRectangle(layer->getProps().x, layer->getProps().y, layer->getProps().width, 800);
|
r = ofRectangle(layer->getProps().x, layer->getProps().y, layer->getProps().width, 800);
|
||||||
|
|
||||||
|
//cout << vertices.size() << " / " << indices.size() << endl;
|
||||||
|
// culling
|
||||||
|
//deque <int> removeMe;
|
||||||
|
//for(int index = 0; index < vertices.size() / 4; index++){
|
||||||
|
//const auto & v0 = vertices[index * 4];
|
||||||
|
//const auto & v1 = vertices[index * 4 + 1];
|
||||||
|
//const auto & v2 = vertices[index * 4 + 2];
|
||||||
|
//const auto & v3 = vertices[index * 4 + 3];
|
||||||
|
//if(!isInside(v0.x, v0.y, 0, 0, float(width), float(height))
|
||||||
|
//&& !isInside(v1.x, v1.y, 0, 0, float(width), float(height))
|
||||||
|
//&& !isInside(v2.x, v2.y, 0, 0, float(width), float(height))
|
||||||
|
//&& !isInside(v3.x, v3.y, 0, 0, float(width), float(height))){
|
||||||
|
//removeMe.push_front(index);
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//for(int index : removeMe){
|
||||||
|
//indices.erase(indices.begin() + (index * 6));
|
||||||
|
//indices.erase(indices.begin() + (index * 6) + 1);
|
||||||
|
//indices.erase(indices.begin() + (index * 6) + 2);
|
||||||
|
//indices.erase(indices.begin() + (index * 6) + 3);
|
||||||
|
//indices.erase(indices.begin() + (index * 6) + 4);
|
||||||
|
//indices.erase(indices.begin() + (index * 6) + 5);
|
||||||
|
//vertices.erase(vertices.begin() + (index * 4));
|
||||||
|
//vertices.erase(vertices.begin() + (index * 4) + 1);
|
||||||
|
//vertices.erase(vertices.begin() + (index * 4) + 2);
|
||||||
|
//vertices.erase(vertices.begin() + (index * 4) + 3);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
OFX_PROFILER_SCOPE("font->draw()");
|
OFX_PROFILER_SCOPE("font->draw()");
|
||||||
font->draw(vertices, indices);
|
font->draw(vertices, indices);
|
||||||
|
@ -717,7 +744,8 @@ void GPUFontAtlasLayerCombo::getAndApplyTransformOrigin(glm::vec4 & transformOri
|
||||||
}
|
}
|
||||||
|
|
||||||
case Layer::TransformOrigin::BOTTOM_LEFT: {
|
case Layer::TransformOrigin::BOTTOM_LEFT: {
|
||||||
float moveY = ascender - advanceY;
|
//float moveY = ascender - advanceY;
|
||||||
|
float moveY = (bb.p0.y - bb.p2.y);
|
||||||
node.setPosition(glm::vec3(0,
|
node.setPosition(glm::vec3(0,
|
||||||
moveY,
|
moveY,
|
||||||
0));
|
0));
|
||||||
|
@ -728,7 +756,8 @@ void GPUFontAtlasLayerCombo::getAndApplyTransformOrigin(glm::vec4 & transformOri
|
||||||
}
|
}
|
||||||
|
|
||||||
case Layer::TransformOrigin::BOTTOM_RIGHT: {
|
case Layer::TransformOrigin::BOTTOM_RIGHT: {
|
||||||
float moveY = ascender - (advanceY);
|
//float moveY = ascender - (advanceY);
|
||||||
|
float moveY = (bb.p0.y - bb.p2.y);
|
||||||
float moveX = (bb.p2.x - bb.p0.x);
|
float moveX = (bb.p2.x - bb.p0.x);
|
||||||
node.setPosition(glm::vec3(-moveX,
|
node.setPosition(glm::vec3(-moveX,
|
||||||
moveY,
|
moveY,
|
||||||
|
@ -746,21 +775,32 @@ void GPUFontAtlasLayerCombo::getAndApplyTransformOrigin(glm::vec4 & transformOri
|
||||||
int GPUFontAtlasLayerCombo::wrapBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
int GPUFontAtlasLayerCombo::wrapBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
||||||
const std::vector <ofxGPUFont::GlyphIdentity> & _variationText,
|
const std::vector <ofxGPUFont::GlyphIdentity> & _variationText,
|
||||||
int width,
|
int width,
|
||||||
float advanceY){
|
float advanceY,
|
||||||
|
float textAlignment){
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int vi = 0;
|
int vi = 0;
|
||||||
int wrapIndex = -1;
|
int wrapIndex = -1;
|
||||||
int n_wraps = 0;
|
int n_wraps = 0;
|
||||||
bool firstToBreak = true;
|
|
||||||
float collectedWrapWidth = 0;
|
float collectedWrapWidth = 0;
|
||||||
|
std::vector <int> lineBreaks;
|
||||||
|
std::vector <int> goodCharacters;
|
||||||
|
int lastGoodCharacter = -1;
|
||||||
|
//textAlignment = ofMap(sin(ofGetElapsedTimef()), -1, 1, 0, 1);
|
||||||
|
|
||||||
|
float maxX = 0;
|
||||||
for(ofxGPUFont::Font::BoundingBox & bb : bbs){
|
for(ofxGPUFont::Font::BoundingBox & bb : bbs){
|
||||||
|
// good character means it's a drawable character
|
||||||
bool hasGoodCharacter = false;
|
bool hasGoodCharacter = false;
|
||||||
while(!hasGoodCharacter && vi < variationText.size() - 1){
|
while(!hasGoodCharacter && vi < variationText.size()){
|
||||||
if(variationText[vi].charcode == '\0'
|
if(variationText[vi].charcode == '\0'
|
||||||
|| variationText[vi].charcode == '\r'
|
|| variationText[vi].charcode == '\r'
|
||||||
|| variationText[vi].charcode == '\n'){
|
|| variationText[vi].charcode == '\n'){
|
||||||
|
if(variationText[vi].charcode == '\n'){
|
||||||
|
if(lastGoodCharacter >= 0){
|
||||||
|
lineBreaks.push_back(lastGoodCharacter);
|
||||||
|
}
|
||||||
|
}
|
||||||
wrapIndex = -1;
|
wrapIndex = -1;
|
||||||
collectedWrapWidth = 0;
|
collectedWrapWidth = 0;
|
||||||
vi++;
|
vi++;
|
||||||
|
@ -769,70 +809,62 @@ int GPUFontAtlasLayerCombo::wrapBoundingBoxes(std::vector <ofxGPUFont::Font::Bou
|
||||||
vi++;
|
vi++;
|
||||||
}else{
|
}else{
|
||||||
hasGoodCharacter = true;
|
hasGoodCharacter = true;
|
||||||
|
goodCharacters.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(variationText[vi].charcode == '-'){
|
if(variationText[vi].charcode == '-'){
|
||||||
wrapIndex = i;
|
wrapIndex = i;
|
||||||
}
|
}
|
||||||
//float xxx = bb.p1.x - collectedWrapWidth;
|
const float insideWidth = bb.p1.x - collectedWrapWidth;
|
||||||
//if(ofGetFrameNum() % 600 == 0){
|
bool overhang = (insideWidth / float(width)) > (n_wraps + 1);
|
||||||
//cout << "WRAP INDEX " << char(variationText[vi].charcode) << ":" << ofToString(wrapIndex) << " xxx: " << ofToString(xxx) << " cww: " << ofToString(collectedWrapWidth) << endl;
|
|
||||||
//}
|
if(width > 0 && insideWidth > width){
|
||||||
if(bb.p1.x - collectedWrapWidth > width){
|
|
||||||
if(wrapIndex >= 0){
|
if(wrapIndex >= 0){
|
||||||
if(wrapIndex == i){
|
float wrapWidth = bbs[wrapIndex].p0.x;
|
||||||
float wrapWidth = bb.p0.x;
|
for(int w = wrapIndex; w < bbs.size(); w++){
|
||||||
collectedWrapWidth = wrapWidth;
|
bbs[w].p0.x -= wrapWidth;
|
||||||
|
bbs[w].p1.x -= wrapWidth;
|
||||||
|
bbs[w].p2.x -= wrapWidth;
|
||||||
|
bbs[w].p3.x -= wrapWidth;
|
||||||
|
bbs[w].p0.y += advanceY;
|
||||||
|
bbs[w].p1.y += advanceY;
|
||||||
|
bbs[w].p2.y += advanceY;
|
||||||
|
bbs[w].p3.y += advanceY;
|
||||||
|
}
|
||||||
n_wraps++;
|
n_wraps++;
|
||||||
bb.p0.x -= wrapWidth;
|
lineBreaks.push_back(wrapIndex - 1);
|
||||||
bb.p1.x -= wrapWidth;
|
wrapIndex = -1;
|
||||||
bb.p2.x -= wrapWidth;
|
|
||||||
bb.p3.x -= wrapWidth;
|
|
||||||
bb.p0.y += (n_wraps) * advanceY;
|
|
||||||
bb.p1.y += (n_wraps) * advanceY;
|
|
||||||
bb.p2.y += (n_wraps) * advanceY;
|
|
||||||
bb.p3.y += (n_wraps) * advanceY;
|
|
||||||
}else{
|
|
||||||
if(firstToBreak){
|
|
||||||
collectedWrapWidth = bbs[wrapIndex].p0.x;
|
|
||||||
n_wraps++;
|
|
||||||
for(int w = wrapIndex; w <= i; w++){
|
|
||||||
bbs[w].p0.x -= collectedWrapWidth;
|
|
||||||
bbs[w].p1.x -= collectedWrapWidth;
|
|
||||||
bbs[w].p2.x -= collectedWrapWidth;
|
|
||||||
bbs[w].p3.x -= collectedWrapWidth;
|
|
||||||
bbs[w].p0.y += (n_wraps) * advanceY;
|
|
||||||
bbs[w].p1.y += (n_wraps) * advanceY;
|
|
||||||
bbs[w].p2.y += (n_wraps) * advanceY;
|
|
||||||
bbs[w].p3.y += (n_wraps) * advanceY;
|
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
bb.p0.x -= collectedWrapWidth;
|
|
||||||
bb.p1.x -= collectedWrapWidth;
|
|
||||||
bb.p2.x -= collectedWrapWidth;
|
|
||||||
bb.p3.x -= collectedWrapWidth;
|
|
||||||
bb.p0.y += (n_wraps) * advanceY;
|
|
||||||
bb.p1.y += (n_wraps) * advanceY;
|
|
||||||
bb.p2.y += (n_wraps) * advanceY;
|
|
||||||
bb.p3.y += (n_wraps) * advanceY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
firstToBreak = false;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
bb.p0.x -= collectedWrapWidth;
|
|
||||||
bb.p1.x -= collectedWrapWidth;
|
|
||||||
bb.p2.x -= collectedWrapWidth;
|
|
||||||
bb.p3.x -= collectedWrapWidth;
|
|
||||||
bb.p0.y += (n_wraps) * advanceY;
|
|
||||||
bb.p1.y += (n_wraps) * advanceY;
|
|
||||||
bb.p2.y += (n_wraps) * advanceY;
|
|
||||||
bb.p3.y += (n_wraps) * advanceY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxX = max(maxX, bbs[i].p1.x);
|
||||||
|
|
||||||
|
if(hasGoodCharacter){
|
||||||
|
lastGoodCharacter = i;
|
||||||
|
}
|
||||||
vi++;
|
vi++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(textAlignment != 0){
|
||||||
|
if(lineBreaks.size() > 0){
|
||||||
|
lineBreaks.push_back(lastGoodCharacter);
|
||||||
|
}
|
||||||
|
float w = width; // > 0 ? width : maxX;
|
||||||
|
int startFromCharacter = 0;
|
||||||
|
for(int lineBreak : lineBreaks){
|
||||||
|
ofxGPUFont::Font::BoundingBox & bbb = bbs[lineBreak];
|
||||||
|
float shiftX = (w - bbb.p1.x) * textAlignment;
|
||||||
|
for(int i = startFromCharacter; i <= lineBreak; i++){
|
||||||
|
auto & bb = bbs[i];
|
||||||
|
bb.p0.x += shiftX;
|
||||||
|
bb.p1.x += shiftX;
|
||||||
|
bb.p2.x += shiftX;
|
||||||
|
bb.p3.x += shiftX;
|
||||||
|
}
|
||||||
|
startFromCharacter = lineBreak + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return n_wraps;
|
return n_wraps;
|
||||||
}
|
}
|
||||||
//void GPUFontAtlasLayerCombo::cullBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
//void GPUFontAtlasLayerCombo::cullBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
||||||
|
@ -844,5 +876,4 @@ int GPUFontAtlasLayerCombo::wrapBoundingBoxes(std::vector <ofxGPUFont::Font::Bou
|
||||||
//bool GPUFontAtlasLayerCombo::isInside(const glm::vec4 & vertex,
|
//bool GPUFontAtlasLayerCombo::isInside(const glm::vec4 & vertex,
|
||||||
//int width, int height){
|
//int width, int height){
|
||||||
//}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,8 @@ class GPUFontAtlasLayerCombo : public AtlasLayerCombo {
|
||||||
int wrapBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
int wrapBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
||||||
const std::vector <ofxGPUFont::GlyphIdentity> & _variationText,
|
const std::vector <ofxGPUFont::GlyphIdentity> & _variationText,
|
||||||
int width,
|
int width,
|
||||||
float advanceY);
|
float advanceY,
|
||||||
|
float textAlignment = 0);
|
||||||
//void cullBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
//void cullBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
|
||||||
//int width, int height);
|
//int width, int height);
|
||||||
//bool isInside(const ofxGPUFont::Font::BoundingBox & bb,
|
//bool isInside(const ofxGPUFont::Font::BoundingBox & bb,
|
||||||
|
@ -130,4 +131,5 @@ class GPUFontAtlasLayerCombo : public AtlasLayerCombo {
|
||||||
int totalCharacters = 0;
|
int totalCharacters = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ class Layer {
|
||||||
float fontSize_px = 42;
|
float fontSize_px = 42;
|
||||||
float letterSpacing = 0;
|
float letterSpacing = 0;
|
||||||
float lineHeight = 1;
|
float lineHeight = 1;
|
||||||
|
float textAlignment = 0;
|
||||||
std::array <float, 4> color = {0, 0, 0, 1};
|
std::array <float, 4> color = {0, 0, 0, 1};
|
||||||
bool mirror_x = false;
|
bool mirror_x = false;
|
||||||
float mirror_x_distance = 0;
|
float mirror_x_distance = 0;
|
||||||
|
|
|
@ -181,12 +181,18 @@ shared_ptr <Layer> LayerComposition::getLayer(const LayerID & layerID){
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerComposition::draw(int width, int height) const {
|
void LayerComposition::draw(int width, int height) const {
|
||||||
|
for(const auto & [identifier, layerCombo] : atlasLayerCombos){
|
||||||
|
if(identifier.type == LayerType::MSDFGEN){
|
||||||
|
auto combo = static_pointer_cast <MsdfAtlasLayerCombo>(layerCombo);
|
||||||
|
//combo->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
for(unsigned int i = layerOrder.size(); i-- > 0;){
|
for(unsigned int i = layerOrder.size(); i-- > 0;){
|
||||||
LayerID layerID = layerOrder[i];
|
LayerID layerID = layerOrder[i];
|
||||||
if(layers.count(layerID) > 0){
|
if(layers.count(layerID) > 0){
|
||||||
auto layer = layers.at(layerID);
|
auto layer = layers.at(layerID);
|
||||||
if(layers.at(layerID)->getType() == LayerType::MSDFGEN){
|
if(layers.at(layerID)->getType() == LayerType::MSDFGEN){
|
||||||
layer->draw(glm::vec3(200, 200, 0));
|
//layer->draw(glm::vec3(200, 200, 0));
|
||||||
}else{
|
}else{
|
||||||
auto combo =
|
auto combo =
|
||||||
static_pointer_cast <GPUFontAtlasLayerCombo>(atlasLayerCombos.at(layer->getMomsComboIdentifier()));
|
static_pointer_cast <GPUFontAtlasLayerCombo>(atlasLayerCombos.at(layer->getMomsComboIdentifier()));
|
||||||
|
@ -209,6 +215,14 @@ void LayerComposition::draw(int width, int height) const {
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
void LayerComposition::drawCamera(const ofCamera & camera) const {
|
||||||
|
for(const auto & [identifier, layerCombo] : atlasLayerCombos){
|
||||||
|
if(identifier.type == LayerType::MSDFGEN){
|
||||||
|
auto combo = static_pointer_cast <MsdfAtlasLayerCombo>(layerCombo);
|
||||||
|
combo->draw(camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const unordered_map <ComboIdentifier, shared_ptr <AtlasLayerCombo> > & LayerComposition::getAtlasLayerCombos() const {
|
const unordered_map <ComboIdentifier, shared_ptr <AtlasLayerCombo> > & LayerComposition::getAtlasLayerCombos() const {
|
||||||
return atlasLayerCombos;
|
return atlasLayerCombos;
|
||||||
|
|
|
@ -15,6 +15,7 @@ class LayerComposition {
|
||||||
void setup();
|
void setup();
|
||||||
void update();
|
void update();
|
||||||
void draw(int width = 0, int height = 0) const;
|
void draw(int width = 0, int height = 0) const;
|
||||||
|
void drawCamera(const ofCamera & camera) const;
|
||||||
LayerID addLayer(const Layer::Props & props,
|
LayerID addLayer(const Layer::Props & props,
|
||||||
LayerID layerID = "");
|
LayerID layerID = "");
|
||||||
LayerID addLayer(const ComboIdentifier & identifier,
|
LayerID addLayer(const ComboIdentifier & identifier,
|
||||||
|
|
|
@ -114,6 +114,16 @@ bool MsdfAtlasLayerCombo::hasChildren(){
|
||||||
return layers.size() > 0;
|
return layers.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unique
|
||||||
|
void MsdfAtlasLayerCombo::draw(const ofCamera & camera){
|
||||||
|
vertices.clear();
|
||||||
|
parameters.clear();
|
||||||
|
for(const auto & layer : layers){
|
||||||
|
vertices.insert(vertices.end(), layer->vertices.begin(), layer->vertices.end());
|
||||||
|
parameters.insert(parameters.end(), layer->parameters.begin(), layer->parameters.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ofImage & MsdfAtlasLayerCombo::getAtlasImage(){
|
const ofImage & MsdfAtlasLayerCombo::getAtlasImage(){
|
||||||
return atlas->getAtlasImage();
|
return atlas->getAtlasImage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ class MsdfAtlasLayerCombo : public AtlasLayerCombo {
|
||||||
const ComboIdentifier & getIdentifier() const override;
|
const ComboIdentifier & getIdentifier() const override;
|
||||||
void setVFlip(VFlipState vFlipState) override;
|
void setVFlip(VFlipState vFlipState) override;
|
||||||
bool hasChildren() override;
|
bool hasChildren() override;
|
||||||
|
void draw(const ofCamera & camera);
|
||||||
const ofImage & getAtlasImage();
|
const ofImage & getAtlasImage();
|
||||||
string getAtlasImagePath();
|
string getAtlasImagePath();
|
||||||
shared_ptr <Layer> getLayer(); // TODO: is this used
|
shared_ptr <Layer> getLayer(); // TODO: is this used
|
||||||
|
@ -39,5 +40,7 @@ class MsdfAtlasLayerCombo : public AtlasLayerCombo {
|
||||||
GLint uboIndex;
|
GLint uboIndex;
|
||||||
void setupUbo();
|
void setupUbo();
|
||||||
bool uboIsSetup = false;
|
bool uboIsSetup = false;
|
||||||
|
std::vector <MsdfLayer::BufferVertex> vertices;
|
||||||
|
std::vector <MsdfLayer::CharacterDrawParameters> parameters;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "fwd.hpp"
|
#include "fwd.hpp"
|
||||||
#include "ofGraphics.h"
|
#include "ofGraphics.h"
|
||||||
|
#include "ofGraphicsConstants.h"
|
||||||
#include "ofUtils.h"
|
#include "ofUtils.h"
|
||||||
|
|
||||||
namespace ofxVariableLab {
|
namespace ofxVariableLab {
|
||||||
|
@ -311,6 +312,122 @@ const Layer::BoundingBox & MsdfLayer::getBoundingBox(){
|
||||||
void MsdfLayer::setBoundingBox(const Layer::BoundingBox & boundingBox){
|
void MsdfLayer::setBoundingBox(const Layer::BoundingBox & boundingBox){
|
||||||
this->boundingBox = boundingBox;
|
this->boundingBox = boundingBox;
|
||||||
}
|
}
|
||||||
|
void MsdfLayer::collectCharacter(const char character,
|
||||||
|
const ofNode & node,
|
||||||
|
glm::vec4 color,
|
||||||
|
ofxVariableLab::FontVariation fontVariation){
|
||||||
|
const ofImage & atlasImage = atlas->getAtlasImage();
|
||||||
|
ofNode n = node;
|
||||||
|
n.setScale(n.getScale() * scaleFactor);
|
||||||
|
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);
|
||||||
|
|
||||||
|
float mix = -1;
|
||||||
|
ofxMsdfgen::GlyphGeometry gg_a;
|
||||||
|
ofxMsdfgen::GlyphGeometry gg_b;
|
||||||
|
|
||||||
|
ofxMsdfgen::FontVariation fv{
|
||||||
|
fontVariation.name,
|
||||||
|
fontVariation.value
|
||||||
|
};
|
||||||
|
|
||||||
|
bool success = atlas->getGlyphGeometryPair(character,
|
||||||
|
fv,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
getVFlip(settings.vFlipBehaviour,
|
||||||
|
ofGetCurrentOrientationMatrix(),
|
||||||
|
vFlip);
|
||||||
|
if(vFlip == V_FLIP_OFF){
|
||||||
|
n.move(pl * magic, (pt * magic) + (-1 * h), 0.0f);
|
||||||
|
}else{
|
||||||
|
n.move(pl * magic, -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));
|
||||||
|
|
||||||
|
BufferVertex v[4];
|
||||||
|
glm::vec4 p0 = n.getGlobalTransformMatrix() * glm::vec4(0, 0, 0, 1);
|
||||||
|
glm::vec4 p1 = n.getGlobalTransformMatrix() * glm::vec4(w, 0, 0, 1);
|
||||||
|
glm::vec4 p2 = n.getGlobalTransformMatrix() * glm::vec4(w, h, 0, 1);
|
||||||
|
glm::vec4 p3 = n.getGlobalTransformMatrix() * glm::vec4(0, h, 0, 1);
|
||||||
|
glm::vec2 uv0_a = glm::vec2();
|
||||||
|
glm::vec2 uv0_b = glm::vec2();
|
||||||
|
glm::vec2 uv1_a = glm::vec2();
|
||||||
|
glm::vec2 uv1_b = glm::vec2();
|
||||||
|
glm::vec2 uv2_a = glm::vec2();
|
||||||
|
glm::vec2 uv2_b = glm::vec2();
|
||||||
|
glm::vec2 uv3_a = glm::vec2();
|
||||||
|
glm::vec2 uv3_b = glm::vec2();
|
||||||
|
vertices.push_back(BufferVertex{
|
||||||
|
{p0.x, p0.y, p0.z, p0.w},
|
||||||
|
{uv0_a.x, uv0_a.y},
|
||||||
|
{uv0_b.x, uv0_b.y}
|
||||||
|
});
|
||||||
|
vertices.push_back(BufferVertex{
|
||||||
|
{p1.x, p1.y, p1.z, p1.w},
|
||||||
|
{uv1_a.x, uv1_a.y},
|
||||||
|
{uv1_b.x, uv1_b.y}
|
||||||
|
});
|
||||||
|
vertices.push_back(BufferVertex{
|
||||||
|
{p2.x, p2.y, p2.z, p2.w},
|
||||||
|
{uv2_a.x, uv2_a.y},
|
||||||
|
{uv2_b.x, uv2_b.y}
|
||||||
|
});
|
||||||
|
vertices.push_back(BufferVertex{
|
||||||
|
{p3.x, p3.y, p3.z, p3.w},
|
||||||
|
{uv3_a.x, uv3_a.y},
|
||||||
|
{uv3_b.x, uv3_b.y}
|
||||||
|
});
|
||||||
|
CharacterDrawParameters characterDrawParameters;
|
||||||
|
characterDrawParameters.unitRange = unitRange;
|
||||||
|
characterDrawParameters.fontColor = color;
|
||||||
|
characterDrawParameters.bgColor = uboParameters.bgColor;
|
||||||
|
characterDrawParameters.translation_a = translation_a;
|
||||||
|
characterDrawParameters.translation_b = translation_b;
|
||||||
|
characterDrawParameters.scale_a = scale_a;
|
||||||
|
characterDrawParameters.scale_b = scale_b;
|
||||||
|
characterDrawParameters.mix = mix;
|
||||||
|
parameters.push_back(characterDrawParameters);
|
||||||
|
}
|
||||||
void MsdfLayer::setAtlas(shared_ptr <ofxMsdfgen::Atlas> _atlas){
|
void MsdfLayer::setAtlas(shared_ptr <ofxMsdfgen::Atlas> _atlas){
|
||||||
atlas = _atlas;
|
atlas = _atlas;
|
||||||
// TODO: this does not seem proper
|
// TODO: this does not seem proper
|
||||||
|
|
|
@ -21,6 +21,22 @@ class MsdfLayer : public Layer {
|
||||||
glm::vec2 scale_b;
|
glm::vec2 scale_b;
|
||||||
float mix;
|
float mix;
|
||||||
};
|
};
|
||||||
|
struct BufferVertex {
|
||||||
|
GLfloat position[4];
|
||||||
|
GLfloat uv_a[2];
|
||||||
|
GLfloat uv_b[2];
|
||||||
|
};
|
||||||
|
struct CharacterDrawParameters {
|
||||||
|
glm::vec2 dimensions;
|
||||||
|
glm::vec4 fontColor;
|
||||||
|
glm::vec4 bgColor;
|
||||||
|
glm::vec2 unitRange;
|
||||||
|
glm::vec2 translation_a;
|
||||||
|
glm::vec2 scale_a;
|
||||||
|
glm::vec2 translation_b;
|
||||||
|
glm::vec2 scale_b;
|
||||||
|
float mix;
|
||||||
|
};
|
||||||
void setup(const LayerSettings & settings = LayerSettings()) override;
|
void setup(const LayerSettings & settings = LayerSettings()) override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void draw(glm::vec3 position = glm::vec3(0, 0, 0)) override;
|
void draw(glm::vec3 position = glm::vec3(0, 0, 0)) override;
|
||||||
|
@ -49,6 +65,10 @@ class MsdfLayer : public Layer {
|
||||||
ofNode & getInnerNode() override;
|
ofNode & getInnerNode() override;
|
||||||
const Layer::BoundingBox & getBoundingBox() override;
|
const Layer::BoundingBox & getBoundingBox() override;
|
||||||
void setBoundingBox(const Layer::BoundingBox & boundingBox) override;
|
void setBoundingBox(const Layer::BoundingBox & boundingBox) override;
|
||||||
|
void collectCharacter(const char character,
|
||||||
|
const ofNode & node,
|
||||||
|
glm::vec4 color = glm::vec4(1, 1, 1, 1),
|
||||||
|
ofxVariableLab::FontVariation fontVariation = ofxVariableLab::FontVariation());
|
||||||
|
|
||||||
void setAtlas(shared_ptr <ofxMsdfgen::Atlas> _atlas);
|
void setAtlas(shared_ptr <ofxMsdfgen::Atlas> _atlas);
|
||||||
shared_ptr <ofxMsdfgen::Atlas> getAtlas() const;
|
shared_ptr <ofxMsdfgen::Atlas> getAtlas() const;
|
||||||
|
@ -67,6 +87,9 @@ class MsdfLayer : public Layer {
|
||||||
GLint uboIndex;
|
GLint uboIndex;
|
||||||
UboParameters uboParameters;
|
UboParameters uboParameters;
|
||||||
|
|
||||||
|
std::vector <BufferVertex> vertices;
|
||||||
|
std::vector <CharacterDrawParameters> parameters;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Props lastProps;
|
Props lastProps;
|
||||||
std::deque <Props> propsBuffer;
|
std::deque <Props> propsBuffer;
|
||||||
|
|
|
@ -41,5 +41,4 @@ void getVFlip(const VFlipBehaviour & vFlipBehaviour,
|
||||||
////ofTranslate(pl * magic, -1 * pt * magic, 0);
|
////ofTranslate(pl * magic, -1 * pt * magic, 0);
|
||||||
//}else{
|
//}else{
|
||||||
//ofTranslate(pl * magic, -1 * pt * magic, 0);
|
//ofTranslate(pl * magic, -1 * pt * magic, 0);
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,4 +159,8 @@ static bool listFontVariationAxes(std::string fontPath,
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isInside(float px, float py, float x, float y, float w, float h){
|
||||||
|
return px >= x && px <= x + w && py >= y && py <= y + h;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue