Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: color is now a parameter of text not font

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