//===================================================================== void ofTrueTypeFontWS::drawStringAsShapes(wstring c, float x, float y) { if (!bLoadedOk){ ofLog(OF_LOG_ERROR,"Error : font not allocated -- line %d in %s", __LINE__,__FILE__); return; }; //----------------------- error checking if (!bMakeContours){ ofLog(OF_LOG_ERROR,"Error : contours not created for this font - call loadFont with makeContours set to true"); return; } int len = (int)c.length(); // if (less_func(NUM_MAX_CHARACTERS, len + getLoadedCharsNum())) { // ofLog(OF_LOG_ERROR,"Error : too many typefaces already loaded"); // return; // } GLint index = 0; GLfloat X = 0; GLfloat Y = 0; glPushMatrix(); glTranslatef(x, y, 0); while(index < len){ int cy = getCharID(c[index]); if (cps[cy].value == TYPEFACE_UNLOADED){ loadEachChar(cy); } if (cy < nCharacters){ // full char set or not? if (c[index] == L'\n') { Y = lineHeight; X = 0 ; //reset X Pos back to zero }else if (c[index] == L' ') { cy = getCharID(L'p'); X += cps[cy].width; //glTranslated(cps[cy].width, 0, 0); } else { drawCharAsShape(cy, X, Y); X += cps[cy].setWidth; //glTranslated(cps[cy].setWidth, 0, 0); } } index++; } glPopMatrix(); }
int gr_measure(const char *s) { GRFont* fnt = NULL; int n, l; wchar_t ch; if (!fnt) fnt = gr_font; l = utf8_mbtowc(&ch, s, strlen(s)); //fprintf(stdout, "unicode: %d\n", l); if(l <= 0 ) return 0; n = fnt->cwidth[getCharID(s,NULL)]; return n; }
int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max_height) { GGLContext *gl = gr_context; GRFont *gfont = (GRFont*) pFont; unsigned off, width, height, n; int rect_x, rect_y; wchar_t ch; /* Handle default font */ if (!gfont) gfont = gr_font; y -= gfont->ascent; gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); gl->enable(gl, GGL_TEXTURE_2D); while(*s) { if(*((unsigned char*)(s)) < 0x20) { s++; continue; } off = getCharID(s,pFont); n = utf8_mbtowc(&ch, s, strlen(s)); if(n <= 0) break; s += n; width = gfont->cwidth[off]; height = gfont->cheight[off]; memcpy(&font_ftex, &gfont->texture, sizeof(font_ftex)); font_ftex.width = width; font_ftex.height = height; font_ftex.stride = width; font_ftex.data = gfont->fontdata[off]; gl->bindTexture(gl, &font_ftex); if ((x + (int)width) < max_width) rect_x = x + width; else rect_x = max_width; if (y + height < (unsigned int)(max_height)) rect_y = y + height; else rect_y = max_height; gl->texCoord2i(gl, 0 - x, 0 - y); gl->recti(gl, x, y, rect_x, rect_y); x += width; if (x > max_width) return x; } return x; }
int gr_measureEx(const char *s, void* font) { GRFont* fnt = (GRFont*) font; int n, l, off; wchar_t ch; if (!fnt) fnt = gr_font; n = 0; off = 0; while(*(s + off)) { l = utf8_mbtowc(&ch, s+off, strlen(s + off)); n += fnt->cwidth[getCharID(s+off,font)]; off += l; } return n; }
int gr_text(int x, int y, const char *s, int bold) { GGLContext *gl = gr_context; GRFont *gfont = NULL; unsigned off, width, height, n; wchar_t ch; /* Handle default font */ if (!gfont) gfont = gr_font; x += overscan_offset_x; y += overscan_offset_y; y -= gfont->ascent; gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); gl->enable(gl, GGL_TEXTURE_2D); while(*s) { if(*((unsigned char*)(s)) < 0x20) { s++; continue; } off = getCharID(s,NULL); n = utf8_mbtowc(&ch, s, strlen(s)); if(n <= 0) break; s += n; width = gfont->cwidth[off]; height = gfont->cheight[off]; memcpy(&font_ftex, &gfont->texture, sizeof(font_ftex)); font_ftex.width = width; font_ftex.height = height; font_ftex.stride = width; font_ftex.data = gfont->fontdata[off]; gl->bindTexture(gl, &font_ftex); gl->texCoord2i(gl, 0 - x, 0 - y); gl->recti(gl, x, y, x + width, y + height); x += width; } return x; }
void CExtendedInput_Item_Char::keyPressed(const int key) { int value = CRCInput::getUnicodeValue(key); if (value != -1) { if (isAllowedChar((char)value)) { *data = (char)value; g_RCInput->postMsg( CRCInput::RC_right, 0 ); } } else { unsigned int pos = getCharID( *data ); if (key==CRCInput::RC_up) { if(pos<allowedChars.size()-1) { *data = allowedChars[pos+1]; } else { *data = allowedChars[0]; } } else if (key==CRCInput::RC_down) { if(pos>0) { *data = allowedChars[pos-1]; } else { *data = allowedChars[allowedChars.size()-1]; } } } }
//------------------------------------------------------------------ void ofTrueTypeFontWS::drawString(const wstring c, float x, float y) { if (!bLoadedOk){ ofLog(OF_LOG_ERROR,"Error : font not allocated -- line %d in %s", __LINE__,__FILE__); return; }; int len = (int)c.length(); if (less_func(NUM_MAX_CHARACTERS, len + getLoadedCharsNum())) { ofLog(OF_LOG_ERROR,"Error : too many typefaces already loaded"); return; } // we need transparency to draw text, but we don't know // if that is set up in outside of this function // we "pushAttrib", turn on alpha and "popAttrib" // http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushattrib.html // **** note **** // I have read that pushAttrib() is slow, if used often, // maybe there is a faster way to do this? // ie, check if blending is enabled, etc... // glIsEnabled().... glGet()... // http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/get.html // ************** GLint index = 0; GLfloat X = 0; GLfloat Y = 0; // (a) record the current "alpha state, blend func, etc" #ifndef TARGET_OF_IPHONE glPushAttrib(GL_COLOR_BUFFER_BIT); #else GLboolean blend_enabled = glIsEnabled(GL_BLEND); GLboolean texture_2d_enabled = glIsEnabled(GL_TEXTURE_2D); GLint blend_src, blend_dst; glGetIntegerv( GL_BLEND_SRC, &blend_src ); glGetIntegerv( GL_BLEND_DST, &blend_dst ); #endif // (b) enable our regular ALPHA blending! glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // (c) enable texture once before we start drawing each char (no point turning it on and off constantly) glEnable(GL_TEXTURE_2D); // (d) store the current matrix position and do a translation to the drawing position glPushMatrix(); glTranslatef(x, y, 0); while(index < len){ int cy = getCharID(c[index]); if (cps[cy].value == TYPEFACE_UNLOADED){ loadEachChar(cy); } if (cy < nCharacters){ // full char set or not? if (c[index] == L'\n') { Y = (float) lineHeight; glTranslatef(-X, Y, 0); X = 0 ; //reset X Pos back to zero }else if (c[index] == L' ') { cy = getCharID(L'p'); X += cps[cy].width; glTranslatef((float)cps[cy].width, 0, 0); } else { drawChar(cy, 0, 0); X += cps[cy].setWidth; glTranslatef((float)cps[cy].setWidth, 0, 0); } } index++; } glPopMatrix(); glDisable(GL_TEXTURE_2D); // (c) return back to the way things were (with blending, blend func, etc) #ifndef TARGET_OF_IPHONE glPopAttrib(); #else if( !blend_enabled ) glDisable(GL_BLEND); if( !texture_2d_enabled ) glDisable(GL_TEXTURE_2D); glBlendFunc( blend_src, blend_dst ); #endif }
//----------------------------------------------------------- ofRectangle ofTrueTypeFontWS::getStringBoundingBox(wstring c, float x, float y){ ofRectangle myRect; GLint index = 0; GLfloat xoffset = 0; GLfloat yoffset = 0; int len = (int)c.length(); float minx = -1; float miny = -1; float maxx = -1; float maxy = -1; if (len < 1){ myRect.x = 0; myRect.y = 0; myRect.width = 0; myRect.height = 0; return myRect; } bool bFirstCharacter = true; while(index < len){ int cy = getCharID(c[index]); if (cps[cy].value == TYPEFACE_UNLOADED){ // fixed bug. thanks oriol! loadEachChar(cy); } if (cy < nCharacters){ // full char set or not? if (c[index] == L'\n') { yoffset += (int)lineHeight; xoffset = 0 ; //reset X Pos back to zero } else if (c[index] == L' ') { cy = getCharID(L'p'); xoffset += cps[cy].width; // zach - this is a bug to fix -- for now, we don't currently deal with ' ' in calculating string bounding box } else { GLint height = cps[cy].height; GLint bwidth = cps[cy].width; GLint top = cps[cy].topExtent - cps[cy].height; GLint lextent = cps[cy].leftExtent; float x1, y1, x2, y2, corr, stretch; stretch = (float)visibleBorder * 2; corr = (float)(((fontSize - height) + top) - fontSize); x1 = (x + xoffset + lextent + bwidth + stretch); y1 = (y + yoffset + height + corr + stretch); x2 = (x + xoffset + lextent); y2 = (y + yoffset + -top + corr); xoffset += cps[cy].setWidth; if (bFirstCharacter == true){ minx = x2; miny = y2; maxx = x1; maxy = y1; bFirstCharacter = false; } else { if (x2 < minx) minx = x2; if (y2 < miny) miny = y2; if (x1 > maxx) maxx = x1; if (y1 > maxy) maxy = y1; } } } index++; } myRect.x = minx; myRect.y = miny; myRect.width = maxx-minx; myRect.height = maxy-miny; return myRect; }
//------------------------------------------------------------------ void ofTrueTypeFontWS::loadFont(string filename, int fontsize, bool _bAntiAliased, bool makeContours){ bMakeContours = makeContours; //------------------------------------------------ if (bLoadedOk == true){ // we've already been loaded, try to clean up : if (cps != NULL){ delete[] cps; } if (texNames != NULL){ for (int i = 0; i < nCharacters; i++){ glDeleteTextures(1, &texNames[i]); } delete[] texNames; } loaded_chars.clear(); bLoadedOk = false; } //------------------------------------------------ filename = ofToDataPath(filename); bLoadedOk = false; bAntiAlised = _bAntiAliased; fontSize = fontsize; //--------------- load the library and typeface if (FT_Init_FreeType( &library )){ ofLog(OF_LOG_ERROR," PROBLEM WITH FT lib"); return; } if (FT_New_Face( library, filename.c_str(), 0, &face )){ return; } FT_Set_Char_Size( face, fontsize << 6, fontsize << 6, 96, 96); lineHeight = fontsize * 1.43f; //------------------------------------------------------ //kerning would be great to support: //ofLog(OF_LOG_NOTICE,"FT_HAS_KERNING ? %i", FT_HAS_KERNING(face)); //------------------------------------------------------ nCharacters = NUM_MAX_CHARACTERS; //--------------- initialize character info and textures cps = new charProps[nCharacters]; texNames = new GLuint[nCharacters]; glGenTextures(nCharacters, texNames); for (int i = 0 ; i < nCharacters; i++){ cps[i].value = TYPEFACE_UNLOADED; } loaded_chars.reserve(nCharacters); if(bMakeContours){ charOutlines.clear(); charOutlines.assign(nCharacters, ofTTFCharacter()); } //---------------- flag bLoadedOk = true; //---------------- load 'p' character for display ' ' int cy = getCharID(L'p'); loadEachChar(cy); }