Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/graphics/font/text_engine.cc @ 3769

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

orxonox/branches/textEngine: compiling again, many movements… still working

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