Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: alignment for text implemented

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