Changeset 5343 in orxonox.OLD for trunk/src/lib/graphics/text_engine/text_engine.cc
- Timestamp:
- Oct 10, 2005, 12:16:19 AM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/graphics/text_engine/text_engine.cc
r5342 r5343 30 30 #include <string.h> 31 31 32 #ifdef HAVE_SDL_IMAGE_H33 #include <SDL_image.h>34 #else35 #include <SDL/SDL_image.h>36 #endif37 #include "font.xpm"38 39 40 32 #include "graphics_engine.h" 41 33 #include "resource_manager.h" … … 46 38 #include "debug.h" 47 39 #include "list.h" 48 49 ////////////50 /// TEXT ///51 ////////////52 53 /**54 * creates a new Text Element55 * @param fontFile the Font to render this text in56 * @param type The renderType to display this font in57 */58 Text::Text(const char* fontFile, unsigned int fontSize, TEXT_RENDER_TYPE type)59 {60 this->init();61 62 if (fontFile != NULL)63 this->setFont(fontFile, fontSize);64 this->setType(type);65 }66 67 /**68 * creates a new Text Element69 * @param font the Font to render this text in70 * @param type The renderType to display this font in71 *72 * this constructor is private, because the user should initialize73 * a text with the TextEngine.74 */75 Text::Text(Font* font, TEXT_RENDER_TYPE type)76 {77 this->init();78 79 this->font = font;80 this->setType(type);81 }82 83 /**84 * deletes a Text out of memory85 *86 * This also ereases the text from the textList of the TextEngine87 */88 Text::~Text()89 {90 if (this->font != NULL)91 ResourceManager::getInstance()->unload(this->font);92 93 if (this->text)94 delete[] this->text;95 }96 97 void Text::init()98 {99 this->setClassID(CL_TEXT, "Text");100 101 // initialize this Text102 this->font = NULL;103 this->text = NULL;104 this->externText = NULL;105 this->setAlignment(TEXT_DEFAULT_ALIGNMENT);106 this->texture = 0;107 this->blending = TEXT_DEFAULT_BLENDING;108 this->color = TEXT_DEFAULT_COLOR;109 this->setType(TEXT_RENDER_DYNAMIC);110 111 this->setText(NULL);112 }113 114 /**115 * sets the Font of this Text to font116 * @param font the Font (normaly from the ResourceManager) to allocate to this Text117 */118 void Text::setFont(Font* font)119 {120 if (this->font != NULL)121 ResourceManager::getInstance()->unload(this->font);122 this->font = font;123 }124 125 /**126 * sets the Font of this Text to font from fontFile127 * @param fontFile the File to load the Font from.128 * @param fontSize the Size of the Font129 */130 void Text::setFont(const char* fontFile, unsigned int fontSize)131 {132 Font* tmpFont;133 Text* newText;134 Vector tmpVec;135 136 tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, &fontSize);137 if (tmpFont == NULL)138 {139 PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);140 this->setFont(NULL);141 }142 else143 this->setFont(tmpFont);144 }145 146 /**147 * sets the Type of this Text148 * @param type the type to set.149 */150 void Text::setType(TEXT_RENDER_TYPE type)151 {152 if (this->font != NULL && this->font->font)153 this->type = type;154 else155 this->type = TEXT_RENDER_DYNAMIC;156 }157 158 /**159 * Sets a new Text to the font160 * @param text the new text to set161 */162 void Text::setText(const char* text, bool isExtern)163 {164 if (isExtern)165 {166 this->externText = text;167 168 if (unlikely(this->text != NULL))169 {170 delete[] this->text;171 this->text = NULL;172 }173 }174 else175 {176 this->externText = NULL;177 if (this->text)178 delete[] this->text;179 if (text != NULL)180 {181 this->text = new char[strlen(text)+1];182 strcpy(this->text, text);183 }184 else185 this->text = NULL;186 }187 188 // setting up the Text-Width if DYNAMIC189 if (this->type & TEXT_RENDER_DYNAMIC && this->getAlignment() != TEXT_ALIGN_LEFT && this->font != NULL)190 {191 Glyph** glyphArray = this->font->getGlyphArray();192 193 int width = 0;194 const char* tmpText = this->externText;195 if (this->externText == NULL)196 tmpText = this->text;197 if (tmpText != NULL)198 {199 while (*tmpText != '\0')200 {201 if(glyphArray[*tmpText])202 {203 width += glyphArray[*tmpText]->width;204 }205 tmpText++;206 }207 this->width = width;208 }209 }210 }211 212 /**213 * creates a texture out of the given parameters214 215 this has to be called every time by the user, to if changes were made.216 this is only for TEXT_STATIC-mode217 */218 void Text::createTexture()219 {220 SDL_Surface* tmpSurf;221 if (this->texture)222 glDeleteTextures(1, &this->texture);223 if (likely(this->font != NULL))224 {225 SDL_Color theColor = { (int)(this->color.x*255), (int)(this->color.y*255), (int)(this->color.z*255) };226 tmpSurf = TTF_RenderText_Blended(this->font->font,227 this->text,228 theColor);229 }230 if (tmpSurf)231 this->texture = loadTexture(tmpSurf, &this->texCoord);232 233 this->width = tmpSurf->w;234 this->height = tmpSurf->h;235 SDL_FreeSurface(tmpSurf);236 }237 238 /**239 * draws the Text240 */241 void Text::draw() const242 {243 glPushMatrix();244 // transform for alignment.245 if (this->getAlignment() == TEXT_ALIGN_RIGHT)246 glTranslatef(-this->width, 0, 0);247 else if (this->getAlignment() == TEXT_ALIGN_CENTER || this->getAlignment() == TEXT_ALIGN_SCREEN_CENTER)248 glTranslatef(-this->width/2, 0, 0);249 250 // drawing this Text.251 // setting the Blending effects252 glColor4f(this->color.x, this->color.y, this->color.z, this->blending);253 glEnable(GL_BLEND);254 glEnable(GL_TEXTURE_2D);255 glBlendFunc(GL_SRC_ALPHA, GL_ONE);256 257 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_MODULATE );258 259 if(likely(type & TEXT_RENDER_DYNAMIC ))260 {261 Glyph** glyphArray;262 if (likely (this->font != NULL))263 {264 glyphArray = this->font->getGlyphArray();265 glBindTexture(GL_TEXTURE_2D, font->getFastTextureID());266 }267 else268 {269 if (unlikely(Font::getDefaultFont() == NULL))270 Font::initDefaultFont();271 glyphArray = Font::getDefaultFont()->getGlyphArray();272 glBindTexture(GL_TEXTURE_2D, Font::getDefaultFont()->getFastTextureID());273 }274 glTranslatef(getAbsCoor2D().x, getAbsCoor2D().y, 0);275 // glRotatef(this->getAbsDir2D(), 0,0,1);276 const char* tmpText = this->externText;277 if (this->externText == NULL)278 tmpText = this->text;279 if (likely(tmpText != NULL))280 {281 while (likely(*tmpText != '\0'))282 {283 if(likely(glyphArray[*tmpText] != NULL))284 {285 glCallList(glyphArray[*tmpText]->displayList);286 glTranslatef(glyphArray[*tmpText]->width, 0, 0);287 }288 tmpText++;289 }290 }291 }292 else //(if type & TEXT_RENDER_STATIC)293 {294 glBindTexture(GL_TEXTURE_2D, this->texture);295 glBegin(GL_QUADS);296 297 glTexCoord2f(this->texCoord.minU, this->texCoord.minV);298 glVertex2f(this->getAbsCoor2D().x, this->getAbsCoor2D().y );299 300 glTexCoord2f(this->texCoord.maxU, this->texCoord.minV);301 glVertex2f(this->getAbsCoor2D().x + this->width, this->getAbsCoor2D().y );302 303 glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);304 glVertex2f(this->getAbsCoor2D().x + this->width, getAbsCoor2D().y + this->height);305 306 glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);307 glVertex2f(getAbsCoor2D().x, getAbsCoor2D().y + this->height);308 309 glEnd();310 311 }312 glPopMatrix();313 }314 315 /**316 * prints out some nice debug information about this text317 */318 void Text::debug() const319 {320 if (this->externText == NULL)321 PRINT(0)("=== TEXT: %s ===\n", this->text);322 else323 PRINT(0)("=== TEXT: %s ===\n", this->externText);324 325 if (this->getBindNode())326 PRINT(0)("is bind to %s; ref=%p\n", this->getBindNode()->getName(), this->getBindNode());327 PRINT(0)("Color: %0.2f %0.2f %0.2f\n", this->color.x, this->color.y, this->color.z);328 }329 330 331 ////////////332 /// UTIL ///333 ////////////334 /**335 * Loads a Font from an SDL_surface into a texture.336 * @param surface The surface to make the texture of337 * @param texCoord The texture coordinates of the 4 corners of the texture338 * @returns the ID of the texture339 */340 GLuint Text::loadTexture(SDL_Surface *surface, TexCoord* texCoord)341 {342 GLuint texture;343 int w, h;344 SDL_Surface *image;345 SDL_Rect area;346 Uint32 saved_flags;347 Uint8 saved_alpha;348 349 /* Use the surface width and height expanded to powers of 2 */350 w = powerOfTwo(surface->w);351 h = powerOfTwo(surface->h);352 if (texCoord != NULL)353 {354 texCoord->minU = 0.0f;355 texCoord->minV = 0.0f;356 texCoord->maxU = (GLfloat)surface->w / w;357 texCoord->maxV = (GLfloat)surface->h / h;358 }359 image = SDL_CreateRGBSurface(SDL_SWSURFACE,360 w, h,361 32,362 #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */363 0x000000FF,364 0x0000FF00,365 0x00FF0000,366 0xFF000000367 #else368 0xFF000000,369 0x00FF0000,370 0x0000FF00,371 0x000000FF372 #endif373 );374 if ( image == NULL ) {375 return 0;376 }377 378 /* Save the alpha blending attributes */379 saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);380 saved_alpha = surface->format->alpha;381 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {382 SDL_SetAlpha(surface, 0, 0);383 }384 385 /* Copy the surface into the GL texture image */386 area.x = 0;387 area.y = 0;388 area.w = surface->w;389 area.h = surface->h;390 SDL_BlitSurface(surface, &area, image, &area);391 392 /* Restore the alpha blending attributes */393 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {394 SDL_SetAlpha(surface, saved_flags, saved_alpha);395 }396 397 /* Create an OpenGL texture for the image */398 glGenTextures(1, &texture);399 glBindTexture(GL_TEXTURE_2D, texture);400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);402 glTexImage2D(GL_TEXTURE_2D,403 0,404 GL_RGBA,405 w, h,406 0,407 GL_RGBA,408 GL_UNSIGNED_BYTE,409 image->pixels);410 SDL_FreeSurface(image); /* No longer needed the data */411 412 return texture;413 }414 415 /**416 * Quick utility function for texture creation417 * @param input an integer418 * @returns the next bigger 2^n-integer than input419 */420 int Text::powerOfTwo(int input)421 {422 int value = 1;423 424 while ( value < input )425 value <<= 1;426 return value;427 }428 429 430 ////////////431 /// FONT ///432 ////////////433 /**434 * constructs a Font435 * @param fontFile the File to load the font from436 * @param fontSize the Size of the Font in Pixels437 */438 Font::Font(const char* fontFile, unsigned int fontSize)439 {440 this->init();441 442 this->setSize(fontSize);443 444 if (fontFile != NULL)445 this->loadFont(fontFile);446 447 this->setStyle("c");//TTF_STYLE_NORMAL);448 449 this->fastTextureID = this->createFastTexture();450 451 452 // this->createAsciiImage("test.bmp");453 }454 455 /**456 * constructs a Font457 * @param fontFile the File to load the font from458 * @param fontSize the Size of the Font in Pixels459 */460 Font::Font(char** xpmArray)461 {462 this->init();463 464 // this->setSize(fontSize);465 SDL_Surface* image = NULL;466 if (xpmArray != NULL)467 image = IMG_ReadXPMFromArray(xpmArray);468 if (image != NULL)469 {470 this->loadFontFromSDL_Surface(image);471 SDL_FreeSurface(image);472 }473 else474 PRINTF(1)("loading from surface failed: %s\n", IMG_GetError());475 476 }477 478 479 /**480 * destructs a font481 * this releases the memory a font uses to be opened.482 * deletes the glLists, and the TTF-handler, if present.483 */484 Font::~Font()485 {486 // deleting all Glyphs487 if (this->glyphArray != NULL)488 {489 for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)490 {491 if (this->glyphArray[i] != NULL)492 {493 glDeleteLists(this->glyphArray[i]->displayList, 1);494 delete this->glyphArray[i];495 }496 }497 delete[] this->glyphArray;498 }499 500 // erease this font out of the memory.501 if (likely(this->font != NULL))502 TTF_CloseFont(this->font);503 }504 505 /**506 * initializes a Font (with default values)507 */508 void Font::init()509 {510 this->setClassID(CL_FONT, "Font");511 // setting default values.512 this->font = NULL;513 this->glyphArray = NULL;514 this->fastTextureID = 0;515 }516 517 518 /**519 * sets The Font.520 * @param fontFile The file containing the font.521 * @returns true if loaded, false if something went wrong, or if a font was loaded before.522 */523 bool Font::loadFont(const char* fontFile)524 {525 if (!this->getName())526 {527 this->setName(fontFile);528 529 this->font = TTF_OpenFont(this->getName(), this->fontSize);530 if(!this->font)531 {532 PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());533 return false;534 }535 else536 return true;537 }538 else539 {540 PRINTF(2)("Font already initialized, unable to change it now.\n");541 return false;542 }543 }544 545 /**546 * loads a font From an XPM-array.547 * @param xpmArray the array of the XPM to load the font from.548 */549 bool Font::loadFontFromSDL_Surface(SDL_Surface* surface)550 {551 // loading to a texture.552 if(surface == NULL)553 return false;554 TexCoord texCoord;555 this->fastTextureID = Text::loadTexture(surface, &texCoord);556 557 // initializing the Glyphs.558 if (this->glyphArray == NULL)559 {560 float cx,cy;561 Glyph* glyph;562 this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];563 for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)564 {565 glyph = this->glyphArray[i] = new Glyph;566 glyph->displayList = glGenLists(1);567 if (!glIsList(glyph->displayList))568 {569 PRINTF(2)("Error creating glList for Font character %c\n", i);570 this->glyphArray[i] = NULL;571 delete glyph;572 continue;573 }574 cx=(float)(i%16)/16.0f; // X Position Of Current Character575 cy=(float)(i/16)/16.0f; // Y Position Of Current Character576 glNewList(glyph->displayList, GL_COMPILE); // Start Building A List577 glBegin(GL_QUADS); // Use A Quad For Each Character578 glTexCoord2f(cx, cy+0.001f); // Texture Coord (Bottom Left)579 glVertex2d(0,-16); // Vertex Coord (Bottom Left)580 glTexCoord2f(cx+0.0625f, cy+0.001f); // Texture Coord (Bottom Right)581 glVertex2i(16,-16); // Vertex Coord (Bottom Right)582 glTexCoord2f(cx+0.0625f, cy+0.0625f); // Texture Coord (Top Right)583 glVertex2i(16,0); // Vertex Coord (Top Right)584 glTexCoord2f(cx, cy+0.0625f); // Texture Coord (Top Left)585 glVertex2i(0,0); // Vertex Coord (Top Left)586 glEnd(); // Done Building Our Quad (Character)587 // glTranslated(12,0,0); // Move To The Right Of The Character588 glEndList(); // Done Building The Display List589 this->glyphArray[i]->width = 12;590 }591 }592 return true;593 }594 595 596 /**597 * sets a specific renderStyle598 * @param renderStyle the Style to render: a char-array containing:599 i: italic, b: bold, u, underline600 */601 void Font::setStyle(const char* renderStyle)602 {603 this->renderStyle = TTF_STYLE_NORMAL;604 605 for (int i = 0; i < strlen(renderStyle); i++)606 if (strncmp(renderStyle+i, "b", 1) == 0)607 this->renderStyle |= TTF_STYLE_BOLD;608 else if (strncmp(renderStyle+i, "i", 1) == 0)609 this->renderStyle |= TTF_STYLE_ITALIC;610 else if (strncmp(renderStyle+i, "u", 1) == 0)611 this->renderStyle |= TTF_STYLE_UNDERLINE;612 613 if (likely(this->font != NULL))614 TTF_SetFontStyle(this->font, this->renderStyle);615 else616 PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");617 }618 619 /**620 * Sets a new Size to the font621 * @param fontSize The new Size in pixels.622 */623 void Font::setSize(unsigned int fontSize)624 {625 this->fontSize = fontSize;626 }627 628 Font* Font::defaultFont = NULL;629 630 void Font::createAsciiImage(const char* fileName)631 {632 if (this->font == NULL)633 return;634 int height = this->getMaxHeight();635 636 //637 SDL_Color tmpColor = {0, 0, 0};638 // Surface definition.639 SDL_Rect tmpRect; // this represents a Rectangle for blitting.640 SDL_Surface* tmpSurf = SDL_CreateRGBSurface(SDL_SWSURFACE,641 height*16, height*16,642 32,643 #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */644 0x000000FF,645 0x0000FF00,646 0x00FF0000,647 0xFF000000648 #else649 0xFF000000,650 0x00FF0000,651 0x0000FF00,652 0x000000FF653 #endif654 );655 tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;656 SDL_SetClipRect(tmpSurf, &tmpRect);657 int maxLineHeight = 0;658 659 int posX, posY;660 // all the interessting Glyphs661 for (posY = 0; posY < 16; posY++)662 {663 for (posX = 0; posX < 16; posX++)664 {665 SDL_Surface* glyphSurf = NULL;666 if (likely(this->font != NULL))667 {668 SDL_Color white = {255, 255, 255};669 glyphSurf = TTF_RenderGlyph_Blended(this->font, posX+16*posY, white);670 }671 if( glyphSurf != NULL )672 {673 tmpRect.x = height*posX;674 tmpRect.y = height*posY;675 SDL_SetAlpha(glyphSurf, 0, 0);676 677 SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);678 SDL_FreeSurface(glyphSurf);679 // Outputting Glyphs to BMP-files.680 /*681 char outname[512];682 if (i < 10)683 sprintf( outname, "%s-glyph-00%d.bmp", this->getName(), i );684 else if (i <100)685 sprintf( outname, "%s-glyph-0%d.bmp", this->getName(), i );686 else687 sprintf( outname, "%s-glyph-%d.bmp", this->getName(), i );688 SDL_SaveBMP(tmpSurf, outname);*/689 690 }691 }692 }693 SDL_SaveBMP(tmpSurf, fileName);694 SDL_FreeSurface(tmpSurf);695 }696 697 /**698 * initializes the default font699 */700 void Font::initDefaultFont()701 {702 if (Font::defaultFont == NULL)703 Font::defaultFont = new Font(font_xpm);704 }705 706 /**707 * deletes the default font708 */709 void Font::removeDefaultFont()710 {711 if (Font::defaultFont != NULL)712 delete Font::defaultFont;713 Font::defaultFont = NULL;714 }715 716 717 /**718 * @returns the maximum height of the Font, if the font was initialized, 0 otherwise719 */720 int Font::getMaxHeight()721 {722 if (likely (this->font != NULL))723 return TTF_FontHeight(this->font);724 else725 return 0;726 }727 728 /**729 * @returns the maximum ascent of the Font, if the font was initialized, 0 otherwise730 731 the ascent is the pixels of the font above the baseline732 */733 int Font::getMaxAscent()734 {735 if (likely(this->font != NULL))736 return TTF_FontAscent(this->font);737 else738 return 0;739 }740 741 /**742 * @returns the maximum descent of the Font, if the font was initialized, 0 otherwise743 744 the descent is the pixels of the font below the baseline745 */746 int Font::getMaxDescent()747 {748 if (likely(this->font != NULL))749 return TTF_FontDescent(this->font);750 else751 return 0;752 }753 754 /**755 * @param character The character to get info about.756 * @returns a Glyph struct of a character. This Glyph is a pointer,757 and MUST be deleted by the user..758 759 This only works for horizontal fonts. see760 http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html761 for more info about vertical Fonts762 */763 Glyph* Font::getGlyphMetrics(Uint16 character)764 {765 Glyph* rg = new Glyph;766 rg->character = character;767 if (likely (this->font!= NULL))768 TTF_GlyphMetrics(this->font, rg->character,769 &rg->minX, &rg->maxX,770 &rg->minY, &rg->maxY,771 &rg->advance);772 rg->height = rg->maxY - rg->minY;773 rg->width = rg->maxX - rg->minX;774 rg->bearingX = (rg->advance - rg->width) / 2;775 rg->bearingY = rg->maxY;776 return rg;777 }778 779 /**780 * creates a Fast-Texture of this Font781 */782 GLuint Font::createFastTexture()783 {784 /* interesting GLYPHS:785 * 32: space786 * 33-47: Special Characters.787 * 48-57: 0-9788 * 58-63: some more special chars (minor)789 * 65-90: A-Z790 * 97-122: a-z791 */792 int numberOfGlyphs = 91;793 794 this->initGlyphs(32, numberOfGlyphs);795 this->glyphArray[32]->width = fontSize/2; //!< @todo find out the real size of a Space796 797 int rectSize = this->findOptimalFastTextureSize();798 799 // setting default values. (maybe not needed afterwards)800 SDL_Color tmpColor; tmpColor.r = tmpColor.g = tmpColor.b = 0;801 // Surface definition.802 SDL_Rect tmpRect; // this represents a Rectangle for blitting.803 SDL_Surface* tmpSurf = SDL_CreateRGBSurface(SDL_SWSURFACE,804 rectSize, rectSize,805 32,806 #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */807 0x000000FF,808 0x0000FF00,809 0x00FF0000,810 0xFF000000811 #else812 0xFF000000,813 0x00FF0000,814 0x0000FF00,815 0x000000FF816 #endif817 );818 tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;819 SDL_SetClipRect(tmpSurf, &tmpRect);820 int maxLineHeight = 0;821 822 // all the interessting Glyphs823 for (int i = 0; i < 128; i++)824 {825 SDL_Surface* glyphSurf = NULL;826 Glyph* tmpGlyph;827 828 if (tmpGlyph = this->glyphArray[i])829 {830 if (tmpGlyph->height > maxLineHeight)831 maxLineHeight = tmpGlyph->height;832 833 if (tmpRect.x+tmpGlyph->advance > tmpSurf->w)834 {835 tmpRect.x = 0;836 tmpRect.y = tmpRect.y + maxLineHeight + 1;837 maxLineHeight = 0;838 }839 if (tmpRect.y + maxLineHeight > tmpSurf->h)840 {841 PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");842 break;843 }844 // reading in the new Glyph845 if (likely(this->font != NULL))846 {847 SDL_Color white = {255, 255, 255};848 glyphSurf = TTF_RenderGlyph_Blended(this->font, i, white);849 }850 if( glyphSurf != NULL )851 {852 SDL_SetAlpha(glyphSurf, 0, 0);853 854 SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);855 TexCoord tmpTexCoord;856 tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;857 tmpTexCoord.maxU = (float)(tmpRect.x + tmpGlyph->advance)/(float)tmpSurf->w;858 tmpTexCoord.minV = (float)(tmpRect.y)/(float)tmpSurf->w;859 tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;860 tmpGlyph->displayList = glGenLists(1);861 862 glNewList(tmpGlyph->displayList, GL_COMPILE);863 glBegin(GL_QUADS);864 glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);865 glVertex2d(0, - tmpGlyph->bearingY);866 glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);867 glVertex2d(0, tmpGlyph->height - tmpGlyph->bearingY);868 glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);869 glVertex2d(tmpGlyph->width, tmpGlyph->height - tmpGlyph->bearingY);870 glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);871 glVertex2d(tmpGlyph->width, - tmpGlyph->bearingY);872 glEnd();873 glEndList();874 SDL_FreeSurface(glyphSurf);875 876 tmpRect.x += tmpGlyph->advance;877 878 // Outputting Glyphs to BMP-files.879 /*880 char outname[512];881 if (i < 10)882 sprintf( outname, "%s-glyph-00%d.bmp", this->getName(), i );883 else if (i <100)884 sprintf( outname, "%s-glyph-0%d.bmp", this->getName(), i );885 else886 sprintf( outname, "%s-glyph-%d.bmp", this->getName(), i );887 SDL_SaveBMP(tmpSurf, outname);*/888 889 }890 }891 }892 893 GLuint texture;894 glGenTextures(1, &texture);895 glBindTexture(GL_TEXTURE_2D, texture);896 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);897 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);898 glTexImage2D(GL_TEXTURE_2D,899 0,900 GL_RGBA,901 tmpSurf->w, tmpSurf->h,902 0,903 GL_RGBA,904 GL_UNSIGNED_BYTE,905 tmpSurf->pixels);906 SDL_FreeSurface(tmpSurf);907 return texture;908 }909 910 /**911 * stores Glyph Metrics in an Array.912 * @param from The Glyph to start from.913 * @param count The number of Glyphs to start From.914 */915 void Font::initGlyphs(Uint16 from, Uint16 count)916 {917 /* initialize the Array, and set all its entries to NULL918 * only if the Glyph-array has not been initialized919 */920 if (!this->glyphArray)921 {922 this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];923 for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)924 this->glyphArray[i] = NULL;925 }926 927 Uint16 lastGlyph = from + count;928 929 for (int i = from; i <= lastGlyph; i++)930 {931 // setting up all the Glyphs we like.932 glyphArray[i] = getGlyphMetrics(i);933 }934 return;935 }936 937 /**938 * @returns the optimal size to use as the texture size939 940 @todo: this algorithm can be a lot more faster, althought it does941 not really matter within the init-context, and 128 glyphs.942 943 This function searches for a 2^n sizes texture-size, this is for944 openGL-version < 1.2 compatibility ( and because it is realy easy like this :))945 */946 int Font::findOptimalFastTextureSize()947 {948 int i;949 int x,y; // the counters950 int maxLineHeight = this->getMaxHeight();951 unsigned int size = 32; // starting Value, we have to start somewhere 32 seems reasonable. (take any small enough 2^i number)952 bool sizeOK = false;953 Glyph* tmpGlyph;954 955 while (!sizeOK)956 {957 x = 0; y = 0;958 for (i = 0; i <= FONT_HIGHEST_KNOWN_CHAR; i++)959 {960 if((tmpGlyph = this->glyphArray[i]) != NULL)961 {962 // getting the height of the highest Glyph in the Line.963 if (tmpGlyph->height > maxLineHeight)964 maxLineHeight = tmpGlyph->height;965 966 if (x + tmpGlyph->advance > size)967 {968 x = 0;969 y = y + maxLineHeight;970 //maxLineHeight = 0;971 }972 if (y + maxLineHeight + 1 > size)973 break;974 x += tmpGlyph->advance;975 976 }977 }978 if (i >= FONT_HIGHEST_KNOWN_CHAR-1 || size > 8192)979 sizeOK = true;980 else981 size *= 2;982 }983 return size;984 }985 986 987 /**988 * a simple function to get some interesting information about this class989 */990 void Font::debug()991 {992 // print the loaded font's style993 int style;994 if (likely(this->font != NULL))995 style = TTF_GetFontStyle(this->font);996 PRINTF(0)("The font style is:");997 if(style==TTF_STYLE_NORMAL)998 PRINTF(0)(" normal");999 else {1000 if(style&TTF_STYLE_BOLD)1001 PRINTF(0)(" bold");1002 if(style&TTF_STYLE_ITALIC)1003 PRINTF(0)(" italic");1004 if(style&TTF_STYLE_UNDERLINE)1005 PRINTF(0)(" underline");1006 }1007 PRINTF(0)("\n");1008 }1009 1010 40 1011 41 ///////////////////
Note: See TracChangeset
for help on using the changeset viewer.