//----------------------------------------------------------- ofVec2f ofTrueTypeFont::getFirstGlyphPosForTexture(const std::string & str, bool vflip) const { if(!str.empty()) { try { auto c = *ofUTF8Iterator(str).begin(); if (c == '\n') { return {0.f, 0.f}; } else { auto g = loadGlyph(c); if(settings.direction == ofTtfSettings::LeftToRight) { return {-float(g.props.xmin), getLineHeight() + g.props.ymin + getDescenderHeight()}; } else { return {-float(g.props.xmin), getLineHeight() + g.props.ymin + getDescenderHeight()}; } } } catch(...) { return {0.f, 0.f}; } } }
//----------------------------------------------------------- ofTexture ofTrueTypeFont::getStringTexture(const std::string& str, bool vflip) const{ string str_valid; utf8::replace_invalid(str.begin(),str.end(),back_inserter(str_valid)); vector<glyph> glyphs; vector<ofVec2f> glyphPositions; utf8::iterator<const char*> it(&str_valid.front(), &str_valid.front(), (&str_valid.back())+1); utf8::iterator<const char*> end((&str_valid.back())+1, &str_valid.front(), (&str_valid.back())+1); int x = 0; int y = 0; long height = 0; uint32_t prevC = 0; while(it != end){ try{ auto c = *it; if (c == '\n') { y += lineHeight; x = 0 ; //reset X Pos back to zero prevC = 0; } else { glyphs.push_back(loadGlyph(c)); if(prevC>0){ x += getKerning(c,prevC); }else if(settings.direction == ofTtfSettings::RightToLeft){ x += glyphs.back().props.width; } glyphPositions.emplace_back(static_cast<float>(x), static_cast<float>(y)); x += glyphs.back().props.advance * letterSpacing; height = max(height, glyphs.back().props.ymax + y + long(getLineHeight())); } ++it; prevC = c; }catch(...){ break; } } ofTexture tex; ofPixels totalPixels; totalPixels.allocate(x, height, OF_PIXELS_GRAY_ALPHA); //-------------------------------- clear data: totalPixels.set(0,255); // every luminance pixel = 255 totalPixels.set(1,0); size_t i = 0; for(auto & g: glyphs){ if(settings.direction == ofTtfSettings::LeftToRight){ g.pixels.blendInto(totalPixels, glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); }else{ g.pixels.blendInto(totalPixels, x-glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); } i++; if(i==glyphPositions.size()){ break; } } tex.allocate(totalPixels); return tex; }
//----------------------------------------------------------- ofTexture ofTrueTypeFont::getStringTexture(const std::string& str, bool vflip) const { vector<glyph> glyphs; vector<ofVec2f> glyphPositions; long height = 0; int width = 0; int lineWidth = 0; uint32_t prevC = 0; iterateString(str, 0, 0, vflip, [&](uint32_t c, ofVec2f pos) { try { if (c != '\n') { auto g = loadGlyph(c); glyphs.push_back(g); int x = pos.x + g.props.xmin; int y = g.props.ymax + pos.y; glyphPositions.emplace_back(x, y); lineWidth += glyphs.back().props.advance * letterSpacing; width = max(width, lineWidth); height = max(height, y + long(getLineHeight())); } else { lineWidth = 0; } } catch(...) { } }); ofTexture tex; ofPixels totalPixels; totalPixels.allocate(width, height, OF_PIXELS_GRAY_ALPHA); //-------------------------------- clear data: totalPixels.set(0,255); // every luminance pixel = 255 totalPixels.set(1,0); size_t i = 0; for(auto & g: glyphs) { if(settings.direction == ofTtfSettings::LeftToRight) { g.pixels.blendInto(totalPixels, glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); } else { g.pixels.blendInto(totalPixels, width-glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); } i++; if(i==glyphPositions.size()) { break; } } tex.allocate(totalPixels); return tex; }