Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: GraphicsEngine now stores the glMatrices, when transforming into 2D-mode

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