Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/openAL/src/lib/graphics/text_engine.cc @ 4195

Last change on this file since 4195 was 3911, checked in by bensch, 20 years ago

orxonox/trunk: minor changes at model

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