Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/graphics/font/text_engine.cc @ 3774

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

orxonox/branches/textEngine: debug() implemented

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