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){
int n_wraps = wrapBoundingBoxes(bbs,
layer->getVariationText(),
const_cast <std::vector <ofxGPUFont::GlyphAppearance> &>(layer->getVariationTextAppearance()), // TODO: REMOVE
layer->getProps().width,
lineHeight);
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;
int n_wraps = wrapBoundingBoxes(bbs,
layer->getVariationText(),
const_cast <std::vector <ofxGPUFont::GlyphAppearance> &>(layer->getVariationTextAppearance()), // TODO: REMOVE
layer->getProps().width,
lineHeight,
layer->getProps().textAlignment);
@ -787,86 +789,110 @@ void GPUFontAtlasLayerCombo::getAndApplyTransformOrigin(glm::vec4 & transformOri
}
int GPUFontAtlasLayerCombo::wrapBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
const std::vector <ofxGPUFont::GlyphIdentity> & _variationText,
std::vector <ofxGPUFont::GlyphAppearance> & variationTextAppearance,
int width,
float advanceY,
float textAlignment){
int i = 0;
int vi = 0;
int wrapIndex = -1;
int n_wraps = 0;
float collectedWrapWidth = 0;
std::vector <int> lineBreaks;
std::vector <int> goodCharacters;
int lastGoodCharacter = -1;
//textAlignment = ofMap(sin(ofGetElapsedTimef()), -1, 1, 0, 1);
std::vector <int> vis;
std::vector <int> wrapIndices;
float maxX = 0;
for(ofxGPUFont::Font::BoundingBox & bb : bbs){
// good character means it's a drawable character
bool hasGoodCharacter = false;
while(!hasGoodCharacter && vi < variationText.size()){
if(variationText[vi].charcode == '\0'
|| variationText[vi].charcode == '\r'
|| variationText[vi].charcode == '\n'){
if(variationText[vi].charcode == '\n'){
if(lastGoodCharacter >= 0){
lineBreaks.push_back(lastGoodCharacter);
{ // collect existing linebreaks, wrapindices and good characters
int vi = 0;
int wrapIndex = -1;
for(int i = 0; i < bbs.size(); i++){
// good character means it's a drawable character
bool hasGoodCharacter = false;
while(!hasGoodCharacter && vi < variationText.size()){
if(variationText[vi].charcode == '\0'
|| variationText[vi].charcode == '\r'
|| variationText[vi].charcode == '\n'){
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;
vi++;
}else if(variationText[vi].charcode == ' '){ // TODO: any whitespace
}
if(variationText[vi].charcode == '-'){
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(wrapIndex >= 0){
float wrapWidth = bbs[wrapIndex].p0.x;
for(int w = wrapIndex; w < bbs.size(); w++){
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;
if(hasGoodCharacter){
lastGoodCharacter = i;
}
wrapIndices.push_back(wrapIndex);
vi++;
}
}
{ // add new linebreaks at wrapindices
int i = 0;
float wrapWidth;
int lastBrokenWrapIndex = -1;
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);
if(hasGoodCharacter){
lastGoodCharacter = i;
}
vi++;
i++;
float maxX = -1 * FLT_MAX;
for(const auto & bb : bbs){
maxX = max(maxX, bb.p1.x);
}
if(textAlignment != 0){
if(lineBreaks.size() > 0){
lineBreaks.push_back(lastGoodCharacter);
}
float w = width; // > 0 ? width : maxX;
//float w = width > 0 ? width : maxX;
float w = maxX;
int startFromCharacter = 0;
for(int lineBreak : lineBreaks){
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;
for(int i = startFromCharacter; i <= lineBreak; i++){
auto & bb = bbs[i];

View file

@ -91,6 +91,7 @@ class GPUFontAtlasLayerCombo : public AtlasLayerCombo {
private:
int wrapBoundingBoxes(std::vector <ofxGPUFont::Font::BoundingBox> & bbs,
const std::vector <ofxGPUFont::GlyphIdentity> & _variationText,
std::vector <ofxGPUFont::GlyphAppearance> & variationTextAppearance,
int width,
float advanceY,
float textAlignment = 0);