Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: patches, to make TextEngine more intuitive

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