Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/textEngine: now the Glyph is transparent

File size: 21.3 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   ***
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      glCallList(glyphArray[65]->displayList);
315    }
316  this->leave2DMode();
317}
318
319/**
320   \brief creates a texture out of the given parameters
321
322   this has to be called every time by the user, to if changes were made.
323*/
324void GLFont::createTexture(void)
325{
326  SDL_Surface* tmpSurf;
327  if (this->currentText->texture)
328    glDeleteTextures(1, &this->currentText->texture);
329  tmpSurf = TTF_RenderText_Blended(this->font,
330                                   this->currentText->text,
331                                   this->currentText->color);
332  if (tmpSurf)
333    this->currentText->texture = loadTexture(tmpSurf, &this->currentText->texCoord);
334
335  this->currentText->textPosSize.w = tmpSurf->w;
336  this->currentText->textPosSize.h = tmpSurf->h;
337  SDL_FreeSurface(tmpSurf);
338}
339
340
341/**
342   \returns the maximum height of the Font, if the font was initialized, 0 otherwise
343*/
344int GLFont::getMaxHeight(void)
345{
346  if (this->font)
347    return TTF_FontHeight(this->font);
348  else
349    return 0;
350}
351
352/**
353   \returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
354
355   the ascent is the pixels of the font above the baseline
356*/
357int GLFont::getMaxAscent(void)
358{
359  if (this->font)
360    return TTF_FontAscent(this->font);
361  else
362    return 0;
363}
364
365/**
366   \returns the maximum descent of the Font, if the font was initialized, 0 otherwise
367
368   the descent is the pixels of the font below the baseline
369*/
370int GLFont::getMaxDescent(void)
371{
372  if (this->font)
373    return TTF_FontDescent(this->font);
374  else
375    return 0;
376}
377
378/**
379   \param character The character to get info about.
380   \returns a Glyph struct of a character. This Glyph is a pointer,
381   and MUST be deleted by the user..
382
383   This only works for horizontal fonts. see
384   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
385   for more info about vertical Fonts
386*/
387Glyph* GLFont::getGlyphMetrics(Uint16 character)
388{
389  Glyph* rg = new Glyph;
390  rg->character = character;
391  TTF_GlyphMetrics(this->font, rg->character,
392                   &rg->minX, &rg->maxX,
393                   &rg->minY, &rg->maxY,
394                   &rg->advance);
395  rg->height = rg->maxY - rg->minY;
396  rg->width = rg->maxX - rg->minX;
397  rg->bearingX = (rg->advance - rg->width) / 2;
398  rg->bearingY = rg->maxY;
399  return rg;
400}
401
402/**
403   \brief entering 2D Mode
404   
405   this is a GL-Projection-mode, that is orthogonal, for placing the font in fron of everything else
406*/
407void GLFont::enter2DMode(void)
408{
409  SDL_Surface *screen = SDL_GetVideoSurface();
410 
411  /* Note, there may be other things you need to change,
412     depending on how you have your OpenGL state set up.
413  */
414  glPushAttrib(GL_ENABLE_BIT);
415  glDisable(GL_DEPTH_TEST);
416  glDisable(GL_CULL_FACE);
417  glDisable(GL_LIGHTING);  // will be set back when leaving 2D-mode
418  glEnable(GL_TEXTURE_2D);
419
420  /* This allows alpha blending of 2D textures with the scene */
421  glEnable(GL_BLEND);
422  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
423 
424  glViewport(0, 0, screen->w, screen->h);
425 
426  glMatrixMode(GL_PROJECTION);
427  glPushMatrix();
428  glLoadIdentity();
429 
430  glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
431 
432  glMatrixMode(GL_MODELVIEW);
433  glPushMatrix();
434  glLoadIdentity();
435 
436  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
437}
438
439/**
440   \brief leaves the 2DMode again also \see GLFont::enter2DMode(void)
441*/
442void GLFont::leave2DMode(void)
443{
444        glMatrixMode(GL_MODELVIEW);
445        glPopMatrix();
446
447        glMatrixMode(GL_PROJECTION);
448        glPopMatrix();
449
450        glPopAttrib();
451}
452
453
454GLuint GLFont::createFastTexture(void)
455{
456  /* interesting GLYPHS:
457   *  33-47: Special Characters.
458   *  48-57: 0-9
459   *  58-63: some more special chars (minor)
460   *  65-90: A-Z
461   *  97-122: a-z
462   */
463  int numberOfGlyphs = 90;
464
465  this->initGlyphs(33, numberOfGlyphs);
466
467  int rectSize = this->findOptimalFastTextureSize();
468
469  // setting default values. (maybe not needed afterwards)
470  SDL_Color tmpColor;  tmpColor.r = tmpColor.g = tmpColor.b = 0;
471  // Surface definition.
472  SDL_Rect tmpRect; // this represents a Rectangle for blitting.
473  SDL_Surface* tmpSurf =  SDL_CreateRGBSurface(SDL_SWSURFACE,
474                                               rectSize, rectSize,
475                                               32,
476#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
477                                               0x000000FF, 
478                                               0x0000FF00, 
479                                               0x00FF0000, 
480                                               0xFF000000
481#else
482                                               0xFF000000,
483                                               0x00FF0000, 
484                                               0x0000FF00, 
485                                               0x000000FF
486#endif
487                                               );
488  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
489  SDL_SetClipRect(tmpSurf, &tmpRect);
490  int maxLineHeight = 0;
491
492  // all the interessting Glyphs
493  for (int i = 33; i <= 122; i++)
494    {
495      SDL_Surface* glyphSurf = NULL;
496      Glyph* tmpGlyph;
497
498      if (tmpGlyph = this->glyphArray[i])
499        {
500          if (tmpGlyph->height > maxLineHeight)
501            maxLineHeight = tmpGlyph->height;
502         
503          if (tmpRect.x+tmpGlyph->width > tmpSurf->w)
504            {
505              tmpRect.x = 0;
506              tmpRect.y = tmpRect.y + maxLineHeight + 1;
507              maxLineHeight = 0;
508            }
509          if (tmpRect.y + maxLineHeight > tmpSurf->h)
510            {
511              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
512              break;
513            }
514          // reading in the new Glyph
515          //glyphSurf = TTF_RenderGlyph_Shaded(this->font, i, this->currentText->color, tmpColor);
516          glyphSurf = TTF_RenderGlyph_Blended(this->font, i, this->currentText->color);
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 Loads a Font from an SDL_surface into a texture.
579   \param surface The surface to make the texture of
580   \param texCoord The texture coordinates of the 4 corners of the texture
581   \returns the ID of the texture
582*/
583GLuint GLFont::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
584{
585  GLuint texture;
586  int w, h;
587  SDL_Surface *image;
588  SDL_Rect area;
589  Uint32 saved_flags;
590  Uint8  saved_alpha;
591 
592  /* Use the surface width and height expanded to powers of 2 */
593  w = powerOfTwo(surface->w);
594  h = powerOfTwo(surface->h);
595  if (texCoord)
596    {
597      texCoord->minU = 0.0f;
598      texCoord->minV = 0.0f;
599      texCoord->maxU = (GLfloat)surface->w / w;
600      texCoord->maxV = (GLfloat)surface->h / h;
601    }
602  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
603                               w, h,
604                               32,
605#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
606                               0x000000FF, 
607                               0x0000FF00, 
608                               0x00FF0000, 
609                               0xFF000000
610#else
611                               0xFF000000,
612                               0x00FF0000, 
613                               0x0000FF00, 
614                               0x000000FF
615#endif
616                               );
617  if ( image == NULL ) {
618    return 0;
619  }
620 
621  /* Save the alpha blending attributes */
622  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
623  saved_alpha = surface->format->alpha;
624  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
625    SDL_SetAlpha(surface, 0, 0);
626  }
627 
628  /* Copy the surface into the GL texture image */
629  area.x = 0;
630  area.y = 0;
631  area.w = surface->w;
632  area.h = surface->h;
633  SDL_BlitSurface(surface, &area, image, &area);
634 
635  /* Restore the alpha blending attributes */
636  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
637    SDL_SetAlpha(surface, saved_flags, saved_alpha);
638  }
639 
640  /* Create an OpenGL texture for the image */
641  glGenTextures(1, &texture);
642  glBindTexture(GL_TEXTURE_2D, texture);
643  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
644  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
645  glTexImage2D(GL_TEXTURE_2D,
646               0,
647               GL_RGBA,
648               w, h,
649               0,
650               GL_RGBA,
651               GL_UNSIGNED_BYTE,
652               image->pixels);
653  SDL_FreeSurface(image); /* No longer needed */
654 
655  return texture;
656}
657
658/**
659   \brief stores Glyph Metrics in an Array.
660   \param from The Glyph to start from.
661   \param count The number of Glyphs to start From.
662*/
663void GLFont::initGlyphs(Uint16 from, Uint16 count)
664{
665  /* initialize the Array, and set all its entries to NULL
666   *  only if the Glyph-array has not been initialized
667   */
668  if (!this->glyphArray)
669    {
670      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
671      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
672        this->glyphArray[i] = NULL;
673    }
674 
675  Uint16 lastGlyph = from + count;
676 
677  for (int i = from; i <= lastGlyph; i++)
678    {
679      // setting up all the Glyphs we like.
680      glyphArray[i] = getGlyphMetrics(i);
681    }
682  return;
683}
684
685/**
686   \returns the optimal size to use as the texture size
687
688   \todo: this algorithm can be a lot more faster, althought it does
689   not really matter within the init-context, and 128 glyphs.
690
691   This function searches for a 2^n sizes texture-size, this is for
692   openGL-version < 1.2 compatibility. and because it is realy easy like this.
693*/
694int GLFont::findOptimalFastTextureSize(void)
695{
696  int i;
697  int x,y; // the counters
698  int maxLineHeight;
699  int size = 32;      // starting Value, we have to start somewhere 32 seems reasonable.
700  bool sizeOK = false;
701  Glyph* tmpGlyph;
702
703  while (!sizeOK)
704    {
705      x = 0; y = 0;
706      maxLineHeight = 0;
707      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
708        {
709          if(tmpGlyph = this->glyphArray[i])
710            {
711              // getting the height of the highest Glyph in the Line.
712              if (tmpGlyph->height > maxLineHeight)
713                maxLineHeight = tmpGlyph->height;
714
715              if (x + tmpGlyph->width > size)
716                {
717                  x = 0;
718                  y = y + maxLineHeight;
719                  maxLineHeight = 0;
720                }
721              if (y + maxLineHeight + 1 > size)
722                break;
723              x += tmpGlyph->width + 1;
724
725            }
726        }
727      if (i == FONT_HIGHEST_KNOWN_CHAR)
728        sizeOK = true;
729      else
730        size *= 2;
731    }
732  return size;
733 
734}
735
736/**
737   \brief Quick utility function for texture creation
738   \param input an integer
739   \returns the next bigger 2^n-integer than input
740*/
741int GLFont::powerOfTwo(int input)
742{
743  int value = 1;
744 
745  while ( value < input ) {
746    value <<= 1;
747  }
748  return value;
749}
750
751
752/**
753   \brief checks if the compiled version and the local version of SDL_ttf match.
754   \returns true if match, false otherwise
755*/
756bool GLFont::checkVersion(void)
757{
758  SDL_version compile_version;
759  SDL_version link_version;
760  TTF_VERSION(&compile_version);
761  link_version = *TTF_Linked_Version();
762
763  if (compile_version.major == link_version.major &&
764      compile_version.minor == link_version.minor &&
765      compile_version.patch == link_version.patch)
766    {
767      return true;
768    }
769  else
770    {
771      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n", 
772                compile_version.major,
773                compile_version.minor,
774                compile_version.patch);
775     
776      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n", 
777                link_version.major,
778                link_version.minor,
779                link_version.patch);
780      return false;
781    }
782}
783
784
785
786/**
787   \brief a simple function to get some interesting information about this class
788*/
789void GLFont::debug(void)
790{
791
792  // print the loaded font's style
793  int style;
794  style=TTF_GetFontStyle(this->font);
795  PRINTF(0)("The font style is:");
796  if(style==TTF_STYLE_NORMAL)
797    PRINTF(0)(" normal");
798  else {
799    if(style&TTF_STYLE_BOLD)
800      PRINTF(0)(" bold");
801    if(style&TTF_STYLE_ITALIC)
802      PRINTF(0)(" italic");
803    if(style&TTF_STYLE_UNDERLINE)
804      PRINTF(0)(" underline");
805  }
806  PRINTF(0)("\n");
807
808
809}
810
811
812void m_inverse(const float *m, float *out)
813{
814    float det;
815    det=  m[0]*m[5]*m[10];
816    det+= m[4]*m[9]*m[2];
817    det+= m[8]*m[1]*m[6];
818    det-= m[8]*m[5]*m[2];
819    det-= m[4]*m[1]*m[10];
820    det-= m[0]*m[9]*m[6];
821   
822    if(det!= 0.0)
823        det=1.0/det;
824    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
825    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
826    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
827    out[3]= 0.0;
828    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
829    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
830    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
831    out[7]= 0.0;
832    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
833    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
834    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
835    out[11]= 0.0;
836    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
837    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
838    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
839    out[15]= 1.0;
840}
841
842
843Vector mvMult(const float *mat, const Vector* vec)
844{
845  Vector tmp;
846  tmp.x = mat[0]*vec->x+mat[1]*vec->y+mat[2]*vec->z;
847  tmp.y = mat[4]*vec->x+mat[5]*vec->y+mat[6]*vec->z;
848  tmp.z = mat[8]*vec->x+mat[9]*vec->y+mat[10]*vec->z;
849  return tmp;
850}
Note: See TracBrowser for help on using the repository browser.