Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/graphics/font/glfont.cc @ 3749

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

orxonox/branches/textEngine: now displays the real text

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