Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/text_engine.cc @ 5076

Last change on this file since 5076 was 5076, checked in by bensch, 19 years ago

orxonox/trunk: minor

File size: 23.4 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   for some fonts and licenses visit: =http://www.dafont.com/en/font.php=
16
17   !! IMPORTANT !! When using ttf fonts clear the license issues prior to
18   adding them to orxonox. This is really important, because we do not
19   want to offend anyone.
20*/
21
22#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_FONT
23
24#include "text_engine.h"
25
26using namespace std;
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "graphics_engine.h"
33#include "resource_manager.h"
34
35#include "p_node.h"
36#include "vector.h"
37#include "debug.h"
38#include "list.h"
39
40////////////
41/// TEXT ///
42////////////
43/**
44 *  creates a new Text Element
45 * @param font the Font to render this text in
46 * @param type The renderType to display this font in
47
48   this constructor is private, because the user should initialize
49   a text with the TextEngine.
50*/
51Text::Text(Font* font, int type)
52{
53  this->setClassID(CL_TEXT, "Text");
54
55  // initialize this Text
56  this->bindNode = NULL;
57  this->font = font;
58  this->text = NULL;
59  this->alignment = TEXT_DEFAULT_ALIGNMENT;
60  this->texture = 0;
61  this->blending = 1.0f;
62  this->setType(type);
63
64  this->setText(FONT_DEFAULT_TEXT);
65}
66
67/**
68 *  deletes a Text out of memory
69
70   This also ereases the text from the textList of the TextEngine
71*/
72Text::~Text()
73{
74  ResourceManager::getInstance()->unload(this->font);
75
76//  if (this->text)
77    //delete []this->text;
78  TextEngine::getInstance()->deleteText(this);
79}
80
81/**
82 *  sets the Type of this Text
83 * @param type the type to set.
84*/
85void Text::setType(int type)
86{
87  if (this->font->font)
88    this->type = type;
89  else
90    this->type = TEXT_DYNAMIC;
91}
92
93/**
94 *  Sets a new Text to the font
95 * @param text the new text to set
96*/
97void Text::setText(const char* text)
98{
99  if (this->text)
100    delete []this->text;
101  if (text != NULL)
102  {
103    this->text = new char[strlen(text)+1];
104    strcpy(this->text, text);
105  }
106  else
107  {
108    this->text = new char[1];
109    *this->text = '\0';
110  }
111
112
113  // setting up the Text-Width if DYNAMIC
114  if (this->type == TEXT_DYNAMIC && this->alignment != TEXT_ALIGN_LEFT)
115    {
116      Glyph** glyphArray = this->font->getGlyphArray();
117
118      int width = 0;
119      char* tmpText = this->text;
120      while (*tmpText != '\0')
121        {
122          if(glyphArray[*tmpText])
123            {
124              width += glyphArray[*tmpText]->width;
125            }
126          tmpText++;
127        }
128      this->posSize.w = width;
129    }
130}
131
132/**
133 *  sets a new color to the font
134 * @param r Red
135 * @param g Green
136 * @param b Blue
137*/
138void Text::setColor(Uint8 r, Uint8 g, Uint8 b)
139{
140  this->color.r = r;
141  this->color.g = g;
142  this->color.b = b;
143}
144
145/**
146 *  creates a texture out of the given parameters
147
148   this has to be called every time by the user, to if changes were made.
149   this is only for TEXT_STATIC-mode
150*/
151void Text::createTexture()
152{
153  SDL_Surface* tmpSurf;
154  if (this->texture)
155    glDeleteTextures(1, &this->texture);
156  if (likely(this->font != NULL))
157    tmpSurf = TTF_RenderText_Blended(this->font->font,
158                                     this->text,
159                                     this->color);
160  if (tmpSurf)
161    this->texture = loadTexture(tmpSurf, &this->texCoord);
162
163  this->posSize.w = tmpSurf->w;
164  this->posSize.h = tmpSurf->h;
165  SDL_FreeSurface(tmpSurf);
166}
167
168/**
169 *  draws the Text
170*/
171void Text::draw() const
172{
173  glPushMatrix();
174  // transform for alignment.
175  if (this->alignment == TEXT_ALIGN_RIGHT)
176    glTranslatef(-this->posSize.w, 0, 0);
177  else if (this->alignment == TEXT_ALIGN_CENTER || this->alignment == TEXT_ALIGN_SCREEN_CENTER)
178    glTranslatef(-this->posSize.w/2, 0, 0);
179
180  // drawing this Text.
181  // setting the Blending effects
182  glColor4f(1.0f,1.0f,1.0f, this->blending);
183  glEnable(GL_BLEND);
184  glEnable(GL_TEXTURE_2D);
185  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
186
187  if(type == TEXT_STATIC)
188    {
189      glBindTexture(GL_TEXTURE_2D, this->texture);
190      glBegin(GL_QUADS);
191
192      glTexCoord2f(this->texCoord.minU, this->texCoord.minV);
193      glVertex2f(this->absPos2D.x,   this->absPos2D.);
194
195      glTexCoord2f(this->texCoord.maxU, this->texCoord.minV);
196      glVertex2f(this->absPos2D.x + this->posSize.w, this->absPos2D.);
197
198      glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);
199      glVertex2f(this->absPos2D.x + this->posSize.w, absPos2D.y + this->posSize.h);
200
201      glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);
202      glVertex2f(absPos2D.x, absPos2D.y + this->posSize.h);
203
204      glEnd();
205    }
206  else //(if type == TEXT_DYNAMIC)
207    {
208      Glyph** glyphArray = this->font->getGlyphArray();
209      glBindTexture(GL_TEXTURE_2D, this->font->getFastTextureID());
210      //      glEnable(GL_TEXTURE_2D);
211      glTranslatef(absPos2D.x, absPos2D.y, 0);
212
213      const char* tmpText = this->text;
214      while (*tmpText != '\0')
215        {
216          if(glyphArray[*tmpText])
217            {
218              glCallList(glyphArray[*tmpText]->displayList);
219              glTranslatef(glyphArray[*tmpText]->width, 0, 0);
220            }
221          tmpText++;
222        }
223    }
224  glPopMatrix();
225}
226
227/**
228 *  prints out some nice debug information about this text
229*/
230void Text::debug() const
231{
232  PRINT(0)("=== TEXT: %s ===\n", this->text);
233  if (this->bindNode)
234    PRINT(0)("is bind to %s; ref=%p\n", this->bindNode->getName(), this->bindNode);
235  PRINT(0)("Relative Position: (%d::%d)\n", this->posSize.x, this->posSize.y);
236  PRINT(0)("Color: %d %d %d\n", this->color.r, this->color.g, this->color.b);
237}
238
239
240////////////
241/// UTIL ///
242////////////
243/**
244 *  Loads a Font from an SDL_surface into a texture.
245 * @param surface The surface to make the texture of
246 * @param texCoord The texture coordinates of the 4 corners of the texture
247 * @returns the ID of the texture
248*/
249GLuint Text::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
250{
251  GLuint texture;
252  int w, h;
253  SDL_Surface *image;
254  SDL_Rect area;
255  Uint32 saved_flags;
256  Uint8  saved_alpha;
257
258  /* Use the surface width and height expanded to powers of 2 */
259  w = powerOfTwo(surface->w);
260  h = powerOfTwo(surface->h);
261  if (texCoord)
262    {
263      texCoord->minU = 0.0f;
264      texCoord->minV = 0.0f;
265      texCoord->maxU = (GLfloat)surface->w / w;
266      texCoord->maxV = (GLfloat)surface->h / h;
267    }
268  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
269                               w, h,
270                               32,
271#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
272                               0x000000FF,
273                               0x0000FF00,
274                               0x00FF0000,
275                               0xFF000000
276#else
277                               0xFF000000,
278                               0x00FF0000,
279                               0x0000FF00,
280                               0x000000FF
281#endif
282                               );
283  if ( image == NULL ) {
284    return 0;
285  }
286
287  /* Save the alpha blending attributes */
288  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
289  saved_alpha = surface->format->alpha;
290  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
291    SDL_SetAlpha(surface, 0, 0);
292  }
293
294  /* Copy the surface into the GL texture image */
295  area.x = 0;
296  area.y = 0;
297  area.w = surface->w;
298  area.h = surface->h;
299  SDL_BlitSurface(surface, &area, image, &area);
300
301  /* Restore the alpha blending attributes */
302  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
303    SDL_SetAlpha(surface, saved_flags, saved_alpha);
304  }
305
306  /* Create an OpenGL texture for the image */
307  glGenTextures(1, &texture);
308  glBindTexture(GL_TEXTURE_2D, texture);
309  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
310  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
311  glTexImage2D(GL_TEXTURE_2D,
312               0,
313               GL_RGBA,
314               w, h,
315               0,
316               GL_RGBA,
317               GL_UNSIGNED_BYTE,
318               image->pixels);
319  SDL_FreeSurface(image); /* No longer needed */
320
321  return texture;
322}
323
324/**
325 *  Quick utility function for texture creation
326 * @param input an integer
327 * @returns the next bigger 2^n-integer than input
328*/
329int Text::powerOfTwo(int input)
330{
331  int value = 1;
332
333  while ( value < input ) {
334    value <<= 1;
335  }
336  return value;
337}
338
339
340////////////
341/// FONT ///
342////////////
343/**
344 *  constructs a Font
345 * @param fontFile the File to load the font from
346 * @param fontSize the Size of the Font in Pixels
347 * @param r Red value of the Font.
348 * @param g Green value of the Font.
349 * @param b Blue value of the Font.
350*/
351Font::Font(const char* fontFile, unsigned int fontSize, Uint8 r, Uint8 g, Uint8 b)
352{
353  this->setClassID(CL_FONT, "Font");
354  // setting default values.
355  this->font = NULL;
356  this->fontFile = NULL;
357  this->glyphArray = NULL;
358  this->fastTextureID = 0;
359
360  this->setSize(fontSize);
361
362  this->setFont(fontFile);
363
364  this->setStyle("c");//TTF_STYLE_NORMAL);
365
366  this->setFastColor(r, g, b);
367
368  this->fastTextureID = this->createFastTexture();
369}
370
371/**
372 *  destructs a font
373*/
374Font::~Font()
375{
376  // deleting the List of all Texts
377
378  // deleting all Glyphs
379  if (this->glyphArray)
380    {
381      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
382        delete this->glyphArray[i];
383      delete []this->glyphArray;
384    }
385
386  // erease this font out of the memory.
387  if (likely(this->font != NULL))
388    TTF_CloseFont(this->font);
389}
390
391/**
392 *  sets The Font.
393 * @param fontFile The file containing the font.
394 * @returns true if loaded, false if something went wrong, or if a font was loaded before.
395*/
396bool Font::setFont(const char* fontFile)
397{
398  if (!this->fontFile)
399    {
400      this->setName(fontFile);
401      this->fontFile = new char[strlen(fontFile)+1];
402      strcpy(this->fontFile, fontFile);
403
404      this->font = TTF_OpenFont(this->fontFile, this->fontSize);
405      if(!this->font)
406        {
407          PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());
408          return false;
409        }
410      else
411          return true;
412    }
413  else
414    {
415      PRINTF(2)("Font already initialized, unable to change it now.\n");
416      return false;
417    }
418}
419
420/**
421 *  sets a specific renderStyle
422 * @param renderStyle the Style to render: a char-array containing:
423   i: italic, b: bold, u, underline
424*/
425void Font::setStyle(const char* renderStyle)
426{
427  this->renderStyle = TTF_STYLE_NORMAL;
428
429  for (int i = 0; i < strlen(renderStyle); i++)
430    if (strncmp(renderStyle+i, "b", 1) == 0)
431      this->renderStyle |= TTF_STYLE_BOLD;
432    else if (strncmp(renderStyle+i, "i", 1) == 0)
433      this->renderStyle |= TTF_STYLE_ITALIC;
434    else if (strncmp(renderStyle+i, "u", 1) == 0)
435      this->renderStyle |= TTF_STYLE_UNDERLINE;
436
437  if (likely(this->font != NULL))
438    TTF_SetFontStyle(this->font, this->renderStyle);
439  else
440    PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");
441}
442
443/**
444 *  Sets a new Size to the font
445 * @param fontSize The new Size in pixels.
446*/
447void Font::setSize(unsigned int fontSize)
448{
449  this->fontSize = fontSize;
450}
451
452/**
453 *  sets a new color to the font
454 * @param r Red
455 * @param g Green
456 * @param b Blue
457*/
458void Font::setFastColor(Uint8 r, Uint8 g, Uint8 b)
459{
460  this->fastColor.r = r;
461  this->fastColor.g = g;
462  this->fastColor.b = b;
463}
464
465/**
466 * @returns the maximum height of the Font, if the font was initialized, 0 otherwise
467*/
468int Font::getMaxHeight()
469{
470  if (likely (this->font != NULL))
471    return TTF_FontHeight(this->font);
472  else
473    return 0;
474}
475
476/**
477 * @returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
478
479   the ascent is the pixels of the font above the baseline
480*/
481int Font::getMaxAscent()
482{
483  if (likely(this->font != NULL))
484    return TTF_FontAscent(this->font);
485  else
486    return 0;
487}
488
489/**
490 * @returns the maximum descent of the Font, if the font was initialized, 0 otherwise
491
492   the descent is the pixels of the font below the baseline
493*/
494int Font::getMaxDescent()
495{
496  if (likely(this->font != NULL))
497    return TTF_FontDescent(this->font);
498  else
499    return 0;
500}
501
502/**
503 * @param character The character to get info about.
504 * @returns a Glyph struct of a character. This Glyph is a pointer,
505   and MUST be deleted by the user..
506
507   This only works for horizontal fonts. see
508   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
509   for more info about vertical Fonts
510*/
511Glyph* Font::getGlyphMetrics(Uint16 character)
512{
513  Glyph* rg = new Glyph;
514  rg->character = character;
515  if (likely (this->font!= NULL))
516    TTF_GlyphMetrics(this->font, rg->character,
517                     &rg->minX, &rg->maxX,
518                     &rg->minY, &rg->maxY,
519                     &rg->advance);
520  rg->height = rg->maxY - rg->minY;
521  rg->width = rg->maxX - rg->minX;
522  rg->bearingX = (rg->advance - rg->width) / 2;
523  rg->bearingY = rg->maxY;
524  return rg;
525}
526
527GLuint Font::createFastTexture()
528{
529  /* interesting GLYPHS:
530   *  32: space
531   *  33-47: Special Characters.
532   *  48-57: 0-9
533   *  58-63: some more special chars (minor)
534   *  65-90: A-Z
535   *  97-122: a-z
536   */
537  int numberOfGlyphs = 91;
538
539  this->initGlyphs(32, numberOfGlyphs);
540  this->glyphArray[32]->width = fontSize/3; //!< @todo find out the real size of a Space
541
542  int rectSize = this->findOptimalFastTextureSize();
543
544  // setting default values. (maybe not needed afterwards)
545  SDL_Color tmpColor;  tmpColor.r = tmpColor.g = tmpColor.b = 0;
546  // Surface definition.
547  SDL_Rect tmpRect; // this represents a Rectangle for blitting.
548  SDL_Surface* tmpSurf =  SDL_CreateRGBSurface(SDL_SWSURFACE,
549                                               rectSize, rectSize,
550                                               32,
551#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
552                                               0x000000FF,
553                                               0x0000FF00,
554                                               0x00FF0000,
555                                               0xFF000000
556#else
557                                               0xFF000000,
558                                               0x00FF0000,
559                                               0x0000FF00,
560                                               0x000000FF
561#endif
562                                               );
563  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
564  SDL_SetClipRect(tmpSurf, &tmpRect);
565  int maxLineHeight = 0;
566
567  // all the interessting Glyphs
568  for (int i = 0; i <= 127; i++)
569    {
570      SDL_Surface* glyphSurf = NULL;
571      Glyph* tmpGlyph;
572
573      if (tmpGlyph = this->glyphArray[i])
574        {
575          if (tmpGlyph->height > maxLineHeight)
576            maxLineHeight = tmpGlyph->height;
577
578          if (tmpRect.x+tmpGlyph->width > tmpSurf->w)
579            {
580              tmpRect.x = 0;
581              tmpRect.y = tmpRect.y + maxLineHeight + 1;
582              maxLineHeight = 0;
583            }
584          if (tmpRect.y + maxLineHeight > tmpSurf->h)
585            {
586              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
587              break;
588            }
589          // reading in the new Glyph
590          if (likely(this->font != NULL))
591            glyphSurf = TTF_RenderGlyph_Blended(this->font, i, this->fastColor);
592          if( glyphSurf != NULL )
593            {
594
595              SDL_SetAlpha(glyphSurf, 0, 0);
596
597              SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);
598              TexCoord tmpTexCoord;
599              tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;
600              tmpTexCoord.maxU = (float)(tmpRect.x +1 +tmpGlyph->width)/(float)tmpSurf->w;
601              tmpTexCoord.minV = (float)tmpRect.y/(float)tmpSurf->w;
602              tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;
603              tmpGlyph->displayList = glGenLists(1);
604
605              glNewList(tmpGlyph->displayList, GL_COMPILE);
606              glBegin(GL_QUADS);
607              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);
608              glVertex2d(0, 0);
609              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
610              glVertex2d(0, tmpGlyph->height);
611              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
612              glVertex2d(tmpGlyph->width, tmpGlyph->height);
613              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
614              glVertex2d(tmpGlyph->width, 0);
615              glEnd();
616              glEndList();
617              SDL_FreeSurface(glyphSurf);
618
619              tmpRect.x += tmpGlyph->width + 2;
620
621              // Outputting Glyphs to BMP-files.
622              /*
623                char outname[64];
624                if (i < 10)
625                sprintf( outname, "glyph-00%d.bmp", i );
626                else if (i <100)
627                sprintf( outname, "glyph-0%d.bmp", i );
628                else
629                sprintf( outname, "glyph-%d.bmp", i );
630                SDL_SaveBMP(tmpSurf, outname);
631              */
632            }
633        }
634    }
635
636  GLuint texture;
637  glGenTextures(1, &texture);
638  glBindTexture(GL_TEXTURE_2D, texture);
639  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
640  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
641  glTexImage2D(GL_TEXTURE_2D,
642               0,
643               GL_RGBA,
644               tmpSurf->w, tmpSurf->h,
645               0,
646               GL_RGBA,
647               GL_UNSIGNED_BYTE,
648               tmpSurf->pixels);
649  SDL_FreeSurface(tmpSurf);
650  return texture;
651}
652
653/**
654 *  stores Glyph Metrics in an Array.
655 * @param from The Glyph to start from.
656 * @param count The number of Glyphs to start From.
657*/
658void Font::initGlyphs(Uint16 from, Uint16 count)
659{
660  /* initialize the Array, and set all its entries to NULL
661   *  only if the Glyph-array has not been initialized
662   */
663  if (!this->glyphArray)
664    {
665      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
666      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
667        this->glyphArray[i] = NULL;
668    }
669
670  Uint16 lastGlyph = from + count;
671
672  for (int i = from; i <= lastGlyph; i++)
673    {
674      // setting up all the Glyphs we like.
675      glyphArray[i] = getGlyphMetrics(i);
676    }
677  return;
678}
679
680/**
681 * @returns the optimal size to use as the texture size
682
683   @todo: this algorithm can be a lot more faster, althought it does
684   not really matter within the init-context, and 128 glyphs.
685
686   This function searches for a 2^n sizes texture-size, this is for
687   openGL-version < 1.2 compatibility ( and because it is realy easy like this :))
688*/
689int Font::findOptimalFastTextureSize()
690{
691  int i;
692  int x,y; // the counters
693  int maxLineHeight;
694  int size = 32;      // starting Value, we have to start somewhere 32 seems reasonable.
695  bool sizeOK = false;
696  Glyph* tmpGlyph;
697
698  while (!sizeOK)
699    {
700      x = 0; y = 0;
701      maxLineHeight = 0;
702      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
703        {
704          if(tmpGlyph = this->glyphArray[i])
705            {
706              // getting the height of the highest Glyph in the Line.
707              if (tmpGlyph->height > maxLineHeight)
708                maxLineHeight = tmpGlyph->height;
709
710              if (x + tmpGlyph->width > size)
711                {
712                  x = 0;
713                  y = y + maxLineHeight;
714                  maxLineHeight = 0;
715                }
716              if (y + maxLineHeight + 1 > size)
717                break;
718              x += tmpGlyph->width + 1;
719
720            }
721        }
722      if (i == FONT_HIGHEST_KNOWN_CHAR)
723        sizeOK = true;
724      else
725        size *= 2;
726    }
727  return size;
728}
729
730
731/**
732 *  a simple function to get some interesting information about this class
733*/
734void Font::debug()
735{
736  // print the loaded font's style
737  int style;
738  if (likely(this->font != NULL))
739    style = TTF_GetFontStyle(this->font);
740  PRINTF(0)("The font style is:");
741  if(style==TTF_STYLE_NORMAL)
742    PRINTF(0)(" normal");
743  else {
744    if(style&TTF_STYLE_BOLD)
745      PRINTF(0)(" bold");
746    if(style&TTF_STYLE_ITALIC)
747      PRINTF(0)(" italic");
748    if(style&TTF_STYLE_UNDERLINE)
749      PRINTF(0)(" underline");
750  }
751  PRINTF(0)("\n");
752}
753
754
755///////////////////
756/// TEXT-ENGINE ///
757///////////////////
758/**
759 *  standard constructor
760*/
761TextEngine::TextEngine ()
762{
763   this->setClassID(CL_TEXT_ENGINE, "TextEngine");
764   this->setName("TextEngine");
765   this->enableFonts();
766
767   this->textList = new tList<Text>;
768}
769
770/**
771 *  the singleton reference to this class
772*/
773TextEngine* TextEngine::singletonRef = NULL;
774
775/**
776 *  standard deconstructor
777
778*/
779TextEngine::~TextEngine ()
780{
781  this->disableFonts();
782
783  delete this->textList;
784
785  TextEngine::singletonRef = NULL;
786}
787
788/**
789 *  function to enable TTF_Fonts
790*/
791void TextEngine::enableFonts()
792{
793  if (!TTF_WasInit())
794    {
795      if(TTF_Init()==-1)
796        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
797
798      TextEngine::checkVersion();
799    }
800  else
801    PRINTF(4)("Fonts already initialized\n");
802}
803
804/**
805 *  function to disable TTF_fonts
806*/
807void TextEngine::disableFonts()
808{
809  if (TTF_WasInit())
810    {
811      TTF_Quit();
812    }
813  else
814    PRINTF(4)("Fonts were not initialized.\n");
815}
816
817/**
818 *  creates a new Text with a certain font.
819   \see Font::Font
820   \see Text::Text
821*/
822Text* TextEngine::createText(const char* fontFile, unsigned int fontSize, int textType, Uint8 r, Uint8 g, Uint8 b)
823{
824  Font* tmpFont;
825  Text* newText;
826  Vector tmpVec;
827
828  tmpVec = Vector(r, g, b);
829  tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, &fontSize, &tmpVec);
830  if (!tmpFont)
831    {
832      PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);
833      return NULL;
834    }
835
836  newText = new Text(tmpFont, TEXT_DYNAMIC);
837  textList->add(newText);
838
839  return newText;
840}
841
842/**
843 *  removes a Text from the List
844 * @param text: the text to delete
845
846   this only ereases allocated memory, and removes the text
847   The normal way to call it, is through "delete text;"
848   So you do not have to concetn yourselves with this.
849*/
850void TextEngine::deleteText(Text* text)
851{
852  textList->remove(text);
853}
854
855/**
856 *  deletes all the Text, and tries to delete all allocated fonts
857*/
858void TextEngine::flush()
859{
860  tIterator<Text>* textIterator = textList->getIterator();
861  Text* text = textIterator->nextElement();
862  while( text != NULL)
863    {
864      delete text;
865      text = textIterator->nextElement();
866    }
867  delete textIterator;
868}
869
870/**
871 *  outputs some nice Debug information
872
873   @todo there should also be something outputted about Font
874*/
875void TextEngine::debug() const
876{
877  PRINT(0)("+-------------------------------+\n");
878  PRINT(0)("+ TEXT ENGINE DEBUG INFORMATION +\n");
879  PRINT(0)("+-------------------------------+\n");
880  PRINT(0)("Reference: %p; Text Counts: %d\n", this, this->textList->getSize());
881
882  tIterator<Text>* textIterator = textList->getIterator();
883  Text* text = textIterator->nextElement();
884  while( text != NULL)
885    {
886      text->debug();
887      text = textIterator->nextElement();
888    }
889  delete textIterator;
890  PRINT(0)("+---------------------------TE--+\n");
891}
892
893
894/**
895 *  checks if the compiled version and the local version of SDL_ttf match.
896 * @returns true if match, false otherwise
897*/
898bool TextEngine::checkVersion()
899{
900  SDL_version compile_version;
901  SDL_version link_version;
902  TTF_VERSION(&compile_version);
903  link_version = *TTF_Linked_Version();
904
905  if (compile_version.major == link_version.major &&
906      compile_version.minor == link_version.minor &&
907      compile_version.patch == link_version.patch)
908    {
909      return true;
910    }
911  else
912    {
913      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n",
914                compile_version.major,
915                compile_version.minor,
916                compile_version.patch);
917
918      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n",
919                link_version.major,
920                link_version.minor,
921                link_version.patch);
922      return false;
923    }
924}
Note: See TracBrowser for help on using the repository browser.