Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/textEngine: little patch, so now 'space' works too

File size: 22.3 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   *  32: space
429   *  33-47: Special Characters.
430   *  48-57: 0-9
431   *  58-63: some more special chars (minor)
432   *  65-90: A-Z
433   *  97-122: a-z
434   */
435  int numberOfGlyphs = 91;
436
437  this->initGlyphs(32, numberOfGlyphs);
438  this->glyphArray[32]->width = fontSize/3; //!< \todo find out the real size of a Space
439
440  int rectSize = this->findOptimalFastTextureSize();
441
442  // setting default values. (maybe not needed afterwards)
443  SDL_Color tmpColor;  tmpColor.r = tmpColor.g = tmpColor.b = 0;
444  // Surface definition.
445  SDL_Rect tmpRect; // this represents a Rectangle for blitting.
446  SDL_Surface* tmpSurf =  SDL_CreateRGBSurface(SDL_SWSURFACE,
447                                               rectSize, rectSize,
448                                               32,
449#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
450                                               0x000000FF, 
451                                               0x0000FF00, 
452                                               0x00FF0000, 
453                                               0xFF000000
454#else
455                                               0xFF000000,
456                                               0x00FF0000, 
457                                               0x0000FF00, 
458                                               0x000000FF
459#endif
460                                               );
461  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
462  SDL_SetClipRect(tmpSurf, &tmpRect);
463  int maxLineHeight = 0;
464
465  // all the interessting Glyphs
466  for (int i = 32; i <= 122; i++)
467    {
468      SDL_Surface* glyphSurf = NULL;
469      Glyph* tmpGlyph;
470
471      if (tmpGlyph = this->glyphArray[i])
472        {
473          if (tmpGlyph->height > maxLineHeight)
474            maxLineHeight = tmpGlyph->height;
475         
476          if (tmpRect.x+tmpGlyph->width > tmpSurf->w)
477            {
478              tmpRect.x = 0;
479              tmpRect.y = tmpRect.y + maxLineHeight + 1;
480              maxLineHeight = 0;
481            }
482          if (tmpRect.y + maxLineHeight > tmpSurf->h)
483            {
484              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
485              break;
486            }
487          // reading in the new Glyph
488          glyphSurf = TTF_RenderGlyph_Blended(this->font, i, this->fastColor);
489          if( glyphSurf ) 
490            {
491
492              SDL_SetAlpha(glyphSurf, 0, 0);
493
494              SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);
495              TexCoord tmpTexCoord;
496              tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;
497              tmpTexCoord.maxU = (float)(tmpRect.x+tmpGlyph->width)/(float)tmpSurf->w;
498              tmpTexCoord.minV = (float)tmpRect.y/(float)tmpSurf->w;
499              tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;
500              tmpGlyph->displayList = glGenLists(1);
501
502              glNewList(tmpGlyph->displayList, GL_COMPILE);
503              glBegin(GL_QUADS);
504              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);
505              glVertex2d(0, 0);
506              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
507              glVertex2d(0, tmpGlyph->height);
508              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
509              glVertex2d(tmpGlyph->width, tmpGlyph->height);
510              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
511              glVertex2d(tmpGlyph->width, 0);
512              glEnd();
513              glEndList();
514              SDL_FreeSurface(glyphSurf);
515
516              tmpRect.x += tmpGlyph->width + 1;
517
518              // Outputting Glyphs to BMP-files.
519              /*
520                char outname[64];
521                if (i < 10)
522                sprintf( outname, "glyph-00%d.bmp", i );
523                else if (i <100)
524                sprintf( outname, "glyph-0%d.bmp", i );
525                else
526                sprintf( outname, "glyph-%d.bmp", i );
527                SDL_SaveBMP(tmpSurf, outname);
528              */
529            }
530        }
531    }
532
533  GLuint texture;
534  glGenTextures(1, &texture);
535  glBindTexture(GL_TEXTURE_2D, texture);
536  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
537  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
538  glTexImage2D(GL_TEXTURE_2D,
539               0,
540               GL_RGBA,
541               tmpSurf->w, tmpSurf->h,
542               0,
543               GL_RGBA,
544               GL_UNSIGNED_BYTE,
545               tmpSurf->pixels);
546  SDL_FreeSurface(tmpSurf);
547  return texture;
548}
549
550/**
551   \brief stores Glyph Metrics in an Array.
552   \param from The Glyph to start from.
553   \param count The number of Glyphs to start From.
554*/
555void Font::initGlyphs(Uint16 from, Uint16 count)
556{
557  /* initialize the Array, and set all its entries to NULL
558   *  only if the Glyph-array has not been initialized
559   */
560  if (!this->glyphArray)
561    {
562      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
563      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
564        this->glyphArray[i] = NULL;
565    }
566 
567  Uint16 lastGlyph = from + count;
568 
569  for (int i = from; i <= lastGlyph; i++)
570    {
571      // setting up all the Glyphs we like.
572      glyphArray[i] = getGlyphMetrics(i);
573    }
574  return;
575}
576
577/**
578   \returns the optimal size to use as the texture size
579
580   \todo: this algorithm can be a lot more faster, althought it does
581   not really matter within the init-context, and 128 glyphs.
582
583   This function searches for a 2^n sizes texture-size, this is for
584   openGL-version < 1.2 compatibility. and because it is realy easy like this.
585*/
586int Font::findOptimalFastTextureSize(void)
587{
588  int i;
589  int x,y; // the counters
590  int maxLineHeight;
591  int size = 32;      // starting Value, we have to start somewhere 32 seems reasonable.
592  bool sizeOK = false;
593  Glyph* tmpGlyph;
594
595  while (!sizeOK)
596    {
597      x = 0; y = 0;
598      maxLineHeight = 0;
599      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
600        {
601          if(tmpGlyph = this->glyphArray[i])
602            {
603              // getting the height of the highest Glyph in the Line.
604              if (tmpGlyph->height > maxLineHeight)
605                maxLineHeight = tmpGlyph->height;
606
607              if (x + tmpGlyph->width > size)
608                {
609                  x = 0;
610                  y = y + maxLineHeight;
611                  maxLineHeight = 0;
612                }
613              if (y + maxLineHeight + 1 > size)
614                break;
615              x += tmpGlyph->width + 1;
616
617            }
618        }
619      if (i == FONT_HIGHEST_KNOWN_CHAR)
620        sizeOK = true;
621      else
622        size *= 2;
623    }
624  return size;
625 
626}
627
628
629/**
630   \brief a simple function to get some interesting information about this class
631*/
632void Font::debug(void)
633{
634
635  // print the loaded font's style
636  int style;
637  style = TTF_GetFontStyle(this->font);
638  PRINTF(0)("The font style is:");
639  if(style==TTF_STYLE_NORMAL)
640    PRINTF(0)(" normal");
641  else {
642    if(style&TTF_STYLE_BOLD)
643      PRINTF(0)(" bold");
644    if(style&TTF_STYLE_ITALIC)
645      PRINTF(0)(" italic");
646    if(style&TTF_STYLE_UNDERLINE)
647      PRINTF(0)(" underline");
648  }
649  PRINTF(0)("\n");
650
651
652}
653
654////////////
655/// UTIL ///
656////////////
657/**
658   \brief Loads a Font from an SDL_surface into a texture.
659   \param surface The surface to make the texture of
660   \param texCoord The texture coordinates of the 4 corners of the texture
661   \returns the ID of the texture
662*/
663GLuint loadTexture(SDL_Surface *surface, TexCoord* texCoord)
664{
665  GLuint texture;
666  int w, h;
667  SDL_Surface *image;
668  SDL_Rect area;
669  Uint32 saved_flags;
670  Uint8  saved_alpha;
671 
672  /* Use the surface width and height expanded to powers of 2 */
673  w = powerOfTwo(surface->w);
674  h = powerOfTwo(surface->h);
675  if (texCoord)
676    {
677      texCoord->minU = 0.0f;
678      texCoord->minV = 0.0f;
679      texCoord->maxU = (GLfloat)surface->w / w;
680      texCoord->maxV = (GLfloat)surface->h / h;
681    }
682  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
683                               w, h,
684                               32,
685#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
686                               0x000000FF, 
687                               0x0000FF00, 
688                               0x00FF0000, 
689                               0xFF000000
690#else
691                               0xFF000000,
692                               0x00FF0000, 
693                               0x0000FF00, 
694                               0x000000FF
695#endif
696                               );
697  if ( image == NULL ) {
698    return 0;
699  }
700 
701  /* Save the alpha blending attributes */
702  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
703  saved_alpha = surface->format->alpha;
704  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
705    SDL_SetAlpha(surface, 0, 0);
706  }
707 
708  /* Copy the surface into the GL texture image */
709  area.x = 0;
710  area.y = 0;
711  area.w = surface->w;
712  area.h = surface->h;
713  SDL_BlitSurface(surface, &area, image, &area);
714 
715  /* Restore the alpha blending attributes */
716  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
717    SDL_SetAlpha(surface, saved_flags, saved_alpha);
718  }
719 
720  /* Create an OpenGL texture for the image */
721  glGenTextures(1, &texture);
722  glBindTexture(GL_TEXTURE_2D, texture);
723  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
724  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
725  glTexImage2D(GL_TEXTURE_2D,
726               0,
727               GL_RGBA,
728               w, h,
729               0,
730               GL_RGBA,
731               GL_UNSIGNED_BYTE,
732               image->pixels);
733  SDL_FreeSurface(image); /* No longer needed */
734 
735  return texture;
736}
737
738/**
739   \brief Quick utility function for texture creation
740   \param input an integer
741   \returns the next bigger 2^n-integer than input
742*/
743int powerOfTwo(int input)
744{
745  int value = 1;
746 
747  while ( value < input ) {
748    value <<= 1;
749  }
750  return value;
751}
752
753
754
755
756
757
758///////////////////
759/// TEXT-ENGINE ///
760///////////////////
761/**
762   \brief standard constructor
763*/
764TextEngine::TextEngine () 
765{
766   this->setClassName ("TextEngine");
767   this->enableFonts();
768
769   this->textList = new tList<Text>;
770}
771
772/**
773   \brief the singleton reference to this class
774*/
775TextEngine* TextEngine::singletonRef = NULL;
776
777/**
778   \returns a Pointer to this Class
779*/
780TextEngine* TextEngine::getInstance(void)
781{
782  if (!TextEngine::singletonRef)
783    TextEngine::singletonRef = new TextEngine();
784  return TextEngine::singletonRef;
785}
786
787/**
788   \brief standard deconstructor
789
790*/
791TextEngine::~TextEngine () 
792{
793  this->disableFonts();
794 
795  delete this->textList;
796
797  TextEngine::singletonRef = NULL;
798
799}
800
801/**
802   \brief function to enable TTF_Fonts
803*/
804void TextEngine::enableFonts(void)
805{
806  if (!TTF_WasInit())
807    {
808      if(TTF_Init()==-1)
809        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
810
811      TextEngine::checkVersion();
812    }
813  else
814    PRINTF(4)("Fonts already initialized\n");
815}
816
817/**
818   \brief function to disable TTF_fonts
819*/
820void TextEngine::disableFonts(void)
821{
822  if (TTF_WasInit())
823    {
824      TTF_Quit();
825    }
826  else
827    PRINTF(4)("Fonts were not initialized.\n");
828}
829
830/**
831   \brief creates a new Text with a certain font.
832   \see Font::Font
833   \see Text::Text
834*/
835Text* TextEngine::createText(const char* fontFile, unsigned int fontSize, int textType, Uint8 r, Uint8 g, Uint8 b)
836{
837  Font* tmpFont;
838  Text* newText;
839  Vector tmpVec;
840
841  tmpVec = Vector(r, g, b);
842  tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, &fontSize, &tmpVec);
843  if (!tmpFont)
844    {
845      PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);
846      return NULL;
847    }
848
849  newText = new Text(tmpFont, TEXT_DYNAMIC);
850  textList->add(newText);
851
852  return newText;
853}
854
855/**
856   \brief removes a Text from the List
857   \param the text to delete
858
859   this only ereases allocated memory, and removes the text
860   The normal way to call it, is through "delete text;"
861   So you do not have to concetn yourselves with this.
862*/
863void TextEngine::deleteText(Text* text)
864{
865  ResourceManager::getInstance()->unload(text->font);
866  textList->remove(text);
867}
868
869/**
870   \brief deletes all the Text, and tries to delete all allocated fonts
871*/
872void TextEngine::flush(void)
873{
874  tIterator<Text>* textIterator = textList->getIterator();
875  Text* text = textIterator->nextElement();
876  while( text != NULL)
877    {
878      delete text;
879      text = textIterator->nextElement();
880    }
881  delete textIterator;
882}
883
884/**
885   \brief draws all the Texts that have been initialized
886*/
887void TextEngine::draw(void) const
888{
889  tIterator<Text>* textIterator = textList->getIterator();
890  Text* text = textIterator->nextElement();
891  while( text != NULL)
892    {
893      text->draw();
894      text = textIterator->nextElement();
895    }
896  delete textIterator;
897}
898
899/**
900   \brief outputs some nice Debug information
901   
902   \todo there should also be something outputted about Font
903*/
904void TextEngine::debug(void) const
905{
906  PRINT(0)("+-------------------------------+\n");
907  PRINT(0)("+ TEXT ENGINE DEBUG INFORMATION +\n");
908  PRINT(0)("+-------------------------------+\n");
909  PRINT(0)("Reference: %p; Text Counts: %d\n", this, this->textList->getSize());
910 
911  tIterator<Text>* textIterator = textList->getIterator();
912  Text* text = textIterator->nextElement();
913  while( text != NULL)
914    {
915      text->debug();
916      text = textIterator->nextElement();
917    }
918  delete textIterator;
919  PRINT(0)("+---------------------------TE--+\n");
920}
921
922
923/**
924   \brief checks if the compiled version and the local version of SDL_ttf match.
925   \returns true if match, false otherwise
926*/
927bool TextEngine::checkVersion(void)
928{
929  SDL_version compile_version;
930  SDL_version link_version;
931  TTF_VERSION(&compile_version);
932  link_version = *TTF_Linked_Version();
933
934  if (compile_version.major == link_version.major &&
935      compile_version.minor == link_version.minor &&
936      compile_version.patch == link_version.patch)
937    {
938      return true;
939    }
940  else
941    {
942      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n", 
943                compile_version.major,
944                compile_version.minor,
945                compile_version.patch);
946     
947      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n", 
948                link_version.major,
949                link_version.minor,
950                link_version.patch);
951      return false;
952    }
953}
Note: See TracBrowser for help on using the repository browser.