Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/textEngine: added bind-node ability, so now the text tries to follow a given PNode (currently trackNode)
the work is not finished, so do not expect too much

File size: 15.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   * the Copyright of the original file is below this copyright         *
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/*
28  glfont:  An example of using the SDL_ttf library with OpenGL.
29  Copyright (C) 1997-2004 Sam Lantinga
30 
31  This library is free software; you can redistribute it and/or
32  modify it under the terms of the GNU Library General Public
33  License as published by the Free Software Foundation; either
34  version 2 of the License, or (at your option) any later version.
35 
36  This library is distributed in the hope that it will be useful,
37  but WITHOUT ANY WARRANTY; without even the implied warranty of
38  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39  Library General Public License for more details.
40 
41  You should have received a copy of the GNU Library General Public
42  License along with this library; if not, write to the Free
43  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 
45  The SDL_GL_* functions in this file are available in the public domain.
46 
47  Sam Lantinga
48  slouken@libsdl.org
49*/
50
51#include "glfont.h"
52
53#include <stdlib.h>
54#include <stdio.h>
55#include <string.h>
56
57#include "p_node.h"
58#include "vector.h"
59#include "debug.h"
60
61/**
62   \brief constructs a Font
63   \param fontFile the File to load the font from
64*/
65GLFont::GLFont(const char* fontFile)
66{
67  this->init(fontFile);
68}
69
70/**
71   \brief destructs a font
72*/
73GLFont::~GLFont(void)
74{
75  delete this->currentText;
76
77  if (this->font)
78    TTF_CloseFont(this->font);
79}
80
81/**
82   \brief function to enable TTF_Fonts
83*/
84void GLFont::enableFonts(void)
85{
86  if (!GLFont::ttfInitialized)
87    {
88      if(TTF_Init()==-1)
89        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
90
91      GLFont::checkVersion();
92      GLFont::ttfInitialized = true;
93    }
94  else
95    PRINTF(4)("Fonts already initialized\n");
96     
97}
98
99/**
100   \brief function to disable TTF_fonts
101*/
102void GLFont::disableFonts(void)
103{
104  if (GLFont::ttfInitialized)
105    {
106      TTF_Quit();
107      GLFont::ttfInitialized = false;
108    }
109  else
110    PRINTF(4)("Fonts were not initialized.\n");
111}
112
113//! A simple variable for checking if ttf was initialized
114bool GLFont::ttfInitialized = false;
115
116/**
117   \brief initializes a new Font
118   \param fontFile The file to load a Font from
119   \param fontSize the Size in pixels of the Font
120*/
121bool GLFont::init(const char* fontFile, unsigned int fontSize)
122{
123  if (!GLFont::ttfInitialized)
124    GLFont::enableFonts();
125
126  // setting default values.
127  this->font = NULL;
128  this->fontFile = NULL;
129
130  this->currentText = new Text;
131
132  this->currentText->bindNode = NULL;
133  this->currentText->text = NULL;
134  this->currentText->texture = 0;
135 
136  this->setSize(fontSize);
137 
138  this->currentText->renderStyle = TTF_STYLE_NORMAL;
139
140  this->setFont(fontFile);
141
142  this->setColor(0, 255, 0);
143
144  this->setText(FONT_DEFAULT_TEXT);
145
146  this->createTexture();
147}
148
149/**
150   \brief sets The Font.
151   \param fontFile The file containing the font.
152   \returns true if loaded, false if something went wrong, or if a font was loaded before.
153*/
154bool GLFont::setFont(const char* fontFile)
155{
156  if (!this->fontFile)
157    {
158      this->fontFile = new char[strlen(fontFile)+1];
159      strcpy(this->fontFile, fontFile);
160     
161      this->font = TTF_OpenFont(this->fontFile, this->fontSize);
162      if(!this->font) 
163        {
164          PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());
165          return false;
166      }
167      return true;
168    }
169  else
170    {
171      PRINTF(2)("Font already initialized, unable to change it now.\n");
172      return false;
173    }
174}
175
176void GLFont::setBindNode(PNode* bindNode)
177{
178  this->currentText->bindNode = bindNode;
179}
180
181
182/**
183   \brief Sets a new Text to the font
184   \param text the new text to set
185*/
186void GLFont::setText(const char* text)
187{
188  if (this->currentText->text)
189    delete []this->currentText->text;
190  this->currentText->text = new char[strlen(text)+1];
191  strcpy(this->currentText->text, text);
192}
193
194/**
195   \brief sets a specific renderStyle
196   \param renderStyle the Style to render: a char-array containing:
197   i: italic, b: bold, u, underline
198*/
199void GLFont::setStyle(char* renderStyle)
200{
201  this->currentText->renderStyle = TTF_STYLE_NORMAL;
202 
203  for (int i = 0; i < strlen(renderStyle); i++)
204    if (strncmp(renderStyle+i, "b", 1) == 0) 
205      this->currentText->renderStyle |= TTF_STYLE_BOLD;
206    else if (strncmp(renderStyle+i, "i", 1) == 0)
207      this->currentText->renderStyle |= TTF_STYLE_ITALIC;
208    else if (strncmp(renderStyle+i, "u", 1) == 0) 
209      this->currentText->renderStyle |= TTF_STYLE_UNDERLINE;
210
211  if (this->font)
212    TTF_SetFontStyle(this->font, this->currentText->renderStyle);
213  else
214    PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");
215}
216
217/**
218   \brief Sets a new Size to the font
219   \param fontSize The new Size in pixels.
220*/
221void GLFont::setSize(unsigned int fontSize)
222{
223  this->fontSize = fontSize;
224}
225
226/**
227   \brief sets a new color to the font
228   \param r Red
229   \param g Green
230   \param b Blue
231*/
232void GLFont::setColor(Uint8 r, Uint8 g, Uint8 b)
233{
234  this->currentText->color.r = r;
235  this->currentText->color.g = g;
236  this->currentText->color.b = b;
237}
238
239/**
240   \brief sets a Position.
241   \param x the x-position in pixels from the left border
242   \param y the y-position in pixels from the top border
243*/
244void GLFont::setPosition(int x, int y)
245{
246  this->currentText->textPosSize.x = x;
247  this->currentText->textPosSize.y = y;
248}
249
250/**
251   \brief draws the Font
252   \todo FIX this is to slow/static
253*/
254void GLFont::draw(void)
255{
256  GLdouble modMat[16];
257  GLint viewPort[4];
258  glGetDoublev(GL_PROJECTION_MATRIX, this->projMat);
259  glGetDoublev(GL_MODELVIEW_MATRIX, modMat);
260  glGetIntegerv(GL_VIEWPORT, viewPort);
261  this->enter2DMode();
262
263
264  Vector pos;
265  if (this->currentText->bindNode)
266    {
267      GLdouble x = this->currentText->bindNode->getAbsCoor().x;
268      GLdouble y = this->currentText->bindNode->getAbsCoor().y;
269      GLdouble z = this->currentText->bindNode->getAbsCoor().z;
270      GLdouble tmp[3];
271      gluProject(x, y, z, modMat, projMat, viewPort, tmp, tmp+1, tmp+2);
272      printf("test %f %f %f,\n", tmp[0], tmp[1], tmp[2]);
273      pos.x = tmp[0];
274      pos.y = tmp[1];
275      pos.z = tmp[2];
276    }
277
278  glBindTexture(GL_TEXTURE_2D, this->currentText->texture);
279  glEnable(GL_TEXTURE_2D);
280  glBegin(GL_QUADS);
281 
282  glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.minV);
283  glVertex2i(pos.x,   pos.);
284
285  glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.minV);
286  glVertex2i(pos.x + this->currentText->textPosSize.w, pos.);
287
288  glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.maxV);
289  glVertex2i(pos.x + this->currentText->textPosSize.w, pos.y + this->currentText->textPosSize.h);
290
291  glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.maxV);
292  glVertex2i(pos.x, pos.y + this->currentText->textPosSize.h);
293
294  glEnd();
295
296  this->leave2DMode();
297}
298
299/**
300   \brief creates a texture out of the given parameters
301
302   this has to be called every time by the user, to if changes were made.
303*/
304void GLFont::createTexture(void)
305{
306  SDL_Surface* tmpSurf;
307  if (this->currentText->texture)
308    glDeleteTextures(1, &this->currentText->texture);
309  tmpSurf = TTF_RenderText_Blended(this->font,
310                                   this->currentText->text,
311                                   this->currentText->color);
312  if (tmpSurf)
313    this->currentText->texture = loadTexture(tmpSurf, &this->currentText->texCoord);
314
315  this->currentText->textPosSize.w = tmpSurf->w;
316  this->currentText->textPosSize.h = tmpSurf->h;
317  SDL_FreeSurface(tmpSurf);
318}
319
320
321/**
322   \returns the maximum height of the Font, if the font was initialized, 0 otherwise
323*/
324int GLFont::getMaxHeight(void)
325{
326  if (this->font)
327    return TTF_FontHeight(this->font);
328  else
329    return 0;
330}
331
332/**
333   \returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
334
335   the ascent is the pixels of the font above the baseline
336*/
337int GLFont::getMaxAscent(void)
338{
339  if (this->font)
340    return TTF_FontAscent(this->font);
341  else
342    return 0;
343}
344
345/**
346   \returns the maximum descent of the Font, if the font was initialized, 0 otherwise
347
348   the descent is the pixels of the font below the baseline
349*/
350int GLFont::getMaxDescent(void)
351{
352  if (this->font)
353    return TTF_FontDescent(this->font);
354  else
355    return 0;
356}
357
358/**
359   \param character The character to get info about.
360   \returns a Glyph struct of a character.
361
362   This only works for horizontal fonts. see
363   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
364   for more info about vertical Fonts
365*/
366Glyph GLFont::getGlyphMetrics(Uint16 character)
367{
368  Glyph rg;
369  rg.character = character;
370  TTF_GlyphMetrics(this->font, rg.character,
371                   &rg.minX, &rg.maxX,
372                   &rg.minY, &rg.maxY,
373                   &rg.advance);
374  rg.height = rg.maxY - rg.minY;
375  rg.width = rg.maxX - rg.minX;
376  rg.bearingX = (rg.advance - rg.width) / 2;
377  rg.bearingY = rg.maxY;
378  return rg;
379}
380
381/**
382   \brief entering 2D Mode
383   
384   this is a GL-Projection-mode, that is orthogonal, for placing the font in fron of everything else
385*/
386void GLFont::enter2DMode(void)
387{
388  SDL_Surface *screen = SDL_GetVideoSurface();
389 
390  /* Note, there may be other things you need to change,
391     depending on how you have your OpenGL state set up.
392  */
393  glPushAttrib(GL_ENABLE_BIT);
394  glDisable(GL_DEPTH_TEST);
395  glDisable(GL_CULL_FACE);
396  glDisable(GL_LIGHTING);  // will be set back when leaving 2D-mode
397  glEnable(GL_TEXTURE_2D);
398
399  /* This allows alpha blending of 2D textures with the scene */
400  glEnable(GL_BLEND);
401  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
402 
403  glViewport(0, 0, screen->w, screen->h);
404 
405  glMatrixMode(GL_PROJECTION);
406  glPushMatrix();
407  glLoadIdentity();
408 
409  glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
410 
411  glMatrixMode(GL_MODELVIEW);
412  glPushMatrix();
413  glLoadIdentity();
414 
415  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
416}
417
418/**
419   \brief leaves the 2DMode again also \see GLFont::enter2DMode(void)
420*/
421void GLFont::leave2DMode(void)
422{
423        glMatrixMode(GL_MODELVIEW);
424        glPopMatrix();
425
426        glMatrixMode(GL_PROJECTION);
427        glPopMatrix();
428
429        glPopAttrib();
430}
431
432/**
433   \brief Loads a Font from an SDL_surface into a texture.
434   \param surface The surface to make the texture of
435   \param texCoord The texture coordinates of the 4 corners of the texture
436   \returns the ID of the texture
437*/
438GLuint GLFont::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
439{
440  GLuint texture;
441  int w, h;
442  SDL_Surface *image;
443  SDL_Rect area;
444  Uint32 saved_flags;
445  Uint8  saved_alpha;
446 
447  /* Use the surface width and height expanded to powers of 2 */
448  w = powerOfTwo(surface->w);
449  h = powerOfTwo(surface->h);
450  texCoord->minU = 0.0f;
451  texCoord->minV = 0.0f;
452  texCoord->maxU = (GLfloat)surface->w / w;
453  texCoord->maxV = (GLfloat)surface->h / h;
454 
455  image = SDL_CreateRGBSurface(
456                               SDL_SWSURFACE,
457                               w, h,
458                               32,
459#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
460                               0x000000FF, 
461                               0x0000FF00, 
462                               0x00FF0000, 
463                               0xFF000000
464#else
465                               0xFF000000,
466                               0x00FF0000, 
467                               0x0000FF00, 
468                               0x000000FF
469#endif
470                               );
471  if ( image == NULL ) {
472    return 0;
473  }
474 
475  /* Save the alpha blending attributes */
476  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
477  saved_alpha = surface->format->alpha;
478  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
479    SDL_SetAlpha(surface, 0, 0);
480  }
481 
482  /* Copy the surface into the GL texture image */
483  area.x = 0;
484  area.y = 0;
485  area.w = surface->w;
486  area.h = surface->h;
487  SDL_BlitSurface(surface, &area, image, &area);
488 
489  /* Restore the alpha blending attributes */
490  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
491    SDL_SetAlpha(surface, saved_flags, saved_alpha);
492  }
493 
494  /* Create an OpenGL texture for the image */
495  glGenTextures(1, &texture);
496  glBindTexture(GL_TEXTURE_2D, texture);
497  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
498  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
499  glTexImage2D(GL_TEXTURE_2D,
500               0,
501               GL_RGBA,
502               w, h,
503               0,
504               GL_RGBA,
505               GL_UNSIGNED_BYTE,
506               image->pixels);
507  SDL_FreeSurface(image); /* No longer needed */
508 
509  return texture;
510}
511
512/**
513   \brief Quick utility function for texture creation
514   \param input an integer
515   \returns the next bigger 2^n-integer than input
516*/
517int GLFont::powerOfTwo(int input)
518{
519  int value = 1;
520 
521  while ( value < input ) {
522    value <<= 1;
523  }
524  return value;
525}
526
527
528/**
529   \brief checks if the compiled version and the local version of SDL_ttf match.
530   \returns true if match, false otherwise
531*/
532bool GLFont::checkVersion(void)
533{
534  SDL_version compile_version;
535  SDL_version link_version;
536  TTF_VERSION(&compile_version);
537  link_version = *TTF_Linked_Version();
538
539  if (compile_version.major == link_version.major &&
540      compile_version.minor == link_version.minor &&
541      compile_version.patch == link_version.patch)
542    {
543      return true;
544    }
545  else
546    {
547      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n", 
548                compile_version.major,
549                compile_version.minor,
550                compile_version.patch);
551     
552      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n", 
553                link_version.major,
554                link_version.minor,
555                link_version.patch);
556      return false;
557    }
558}
559
560
561
562/**
563   \brief a simple function to get some interesting information about this class
564*/
565void GLFont::debug(void)
566{
567
568  // print the loaded font's style
569  int style;
570  style=TTF_GetFontStyle(this->font);
571  PRINTF(0)("The font style is:");
572  if(style==TTF_STYLE_NORMAL)
573    PRINTF(0)(" normal");
574  else {
575    if(style&TTF_STYLE_BOLD)
576      PRINTF(0)(" bold");
577    if(style&TTF_STYLE_ITALIC)
578      PRINTF(0)(" italic");
579    if(style&TTF_STYLE_UNDERLINE)
580      PRINTF(0)(" underline");
581  }
582  PRINTF(0)("\n");
583
584
585}
586
587
588void m_inverse(const float *m, float *out)
589{
590    float det;
591    det=  m[0]*m[5]*m[10];
592    det+= m[4]*m[9]*m[2];
593    det+= m[8]*m[1]*m[6];
594    det-= m[8]*m[5]*m[2];
595    det-= m[4]*m[1]*m[10];
596    det-= m[0]*m[9]*m[6];
597   
598    if(det!= 0.0)
599        det=1.0/det;
600    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
601    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
602    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
603    out[3]= 0.0;
604    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
605    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
606    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
607    out[7]= 0.0;
608    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
609    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
610    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
611    out[11]= 0.0;
612    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
613    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
614    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
615    out[15]= 1.0;
616}
617
618
619Vector mvMult(const float *mat, const Vector* vec)
620{
621  Vector tmp;
622  tmp.x = mat[0]*vec->x+mat[1]*vec->y+mat[2]*vec->z;
623  tmp.y = mat[4]*vec->x+mat[5]*vec->y+mat[6]*vec->z;
624  tmp.z = mat[8]*vec->x+mat[9]*vec->y+mat[10]*vec->z;
625  return tmp;
626}
Note: See TracBrowser for help on using the repository browser.