Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/textEngine: packed some parameters for texts into a Struct, to build a List of texts.

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