Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: redirected all printf-output to the shell
This is just for testing purposes, and will be changed again in the future (perhaps)

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