Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: text is now Rendered as expected (in FastMode)

File size: 23.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#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->loadFont(fontFile);
378
379  this->setStyle("c");//TTF_STYLE_NORMAL);
380
381  this->fastTextureID = this->createFastTexture();
382}
383
384/**
385 * destructs a font
386 * this releases the memory a font uses to be opened.
387*/
388Font::~Font()
389{
390  // deleting the List of all Texts
391
392  // deleting all Glyphs
393  if (this->glyphArray)
394    {
395      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
396        delete this->glyphArray[i];
397      delete[] this->glyphArray;
398    }
399
400  // erease this font out of the memory.
401  if (likely(this->font != NULL))
402    TTF_CloseFont(this->font);
403}
404
405/**
406 *  sets The Font.
407 * @param fontFile The file containing the font.
408 * @returns true if loaded, false if something went wrong, or if a font was loaded before.
409*/
410bool Font::loadFont(const char* fontFile)
411{
412  if (!this->fontFile)
413    {
414      this->setName(fontFile);
415      this->fontFile = new char[strlen(fontFile)+1];
416      strcpy(this->fontFile, fontFile);
417
418      this->font = TTF_OpenFont(this->fontFile, this->fontSize);
419      if(!this->font)
420        {
421          PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());
422          return false;
423        }
424      else
425          return true;
426    }
427  else
428    {
429      PRINTF(2)("Font already initialized, unable to change it now.\n");
430      return false;
431    }
432}
433
434/**
435 *  sets a specific renderStyle
436 * @param renderStyle the Style to render: a char-array containing:
437   i: italic, b: bold, u, underline
438*/
439void Font::setStyle(const char* renderStyle)
440{
441  this->renderStyle = TTF_STYLE_NORMAL;
442
443  for (int i = 0; i < strlen(renderStyle); i++)
444    if (strncmp(renderStyle+i, "b", 1) == 0)
445      this->renderStyle |= TTF_STYLE_BOLD;
446    else if (strncmp(renderStyle+i, "i", 1) == 0)
447      this->renderStyle |= TTF_STYLE_ITALIC;
448    else if (strncmp(renderStyle+i, "u", 1) == 0)
449      this->renderStyle |= TTF_STYLE_UNDERLINE;
450
451  if (likely(this->font != NULL))
452    TTF_SetFontStyle(this->font, this->renderStyle);
453  else
454    PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");
455}
456
457/**
458 *  Sets a new Size to the font
459 * @param fontSize The new Size in pixels.
460*/
461void Font::setSize(unsigned int fontSize)
462{
463  this->fontSize = fontSize;
464}
465
466/**
467 * @returns the maximum height of the Font, if the font was initialized, 0 otherwise
468*/
469int Font::getMaxHeight()
470{
471  if (likely (this->font != NULL))
472    return TTF_FontHeight(this->font);
473  else
474    return 0;
475}
476
477/**
478 * @returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
479
480   the ascent is the pixels of the font above the baseline
481*/
482int Font::getMaxAscent()
483{
484  if (likely(this->font != NULL))
485    return TTF_FontAscent(this->font);
486  else
487    return 0;
488}
489
490/**
491 * @returns the maximum descent of the Font, if the font was initialized, 0 otherwise
492
493   the descent is the pixels of the font below the baseline
494*/
495int Font::getMaxDescent()
496{
497  if (likely(this->font != NULL))
498    return TTF_FontDescent(this->font);
499  else
500    return 0;
501}
502
503/**
504 * @param character The character to get info about.
505 * @returns a Glyph struct of a character. This Glyph is a pointer,
506   and MUST be deleted by the user..
507
508   This only works for horizontal fonts. see
509   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
510   for more info about vertical Fonts
511*/
512Glyph* Font::getGlyphMetrics(Uint16 character)
513{
514  Glyph* rg = new Glyph;
515  rg->character = character;
516  if (likely (this->font!= NULL))
517    TTF_GlyphMetrics(this->font, rg->character,
518                     &rg->minX, &rg->maxX,
519                     &rg->minY, &rg->maxY,
520                     &rg->advance);
521  rg->height = rg->maxY - rg->minY;
522  rg->width = rg->maxX - rg->minX;
523  rg->bearingX = (rg->advance - rg->width) / 2;
524  rg->bearingY = rg->maxY;
525  return rg;
526}
527
528GLuint Font::createFastTexture()
529{
530  /* interesting GLYPHS:
531   *  32: space
532   *  33-47: Special Characters.
533   *  48-57: 0-9
534   *  58-63: some more special chars (minor)
535   *  65-90: A-Z
536   *  97-122: a-z
537   */
538  int numberOfGlyphs = 91;
539
540  this->initGlyphs(32, numberOfGlyphs);
541  this->glyphArray[32]->width = fontSize/2; //!< @todo find out the real size of a Space
542
543  int rectSize = this->findOptimalFastTextureSize();
544
545  // setting default values. (maybe not needed afterwards)
546  SDL_Color tmpColor;  tmpColor.r = tmpColor.g = tmpColor.b = 0;
547  // Surface definition.
548  SDL_Rect tmpRect; // this represents a Rectangle for blitting.
549  SDL_Surface* tmpSurf =  SDL_CreateRGBSurface(SDL_SWSURFACE,
550                                               rectSize, rectSize,
551                                               32,
552#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
553                                               0x000000FF,
554                                               0x0000FF00,
555                                               0x00FF0000,
556                                               0xFF000000
557#else
558                                               0xFF000000,
559                                               0x00FF0000,
560                                               0x0000FF00,
561                                               0x000000FF
562#endif
563                                               );
564  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
565  SDL_SetClipRect(tmpSurf, &tmpRect);
566  int maxLineHeight = 0;
567
568  // all the interessting Glyphs
569  for (int i = 0; i <= 127; i++)
570    {
571      SDL_Surface* glyphSurf = NULL;
572      Glyph* tmpGlyph;
573
574      if (tmpGlyph = this->glyphArray[i])
575        {
576          if (tmpGlyph->height > maxLineHeight)
577            maxLineHeight = tmpGlyph->height;
578
579          if (tmpRect.x+tmpGlyph->advance > tmpSurf->w)
580            {
581              tmpRect.x = 0;
582              tmpRect.y = tmpRect.y + maxLineHeight + 1;
583              maxLineHeight = 0;
584            }
585          if (tmpRect.y + maxLineHeight > tmpSurf->h)
586            {
587              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
588              break;
589            }
590          // reading in the new Glyph
591          if (likely(this->font != NULL))
592          {
593            SDL_Color white = {255, 255, 255};
594            glyphSurf = TTF_RenderGlyph_Blended(this->font, i, white);
595          }
596          if( glyphSurf != NULL )
597            {
598              SDL_SetAlpha(glyphSurf, 0, 0);
599
600              SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);
601              TexCoord tmpTexCoord;
602              tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;
603              tmpTexCoord.maxU = (float)(tmpRect.x + tmpGlyph->advance)/(float)tmpSurf->w;
604              tmpTexCoord.minV = (float)(tmpRect.y)/(float)tmpSurf->w;
605              tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;
606              tmpGlyph->displayList = glGenLists(1);
607
608              glNewList(tmpGlyph->displayList, GL_COMPILE);
609              glBegin(GL_QUADS);
610              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);
611              glVertex2d(0, - tmpGlyph->bearingY);
612              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
613              glVertex2d(0, tmpGlyph->height - tmpGlyph->bearingY);
614              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
615              glVertex2d(tmpGlyph->width, tmpGlyph->height - tmpGlyph->bearingY);
616              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
617              glVertex2d(tmpGlyph->width, - tmpGlyph->bearingY);
618              glEnd();
619              glEndList();
620              SDL_FreeSurface(glyphSurf);
621
622              tmpRect.x += tmpGlyph->advance;
623
624              // Outputting Glyphs to BMP-files.
625/*
626                char outname[512];
627                if (i < 10)
628                sprintf( outname, "%s-glyph-00%d.bmp", this->getName(), i );
629                else if (i <100)
630                  sprintf( outname, "%s-glyph-0%d.bmp", this->getName(), i );
631                else
632                  sprintf( outname, "%s-glyph-%d.bmp", this->getName(), i );
633                SDL_SaveBMP(tmpSurf, outname);*/
634
635            }
636        }
637    }
638
639  GLuint texture;
640  glGenTextures(1, &texture);
641  glBindTexture(GL_TEXTURE_2D, texture);
642  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
643  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
644  glTexImage2D(GL_TEXTURE_2D,
645               0,
646               GL_RGBA,
647               tmpSurf->w, tmpSurf->h,
648               0,
649               GL_RGBA,
650               GL_UNSIGNED_BYTE,
651               tmpSurf->pixels);
652  SDL_FreeSurface(tmpSurf);
653  return texture;
654}
655
656/**
657 *  stores Glyph Metrics in an Array.
658 * @param from The Glyph to start from.
659 * @param count The number of Glyphs to start From.
660*/
661void Font::initGlyphs(Uint16 from, Uint16 count)
662{
663  /* initialize the Array, and set all its entries to NULL
664   *  only if the Glyph-array has not been initialized
665   */
666  if (!this->glyphArray)
667    {
668      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
669      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
670        this->glyphArray[i] = NULL;
671    }
672
673  Uint16 lastGlyph = from + count;
674
675  for (int i = from; i <= lastGlyph; i++)
676    {
677      // setting up all the Glyphs we like.
678      glyphArray[i] = getGlyphMetrics(i);
679    }
680  return;
681}
682
683/**
684 * @returns the optimal size to use as the texture size
685
686   @todo: this algorithm can be a lot more faster, althought it does
687   not really matter within the init-context, and 128 glyphs.
688
689   This function searches for a 2^n sizes texture-size, this is for
690   openGL-version < 1.2 compatibility ( and because it is realy easy like this :))
691*/
692int Font::findOptimalFastTextureSize()
693{
694  int i;
695  int x,y; // the counters
696  int maxLineHeight = this->getMaxHeight();
697  unsigned int size = 32;  // starting Value, we have to start somewhere 32 seems reasonable. (take any small enough 2^i number)
698  bool sizeOK = false;
699  Glyph* tmpGlyph;
700
701  while (!sizeOK)
702    {
703      x = 0; y = 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->advance > size)
713                {
714                  x = 0;
715                  y = y + maxLineHeight;
716                  //maxLineHeight = 0;
717                }
718              if (y + maxLineHeight + 1 > size)
719                break;
720              x += tmpGlyph->advance;
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.