Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3809 was 3790, checked in by bensch, 20 years ago

orxonox/trunk: merged the textEngine back into the trunk.
merged with command:
svn merge -r 3681:HEAD branches/textEngine/ trunk/

conflicts in:
world.cc/h orxonox.cc NEWS
changed in favor of the trunk

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