Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/textEngine: doxygen tags, some minor fix

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