Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3836 was 3833, checked in by bensch, 20 years ago

orxonox/trunk: animation can now return the BaseObject it operates on

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