diff --git a/src/GPUFontAtlasLayerCombo.cpp b/src/GPUFontAtlasLayerCombo.cpp index 0735b16..fa3faf1 100644 --- a/src/GPUFontAtlasLayerCombo.cpp +++ b/src/GPUFontAtlasLayerCombo.cpp @@ -1,4 +1,5 @@ #include "GPUFontAtlasLayerCombo.h" +#include "GPUFontLayer.h" #include "Utils.h" #include "font.hpp" #include "ofAppRunner.h" @@ -67,7 +68,17 @@ void GPUFontAtlasLayerCombo::update(){ std::vector _variationText; for(const auto & layer : layers){ std::string layerText = layer->getProps().text; - totalCharacters += layerText.length(); + int mirrorMultiplier = 1; + if(layer->getProps().mirror_x){ + mirrorMultiplier += 1; + } + if(layer->getProps().mirror_y){ + mirrorMultiplier += 1; + } + if(layer->getProps().mirror_xy){ + mirrorMultiplier += 1; + } + totalCharacters += layerText.length() * mirrorMultiplier; _variationText.insert(_variationText.end(), layer->getVariationText().begin(), layer->getVariationText().end()); @@ -211,6 +222,19 @@ void GPUFontAtlasLayerCombo::draw(int width, int height){ bb, bbs, advanceY, true, layer->getProps().fontSize_px, layer->getProps().lineHeight); + float lineHeight = font->getLineHeight(layer->getProps().fontSize_px) * layer->getProps().lineHeight; + int n_wraps = wrapBoundingBoxes(bbs, + layer->getVariationText(), + layer->getProps().width, + lineHeight); + if(ofGetFrameNum() % 30 == 0){ + cout + << "n_wraps: " << ofToString(n_wraps) << endl + << "layer->getProps().width: " << ofToString(layer->getProps().width) << endl + ; + } + bb.p2.y += n_wraps * lineHeight; + bb.p3.y += n_wraps * lineHeight; glm::vec4 transformOrigin; getAndApplyTransformOrigin(transformOrigin, layer->getOuterNode(), @@ -219,6 +243,7 @@ void GPUFontAtlasLayerCombo::draw(int width, int height){ ascender, advanceY, layer->getProps()); + auto bb_mirror_none = bb; bb_mirror_none.multiply(layer->getInnerNode().getGlobalTransformMatrix()); @@ -418,5 +443,89 @@ void GPUFontAtlasLayerCombo::getAndApplyTransformOrigin(glm::vec4 & transformOri momNode.rotateDeg(props.rotation, glm::vec3(0, 0, 1)); momNode.setPosition(transformOrigin); } +int GPUFontAtlasLayerCombo::wrapBoundingBoxes(std::vector & bbs, + const std::vector & _variationText, + int width, + float advanceY){ + + int i = 0; + int wrapIndex = -1; + int n_wraps = 0; + bool firstToBreak = true; + vector breakPoints; + + for(ofxGPUFont::Font::BoundingBox & bb : bbs){ + bool hasGoodCharacter = false; + bool hadAlwaysGoodCharacter = true; + while(!hasGoodCharacter && i < variationText.size() - 1){ + if(variationText[i].charcode == '\0' + || variationText[i].charcode == '\r' + || variationText[i].charcode == '\n'){ + hadAlwaysGoodCharacter = false; + wrapIndex = -1; + i++; + }else{ + hasGoodCharacter = true; + } + } + if( //!hadAlwaysGoodCharacter || + (variationText[i].charcode == '-' + || variationText[i].charcode == ' ')){ + wrapIndex = i + 1; + cout << "WRAP INDEX " << ofToString(wrapIndex) << endl; + } + if(bb.p1.x > width){ + if(wrapIndex >= 0){ + if(wrapIndex == i){ + breakPoints.push_back(i); + bb.p0.x = 0; + bb.p1.x -= bb.p0.x; + bb.p2.x -= bb.p0.x; + bb.p3.x -= bb.p0.x; + bb.p0.y += (n_wraps + 1) * advanceY; + bb.p1.y += (n_wraps + 1) * advanceY; + bb.p2.y += (n_wraps + 1) * advanceY; + bb.p3.y += (n_wraps + 1) * advanceY; + }else{ + if(firstToBreak){ + breakPoints.push_back(wrapIndex); + for(int w = wrapIndex; w <= i; w++){ + bbs[w].p0.x -= bbs[wrapIndex].p0.x; + bbs[w].p1.x -= bbs[wrapIndex].p0.x; + bbs[w].p2.x -= bbs[wrapIndex].p0.x; + bbs[w].p3.x -= bbs[wrapIndex].p0.x; + bbs[w].p0.y += (n_wraps + 1) * advanceY; + bbs[w].p1.y += (n_wraps + 1) * advanceY; + bbs[w].p2.y += (n_wraps + 1) * advanceY; + bbs[w].p3.y += (n_wraps + 1) * advanceY; + } + }else{ + bb.p0.x -= bbs[wrapIndex].p0.x; + bb.p1.x -= bbs[wrapIndex].p0.x; + bb.p2.x -= bbs[wrapIndex].p0.x; + bb.p3.x -= bbs[wrapIndex].p0.x; + bb.p0.y += (n_wraps + 1) * advanceY; + bb.p1.y += (n_wraps + 1) * advanceY; + bb.p2.y += (n_wraps + 1) * advanceY; + bb.p3.y += (n_wraps + 1) * advanceY; + } + } + n_wraps++; + firstToBreak = false; + } + } + i++; + } + return n_wraps; +} +//void GPUFontAtlasLayerCombo::cullBoundingBoxes(std::vector & bbs, +//int width, int height){ +//} +//bool GPUFontAtlasLayerCombo::isInside(const ofxGPUFont::Font::BoundingBox & bb, +//int width, int height){ +//} +//bool GPUFontAtlasLayerCombo::isInside(const glm::vec4 & vertex, +//int width, int height){ +//} } diff --git a/src/GPUFontAtlasLayerCombo.h b/src/GPUFontAtlasLayerCombo.h index b67f16e..9624ce8 100644 --- a/src/GPUFontAtlasLayerCombo.h +++ b/src/GPUFontAtlasLayerCombo.h @@ -1,6 +1,7 @@ #pragma once #include "Utils.h" +#include "font.hpp" #include "ofMain.h" #include "AtlasLayerCombo.h" #include "GPUFontLayer.h" @@ -83,6 +84,16 @@ class GPUFontAtlasLayerCombo : public AtlasLayerCombo { bool isDirty = false; private: + int wrapBoundingBoxes(std::vector & bbs, + const std::vector & _variationText, + int width, + float advanceY); + //void cullBoundingBoxes(std::vector & bbs, + //int width, int height); + //bool isInside(const ofxGPUFont::Font::BoundingBox & bb, + //int width, int height); + //bool isInside(const glm::vec4 & vertex, + //int width, int height); GPUFontAtlasLayerComboSettings settings; FT_Library library; vector > layers; diff --git a/src/Layer.h b/src/Layer.h index 0087e96..3d5c618 100644 --- a/src/Layer.h +++ b/src/Layer.h @@ -30,6 +30,8 @@ class Layer { struct Props { float x = 200; float y = 200; + float width = 0; + float height = 0; float rotation = 0; float fontSize_px = 42; float letterSpacing = 0;