const ofTrueTypeFont::glyphProps & ofTrueTypeFont::getGlyphProperties(uint32_t glyph) const{ if(isValidGlyph(glyph)){ return cps[indexForGlyph(glyph)]; }else{ return invalidProps; } }
//----------------------------------------------------------- void ofTrueTypeFont::drawChar(uint32_t c, float x, float y, bool vFlipped) const{ if (!isValidGlyph(c)){ //ofLogError("ofTrueTypeFont") << "drawChar(): char " << c + NUM_CHARACTER_TO_START << " not allocated: line " << __LINE__ << " in " << __FILE__; return; } long xmin, ymin, xmax, ymax; float t1, v1, t2, v2; auto props = getGlyphProperties(c); t1 = props.t1; t2 = props.t2; v2 = props.v2; v1 = props.v1; xmin = long(props.xmin+x); ymin = props.ymin; xmax = long(props.xmax+x); ymax = props.ymax; if(!vFlipped){ ymin *= -1; ymax *= -1; } ymin += y; ymax += y; ofIndexType firstIndex = stringQuads.getVertices().size(); stringQuads.addVertex(ofVec3f(xmin,ymin)); stringQuads.addVertex(ofVec3f(xmax,ymin)); stringQuads.addVertex(ofVec3f(xmax,ymax)); stringQuads.addVertex(ofVec3f(xmin,ymax)); stringQuads.addTexCoord(ofVec2f(t1,v1)); stringQuads.addTexCoord(ofVec2f(t2,v1)); stringQuads.addTexCoord(ofVec2f(t2,v2)); stringQuads.addTexCoord(ofVec2f(t1,v2)); stringQuads.addIndex(firstIndex); stringQuads.addIndex(firstIndex+1); stringQuads.addIndex(firstIndex+2); stringQuads.addIndex(firstIndex+2); stringQuads.addIndex(firstIndex+3); stringQuads.addIndex(firstIndex); }
void ofTrueTypeFont::iterateString(const string & str, float x, float y, bool vFlipped, std::function<void(uint32_t, ofVec2f)> f) const{ ofVec2f pos(x,y); int newLineDirection = 1; if(!vFlipped){ // this would align multiline texts to the last line when vflip is disabled //int lines = ofStringTimesInString(c,"\n"); //Y = lines*lineHeight; newLineDirection = -1; } int directionX = settings.direction == ofTtfSettings::LeftToRight?1:-1; string str_valid; utf8::replace_invalid(str.begin(),str.end(),back_inserter(str_valid)); 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); uint32_t prevC = 0; while(it != end){ try{ auto c = *it; if (c == '\n') { pos.y += lineHeight*newLineDirection; pos.x = x ; //reset X Pos back to zero prevC = 0; }if (c == '\t') { pos.x += getGlyphProperties(' ').advance * letterSpacing * 4 * directionX; prevC = c; } else if(isValidGlyph(c)) { const auto & props = getGlyphProperties(c); if(prevC>0){ pos.x += getKerning(c,prevC);// * directionX; } f(c,pos); pos.x += props.advance * letterSpacing * directionX; prevC = c; } ++it; }catch(...){ break; } } }
void ofTrueTypeFont::iterateString(const string & str, float x, float y, bool vFlipped, std::function<void(uint32_t, ofVec2f)> f) const { ofVec2f pos(x,y); int newLineDirection = 1; if(!vFlipped) { // this would align multiline texts to the last line when vflip is disabled //int lines = ofStringTimesInString(c,"\n"); //Y = lines*lineHeight; newLineDirection = -1; } int directionX = settings.direction == ofTtfSettings::LeftToRight?1:-1; uint32_t prevC = 0; for(auto c: ofUTF8Iterator(str)) { try { if (c == '\n') { pos.y += lineHeight*newLineDirection; pos.x = x ; //reset X Pos back to zero prevC = 0; } if (c == '\t') { pos.x += getGlyphProperties(' ').advance * letterSpacing * 4 * directionX; prevC = c; } else if(isValidGlyph(c)) { const auto & props = getGlyphProperties(c); if(prevC>0) { pos.x += getKerning(c,prevC);// * directionX; } f(c,pos); pos.x += props.advance * letterSpacing * directionX; prevC = c; } } catch(...) { break; } } }
//------------------------------------------------------------------ ofTTFCharacter ofTrueTypeFont::getCharacterAsPoints(uint32_t character, bool vflip, bool filled) const{ if( settings.contours == false ){ ofLogError("ofxTrueTypeFont") << "getCharacterAsPoints(): contours not created, call loadFont() with makeContours set to true"; return ofTTFCharacter(); } if (!isValidGlyph(character)){ return ofTTFCharacter(); } if(vflip){ if(filled){ return charOutlines[indexForGlyph(character)]; }else{ return charOutlinesContour[indexForGlyph(character)]; } }else{ if(filled){ return charOutlinesNonVFlipped[indexForGlyph(character)]; }else{ return charOutlinesNonVFlippedContour[indexForGlyph(character)]; } } }