Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: a first command can be executed 'clear'
also improved the seg-fault-protection of the TextEngine

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