fix wrapping

text alignment still broken
This commit is contained in:
jrkb 2023-09-06 17:12:34 +02:00
parent 1f5b02e947
commit 8952672e84
2 changed files with 79 additions and 52 deletions

View file

@ -243,6 +243,7 @@ void GPUFontAtlasLayerCombo::draw(int width, int height){
if(layer->getProps().width > 0){ if(layer->getProps().width > 0){
int n_wraps = wrapBoundingBoxes(bbs, int n_wraps = wrapBoundingBoxes(bbs,
layer->getVariationText(), layer->getVariationText(),
const_cast <std::vector <ofxGPUFont::GlyphAppearance> &>(layer->getVariationTextAppearance()), // TODO: REMOVE
layer->getProps().width, layer->getProps().width,
lineHeight); lineHeight);
float min_x = FLT_MAX; float min_x = FLT_MAX;
@ -515,6 +516,7 @@ void GPUFontAtlasLayerCombo::draw(int width,
float lineHeight = font->getLineHeight(layer->getProps().fontSize_px) * layer->getProps().lineHeight; float lineHeight = font->getLineHeight(layer->getProps().fontSize_px) * layer->getProps().lineHeight;
int n_wraps = wrapBoundingBoxes(bbs, int n_wraps = wrapBoundingBoxes(bbs,
layer->getVariationText(), layer->getVariationText(),
const_cast <std::vector <ofxGPUFont::GlyphAppearance> &>(layer->getVariationTextAppearance()), // TODO: REMOVE
layer->getProps().width, layer->getProps().width,
lineHeight, lineHeight,
layer->getProps().textAlignment); layer->getProps().textAlignment);
@ -787,86 +789,110 @@ 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,
std::vector <ofxGPUFont::GlyphAppearance> & variationTextAppearance,
int width, int width,
float advanceY, float advanceY,
float textAlignment){ float textAlignment){
int i = 0;
int vi = 0;
int wrapIndex = -1;
int n_wraps = 0; int n_wraps = 0;
float collectedWrapWidth = 0;
std::vector <int> lineBreaks; std::vector <int> lineBreaks;
std::vector <int> goodCharacters; std::vector <int> goodCharacters;
int lastGoodCharacter = -1; int lastGoodCharacter = -1;
//textAlignment = ofMap(sin(ofGetElapsedTimef()), -1, 1, 0, 1); //textAlignment = ofMap(sin(ofGetElapsedTimef()), -1, 1, 0, 1);
std::vector <int> vis;
std::vector <int> wrapIndices;
float maxX = 0; { // collect existing linebreaks, wrapindices and good characters
for(ofxGPUFont::Font::BoundingBox & bb : bbs){ int vi = 0;
// good character means it's a drawable character int wrapIndex = -1;
bool hasGoodCharacter = false; for(int i = 0; i < bbs.size(); i++){
while(!hasGoodCharacter && vi < variationText.size()){ // good character means it's a drawable character
if(variationText[vi].charcode == '\0' bool hasGoodCharacter = false;
|| variationText[vi].charcode == '\r' while(!hasGoodCharacter && vi < variationText.size()){
|| variationText[vi].charcode == '\n'){ if(variationText[vi].charcode == '\0'
if(variationText[vi].charcode == '\n'){ || variationText[vi].charcode == '\r'
if(lastGoodCharacter >= 0){ || variationText[vi].charcode == '\n'){
lineBreaks.push_back(lastGoodCharacter); if(variationText[vi].charcode == '\n'){
if(lastGoodCharacter >= 0){
lineBreaks.push_back(lastGoodCharacter);
}
} }
wrapIndex = -1;
vi++;
}else if(variationText[vi].charcode == ' '){ // TODO: any whitespace
wrapIndex = i;
vi++;
}else{
hasGoodCharacter = true;
goodCharacters.push_back(vi);
} }
wrapIndex = -1; }
collectedWrapWidth = 0; if(variationText[vi].charcode == '-'){
vi++;
}else if(variationText[vi].charcode == ' '){ // TODO: any whitespace
wrapIndex = i; wrapIndex = i;
vi++;
}else{
hasGoodCharacter = true;
goodCharacters.push_back(i);
} }
}
if(variationText[vi].charcode == '-'){
wrapIndex = i;
}
const float insideWidth = bb.p1.x - collectedWrapWidth;
bool overhang = (insideWidth / float(width)) > (n_wraps + 1);
if(width > 0 && insideWidth > width){ if(hasGoodCharacter){
if(wrapIndex >= 0){ lastGoodCharacter = i;
float wrapWidth = bbs[wrapIndex].p0.x; }
for(int w = wrapIndex; w < bbs.size(); w++){ wrapIndices.push_back(wrapIndex);
bbs[w].p0.x -= wrapWidth; vi++;
bbs[w].p1.x -= wrapWidth; }
bbs[w].p2.x -= wrapWidth; }
bbs[w].p3.x -= wrapWidth; { // add new linebreaks at wrapindices
bbs[w].p0.y += advanceY; int i = 0;
bbs[w].p1.y += advanceY; float wrapWidth;
bbs[w].p2.y += advanceY; int lastBrokenWrapIndex = -1;
bbs[w].p3.y += advanceY; for(ofxGPUFont::Font::BoundingBox & bb : bbs){
int wrapIndex = wrapIndices[i];
if(width > 0 && bb.p1.x > width){
if(wrapIndex >= 0 && std::find(lineBreaks.begin(), lineBreaks.end(), wrapIndex - 1) == lineBreaks.end()){
lastBrokenWrapIndex = wrapIndex;
wrapWidth = bbs[wrapIndex].p0.x;
int nextLineBreak = INT_MAX;
for(int lb = 0; lb < lineBreaks.size(); lb++){
if(lineBreaks[lb] >= i){
nextLineBreak = lineBreaks[lb];
break;
}
}
for(int w = wrapIndex; w < bbs.size(); w++){
if(w <= nextLineBreak){
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++;
lineBreaks.push_back(wrapIndex - 1);
} }
n_wraps++;
lineBreaks.push_back(wrapIndex - 1);
wrapIndex = -1;
} }
i++;
} }
}
maxX = max(maxX, bbs[i].p1.x); float maxX = -1 * FLT_MAX;
for(const auto & bb : bbs){
if(hasGoodCharacter){ maxX = max(maxX, bb.p1.x);
lastGoodCharacter = i;
}
vi++;
i++;
} }
if(textAlignment != 0){ if(textAlignment != 0){
if(lineBreaks.size() > 0){ if(lineBreaks.size() > 0){
lineBreaks.push_back(lastGoodCharacter); lineBreaks.push_back(lastGoodCharacter);
} }
float w = width; // > 0 ? width : maxX; //float w = width > 0 ? width : maxX;
float w = maxX;
int startFromCharacter = 0; int startFromCharacter = 0;
for(int lineBreak : lineBreaks){ for(int lineBreak : lineBreaks){
ofxGPUFont::Font::BoundingBox & bbb = bbs[lineBreak]; ofxGPUFont::Font::BoundingBox & bbb = bbs[lineBreak];
int vi = vis[lineBreak];
int vi2 = vis[startFromCharacter];
variationTextAppearance[vi].color[0] = 1.0;
variationTextAppearance[vi2].color[1] = 1.0;
float shiftX = (w - bbb.p1.x) * textAlignment; float shiftX = (w - bbb.p1.x) * textAlignment;
for(int i = startFromCharacter; i <= lineBreak; i++){ for(int i = startFromCharacter; i <= lineBreak; i++){
auto & bb = bbs[i]; auto & bb = bbs[i];

View file

@ -91,6 +91,7 @@ class GPUFontAtlasLayerCombo : public AtlasLayerCombo {
private: private:
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,
std::vector <ofxGPUFont::GlyphAppearance> & variationTextAppearance,
int width, int width,
float advanceY, float advanceY,
float textAlignment = 0); float textAlignment = 0);