Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: optimized TextEngine, now the chars can also be copied fast by using a const char-pointer instead of copiing the whole text-array

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->posSize.w = 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->posSize.w = tmpSurf->w;
171  this->posSize.h = 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->posSize.w, 0, 0);
184  else if (this->getAlignment() == TEXT_ALIGN_CENTER || this->getAlignment() == TEXT_ALIGN_SCREEN_CENTER)
185    glTranslatef(-this->posSize.w/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->posSize.w, this->getAbsCoor2D().);
226
227      glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);
228      glVertex2f(this->getAbsCoor2D().x + this->posSize.w, getAbsCoor2D().y + this->posSize.h);
229
230      glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);
231      glVertex2f(getAbsCoor2D().x, getAbsCoor2D().y + this->posSize.h);
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)("Relative Position: (%d::%d)\n", this->posSize.x, this->posSize.y);
252  PRINT(0)("Color: %0.2f %0.2f %0.2f\n", this->color.x, this->color.y, this->color.z);
253}
254
255
256////////////
257/// UTIL ///
258////////////
259/**
260 *  Loads a Font from an SDL_surface into a texture.
261 * @param surface The surface to make the texture of
262 * @param texCoord The texture coordinates of the 4 corners of the texture
263 * @returns the ID of the texture
264*/
265GLuint Text::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
266{
267  GLuint texture;
268  int w, h;
269  SDL_Surface *image;
270  SDL_Rect area;
271  Uint32 saved_flags;
272  Uint8  saved_alpha;
273
274  /* Use the surface width and height expanded to powers of 2 */
275  w = powerOfTwo(surface->w);
276  h = powerOfTwo(surface->h);
277  if (texCoord)
278    {
279      texCoord->minU = 0.0f;
280      texCoord->minV = 0.0f;
281      texCoord->maxU = (GLfloat)surface->w / w;
282      texCoord->maxV = (GLfloat)surface->h / h;
283    }
284  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
285                               w, h,
286                               32,
287#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
288                               0x000000FF,
289                               0x0000FF00,
290                               0x00FF0000,
291                               0xFF000000
292#else
293                               0xFF000000,
294                               0x00FF0000,
295                               0x0000FF00,
296                               0x000000FF
297#endif
298                               );
299  if ( image == NULL ) {
300    return 0;
301  }
302
303  /* Save the alpha blending attributes */
304  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
305  saved_alpha = surface->format->alpha;
306  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
307    SDL_SetAlpha(surface, 0, 0);
308  }
309
310  /* Copy the surface into the GL texture image */
311  area.x = 0;
312  area.y = 0;
313  area.w = surface->w;
314  area.h = surface->h;
315  SDL_BlitSurface(surface, &area, image, &area);
316
317  /* Restore the alpha blending attributes */
318  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
319    SDL_SetAlpha(surface, saved_flags, saved_alpha);
320  }
321
322  /* Create an OpenGL texture for the image */
323  glGenTextures(1, &texture);
324  glBindTexture(GL_TEXTURE_2D, texture);
325  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
326  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
327  glTexImage2D(GL_TEXTURE_2D,
328               0,
329               GL_RGBA,
330               w, h,
331               0,
332               GL_RGBA,
333               GL_UNSIGNED_BYTE,
334               image->pixels);
335  SDL_FreeSurface(image); /* No longer needed */
336
337  return texture;
338}
339
340/**
341 *  Quick utility function for texture creation
342 * @param input an integer
343 * @returns the next bigger 2^n-integer than input
344*/
345int Text::powerOfTwo(int input)
346{
347  int value = 1;
348
349  while ( value < input ) {
350    value <<= 1;
351  }
352  return value;
353}
354
355
356////////////
357/// FONT ///
358////////////
359/**
360 *  constructs a Font
361 * @param fontFile the File to load the font from
362 * @param fontSize the Size of the Font in Pixels
363 * @param r Red value of the Font.
364 * @param g Green value of the Font.
365 * @param b Blue value of the Font.
366*/
367Font::Font(const char* fontFile, unsigned int fontSize)
368{
369  this->setClassID(CL_FONT, "Font");
370  // setting default values.
371  this->font = NULL;
372  this->fontFile = NULL;
373  this->glyphArray = NULL;
374  this->fastTextureID = 0;
375
376  this->setSize(fontSize);
377
378  this->setFont(fontFile);
379
380  this->setStyle("c");//TTF_STYLE_NORMAL);
381
382  this->fastTextureID = this->createFastTexture();
383}
384
385/**
386 *  destructs a font
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::setFont(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->width > 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 +1 + tmpGlyph->width)/(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, 0);
612              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
613              glVertex2d(0, tmpGlyph->height);
614              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
615              glVertex2d(tmpGlyph->width, tmpGlyph->height);
616              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
617              glVertex2d(tmpGlyph->width, 0);
618              glEnd();
619              glEndList();
620              SDL_FreeSurface(glyphSurf);
621
622              tmpRect.x += tmpGlyph->width + 2;
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;
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      maxLineHeight = 0;
705      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
706        {
707          if(tmpGlyph = this->glyphArray[i])
708            {
709              // getting the height of the highest Glyph in the Line.
710              if (tmpGlyph->height > maxLineHeight)
711                maxLineHeight = tmpGlyph->height;
712
713              if (x + tmpGlyph->width > size)
714                {
715                  x = 0;
716                  y = y + maxLineHeight;
717                  //maxLineHeight = 0;
718                }
719              if (y + maxLineHeight + 1 > size)
720                break;
721              x += tmpGlyph->width + 1;
722
723            }
724        }
725      if (i == FONT_HIGHEST_KNOWN_CHAR)
726        sizeOK = true;
727      else
728        size *= 2;
729    }
730  return size;
731}
732
733
734/**
735 *  a simple function to get some interesting information about this class
736*/
737void Font::debug()
738{
739  // print the loaded font's style
740  int style;
741  if (likely(this->font != NULL))
742    style = TTF_GetFontStyle(this->font);
743  PRINTF(0)("The font style is:");
744  if(style==TTF_STYLE_NORMAL)
745    PRINTF(0)(" normal");
746  else {
747    if(style&TTF_STYLE_BOLD)
748      PRINTF(0)(" bold");
749    if(style&TTF_STYLE_ITALIC)
750      PRINTF(0)(" italic");
751    if(style&TTF_STYLE_UNDERLINE)
752      PRINTF(0)(" underline");
753  }
754  PRINTF(0)("\n");
755}
756
757
758///////////////////
759/// TEXT-ENGINE ///
760///////////////////
761/**
762 *  standard constructor
763*/
764TextEngine::TextEngine ()
765{
766   this->setClassID(CL_TEXT_ENGINE, "TextEngine");
767   this->setName("TextEngine");
768   this->enableFonts();
769}
770
771/**
772 *  the singleton reference to this class
773*/
774TextEngine* TextEngine::singletonRef = NULL;
775
776/**
777 *  standard deconstructor
778
779*/
780TextEngine::~TextEngine ()
781{
782  this->disableFonts();
783
784  TextEngine::singletonRef = NULL;
785}
786
787/**
788 *  function to enable TTF_Fonts
789*/
790void TextEngine::enableFonts()
791{
792  if (!TTF_WasInit())
793    {
794      if(TTF_Init()==-1)
795        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
796
797      TextEngine::checkVersion();
798    }
799  else
800    PRINTF(4)("Fonts already initialized\n");
801}
802
803/**
804 *  function to disable TTF_fonts
805*/
806void TextEngine::disableFonts()
807{
808  if (TTF_WasInit())
809    {
810      TTF_Quit();
811    }
812  else
813    PRINTF(4)("Fonts were not initialized.\n");
814}
815
816/**
817 *  creates a new Text with a certain font.
818   @see Font::Font
819   @see Text::Text
820*/
821Text* TextEngine::createText(const char* fontFile, unsigned int fontSize, int textType)
822{
823  Font* tmpFont;
824  Text* newText;
825  Vector tmpVec;
826
827  tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, &fontSize);
828  if (!tmpFont)
829    {
830      PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);
831      return NULL;
832    }
833  else
834    return new Text(tmpFont, TEXT_RENDER_DYNAMIC);
835}
836
837/**
838 *  outputs some nice Debug information
839
840   @todo there should also be something outputted about Font
841*/
842void TextEngine::debug() const
843{
844  PRINT(0)("+-------------------------------+\n");
845  PRINT(0)("+ TEXT ENGINE DEBUG INFORMATION +\n");
846  PRINT(0)("+-------------------------------+\n");
847  PRINT(0)("Reference: %p; Text Counts: %d\n", this, ClassList::getList(CL_TEXT)->getSize());
848
849  tIterator<BaseObject>* textIterator = ClassList::getList(CL_TEXT)->getIterator();
850  Text* text = dynamic_cast<Text*>(textIterator->firstElement());
851  while( text != NULL)
852    {
853      text->debug();
854      text = dynamic_cast<Text*>(textIterator->nextElement());
855    }
856  delete textIterator;
857  PRINT(0)("+---------------------------TE--+\n");
858}
859
860
861/**
862 *  checks if the compiled version and the local version of SDL_ttf match.
863 * @returns true if match, false otherwise
864*/
865bool TextEngine::checkVersion()
866{
867  SDL_version compile_version;
868  SDL_version link_version;
869  TTF_VERSION(&compile_version);
870  link_version = *TTF_Linked_Version();
871
872  if (compile_version.major == link_version.major &&
873      compile_version.minor == link_version.minor &&
874      compile_version.patch == link_version.patch)
875    {
876      return true;
877    }
878  else
879    {
880      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n",
881                compile_version.major,
882                compile_version.minor,
883                compile_version.patch);
884
885      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n",
886                link_version.major,
887                link_version.minor,
888                link_version.patch);
889      return false;
890    }
891}
Note: See TracBrowser for help on using the repository browser.