Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/braches/textEngine: now shows single char

File size: 20.8 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(
474                                               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
490  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
491  SDL_SetClipRect(tmpSurf, &tmpRect);
492  int maxLineHeight = 0;
493
494  // all the interessting Glyphs
495  for (int i = 33; i <= 122; i++)
496    {
497      SDL_Surface* glyphSurf = NULL;
498      Glyph* tmpGlyph;
499
500      if (tmpGlyph = this->glyphArray[i])
501        {
502          if (tmpGlyph->height > maxLineHeight)
503            maxLineHeight = tmpGlyph->height;
504         
505          if (tmpRect.x+tmpGlyph->width > tmpSurf->w)
506            {
507              tmpRect.x = 0;
508              tmpRect.y = tmpRect.y + maxLineHeight + 1;
509              maxLineHeight = 0;
510            }
511          if (tmpRect.y + maxLineHeight > tmpSurf->h)
512            {
513              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
514              break;
515            }
516          // reading in the new Glyph
517          glyphSurf = TTF_RenderGlyph_Shaded(this->font,
518                                              i,
519                                              this->currentText->color,
520          tmpColor);
521          if( glyphSurf ) 
522            {
523              SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);
524              TexCoord tmpTexCoord;
525              tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;
526              tmpTexCoord.maxU = (float)(tmpRect.x+tmpGlyph->width)/(float)tmpSurf->w;
527              tmpTexCoord.minV = (float)tmpRect.y/(float)tmpSurf->w;
528              tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;
529              tmpGlyph->displayList = glGenLists(1);
530
531              glNewList(tmpGlyph->displayList, GL_COMPILE);
532              glBegin(GL_QUADS);
533              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);
534              glVertex2d(0, 0);
535              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
536              glVertex2d(0, tmpRect.y);
537              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
538              glVertex2d(tmpRect.x, tmpRect.y);
539              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
540              glVertex2d(tmpRect.x, 0);
541              glEnd();
542              glEndList();
543              SDL_FreeSurface(glyphSurf);
544
545              tmpRect.x += tmpGlyph->width + 1;
546
547              // Outputting Glyphs to BMP-files.
548              /*
549                char outname[64];
550                if (i < 10)
551                sprintf( outname, "glyph-00%d.bmp", i );
552                else if (i <100)
553                sprintf( outname, "glyph-0%d.bmp", i );
554                else
555                sprintf( outname, "glyph-%d.bmp", i );
556                SDL_SaveBMP(tmpSurf, outname);
557              */
558            }
559        }
560    }
561
562  GLuint tmpRet = this->loadTexture(tmpSurf, NULL);
563  SDL_FreeSurface(tmpSurf);
564  return tmpRet;
565}
566
567/**
568   \brief Loads a Font from an SDL_surface into a texture.
569   \param surface The surface to make the texture of
570   \param texCoord The texture coordinates of the 4 corners of the texture
571   \returns the ID of the texture
572*/
573GLuint GLFont::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
574{
575  GLuint texture;
576  int w, h;
577  SDL_Surface *image;
578  SDL_Rect area;
579  Uint32 saved_flags;
580  Uint8  saved_alpha;
581 
582  /* Use the surface width and height expanded to powers of 2 */
583  w = powerOfTwo(surface->w);
584  h = powerOfTwo(surface->h);
585  if (texCoord)
586    {
587      texCoord->minU = 0.0f;
588      texCoord->minV = 0.0f;
589      texCoord->maxU = (GLfloat)surface->w / w;
590      texCoord->maxV = (GLfloat)surface->h / h;
591    }
592  image = SDL_CreateRGBSurface(
593                               SDL_SWSURFACE,
594                               w, h,
595                               32,
596#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
597                               0x000000FF, 
598                               0x0000FF00, 
599                               0x00FF0000, 
600                               0xFF000000
601#else
602                               0xFF000000,
603                               0x00FF0000, 
604                               0x0000FF00, 
605                               0x000000FF
606#endif
607                               );
608  if ( image == NULL ) {
609    return 0;
610  }
611 
612  /* Save the alpha blending attributes */
613  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
614  saved_alpha = surface->format->alpha;
615  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
616    SDL_SetAlpha(surface, 0, 0);
617  }
618 
619  /* Copy the surface into the GL texture image */
620  area.x = 0;
621  area.y = 0;
622  area.w = surface->w;
623  area.h = surface->h;
624  SDL_BlitSurface(surface, &area, image, &area);
625 
626  /* Restore the alpha blending attributes */
627  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
628    SDL_SetAlpha(surface, saved_flags, saved_alpha);
629  }
630 
631  /* Create an OpenGL texture for the image */
632  glGenTextures(1, &texture);
633  glBindTexture(GL_TEXTURE_2D, texture);
634  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
635  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
636  glTexImage2D(GL_TEXTURE_2D,
637               0,
638               GL_RGBA,
639               w, h,
640               0,
641               GL_RGBA,
642               GL_UNSIGNED_BYTE,
643               image->pixels);
644  SDL_FreeSurface(image); /* No longer needed */
645 
646  return texture;
647}
648
649/**
650   \brief stores Glyph Metrics in an Array.
651   \param from The Glyph to start from.
652   \param count The number of Glyphs to start From.
653*/
654void GLFont::initGlyphs(Uint16 from, Uint16 count)
655{
656  /* initialize the Array, and set all its entries to NULL
657   *  only if the Glyph-array has not been initialized
658   */
659  if (!this->glyphArray)
660    {
661      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
662      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
663        this->glyphArray[i] = NULL;
664    }
665 
666  Uint16 lastGlyph = from + count;
667 
668  for (int i = from; i <= lastGlyph; i++)
669    {
670      // setting up all the Glyphs we like.
671      glyphArray[i] = getGlyphMetrics(i);
672    }
673  return;
674}
675
676/**
677   \returns the optimal size to use as the texture size
678
679   \todo: this algorithm can be a lot more faster, althought it does
680   not really matter within the init-context, and 128 glyphs.
681
682   This function searches for a 2^n sizes texture-size, this is for
683   openGL-version < 1.2 compatibility. and because it is realy easy like this.
684*/
685int GLFont::findOptimalFastTextureSize(void)
686{
687  int i;
688  int x,y; // the counters
689  int maxLineHeight;
690  int size = 32;      // starting Value, we have to start somewhere 32 seems reasonable.
691  bool sizeOK = false;
692  Glyph* tmpGlyph;
693
694  while (!sizeOK)
695    {
696      x = 0; y = 0;
697      maxLineHeight = 0;
698      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
699        {
700          if(tmpGlyph = this->glyphArray[i])
701            {
702              // getting the height of the highest Glyph in the Line.
703              if (tmpGlyph->height > maxLineHeight)
704                maxLineHeight = tmpGlyph->height;
705
706              if (x + tmpGlyph->width > size)
707                {
708                  x = 0;
709                  y = y + maxLineHeight;
710                  maxLineHeight = 0;
711                }
712              if (y + maxLineHeight + 1 > size)
713                break;
714              x += tmpGlyph->width + 1;
715
716            }
717        }
718      if (i == FONT_HIGHEST_KNOWN_CHAR)
719        sizeOK = true;
720      else
721        size *= 2;
722    }
723  return size;
724 
725}
726
727/**
728   \brief Quick utility function for texture creation
729   \param input an integer
730   \returns the next bigger 2^n-integer than input
731*/
732int GLFont::powerOfTwo(int input)
733{
734  int value = 1;
735 
736  while ( value < input ) {
737    value <<= 1;
738  }
739  return value;
740}
741
742
743/**
744   \brief checks if the compiled version and the local version of SDL_ttf match.
745   \returns true if match, false otherwise
746*/
747bool GLFont::checkVersion(void)
748{
749  SDL_version compile_version;
750  SDL_version link_version;
751  TTF_VERSION(&compile_version);
752  link_version = *TTF_Linked_Version();
753
754  if (compile_version.major == link_version.major &&
755      compile_version.minor == link_version.minor &&
756      compile_version.patch == link_version.patch)
757    {
758      return true;
759    }
760  else
761    {
762      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n", 
763                compile_version.major,
764                compile_version.minor,
765                compile_version.patch);
766     
767      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n", 
768                link_version.major,
769                link_version.minor,
770                link_version.patch);
771      return false;
772    }
773}
774
775
776
777/**
778   \brief a simple function to get some interesting information about this class
779*/
780void GLFont::debug(void)
781{
782
783  // print the loaded font's style
784  int style;
785  style=TTF_GetFontStyle(this->font);
786  PRINTF(0)("The font style is:");
787  if(style==TTF_STYLE_NORMAL)
788    PRINTF(0)(" normal");
789  else {
790    if(style&TTF_STYLE_BOLD)
791      PRINTF(0)(" bold");
792    if(style&TTF_STYLE_ITALIC)
793      PRINTF(0)(" italic");
794    if(style&TTF_STYLE_UNDERLINE)
795      PRINTF(0)(" underline");
796  }
797  PRINTF(0)("\n");
798
799
800}
801
802
803void m_inverse(const float *m, float *out)
804{
805    float det;
806    det=  m[0]*m[5]*m[10];
807    det+= m[4]*m[9]*m[2];
808    det+= m[8]*m[1]*m[6];
809    det-= m[8]*m[5]*m[2];
810    det-= m[4]*m[1]*m[10];
811    det-= m[0]*m[9]*m[6];
812   
813    if(det!= 0.0)
814        det=1.0/det;
815    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
816    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
817    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
818    out[3]= 0.0;
819    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
820    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
821    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
822    out[7]= 0.0;
823    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
824    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
825    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
826    out[11]= 0.0;
827    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
828    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
829    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
830    out[15]= 1.0;
831}
832
833
834Vector mvMult(const float *mat, const Vector* vec)
835{
836  Vector tmp;
837  tmp.x = mat[0]*vec->x+mat[1]*vec->y+mat[2]*vec->z;
838  tmp.y = mat[4]*vec->x+mat[5]*vec->y+mat[6]*vec->z;
839  tmp.z = mat[8]*vec->x+mat[9]*vec->y+mat[10]*vec->z;
840  return tmp;
841}
Note: See TracBrowser for help on using the repository browser.