Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/text_engine/text.cc @ 5347

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

orxonox/trunk: Text now does not segfault anymore, if Font could not be loaded

File size: 9.7 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#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_FONT
17
18#include "text.h"
19#include "font.h"
20
21#include "graphics_engine.h"
22#include "resource_manager.h"
23#include "class_list.h"
24#include "debug.h"
25#include "p_node.h"
26
27using namespace std;
28
29/**
30 *  creates a new Text Element
31 * @param fontFile the Font to render this text in
32 * @param type The renderType to display this font in
33 */
34Text::Text(const char* fontFile, unsigned int fontSize, TEXT_RENDER_TYPE type)
35{
36  this->init();
37
38  if (fontFile != NULL)
39    this->setFont(fontFile, fontSize);
40  this->setType(type);
41}
42
43/**
44 *  deletes a Text out of memory
45 *
46 * This also ereases the text from the textList of the TextEngine
47 */
48Text::~Text()
49{
50  if (this->font != NULL)
51    ResourceManager::getInstance()->unload(this->font);
52
53  if (this->text)
54    delete[] this->text;
55}
56
57void Text::init()
58{
59  this->setClassID(CL_TEXT, "Text");
60
61  // initialize this Text
62  this->font = NULL;
63  this->text = NULL;
64  this->externText = NULL;
65  this->setAlignment(TEXT_DEFAULT_ALIGNMENT);
66  this->texture = 0;
67  this->blending = TEXT_DEFAULT_BLENDING;
68  this->color = TEXT_DEFAULT_COLOR;
69  this->setType(TEXT_RENDER_DYNAMIC);
70
71  this->setText(NULL);
72}
73
74/**
75 * sets the Font of this Text to font from fontFile
76 * @param fontFile the File to load the Font from.
77 * @param fontSize the Size of the Font
78 */
79void Text::setFont(const char* fontFile, unsigned int fontSize)
80{
81  Font* tmpFont;
82  Text* newText;
83  Vector tmpVec;
84
85  // unloading the Font if we alrady have one loaded.
86  if (this->font != NULL)
87    ResourceManager::getInstance()->unload(this->font);
88  this->font = NULL;
89
90  // load a new Font
91  if (fontFile != NULL)
92  {
93    tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, &fontSize);
94    if (tmpFont != NULL)
95      this->font = tmpFont;
96    else
97      PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);
98  }
99}
100
101/**
102 *  sets the Type of this Text
103 * @param type the type to set.
104 */
105void Text::setType(TEXT_RENDER_TYPE type)
106{
107  if (this->font != NULL && this->font->font)
108    this->type = type;
109  else
110    this->type = TEXT_RENDER_DYNAMIC;
111}
112
113/**
114 *  Sets a new Text to the font
115 * @param text the new text to set
116 */
117void Text::setText(const char* text, bool isExtern)
118{
119  if (isExtern)
120  {
121    this->externText = text;
122
123    if (unlikely(this->text != NULL))
124    {
125      delete[] this->text;
126      this->text = NULL;
127    }
128  }
129  else
130  {
131    this->externText = NULL;
132    if (this->text)
133      delete[] this->text;
134    if (text != NULL)
135    {
136      this->text = new char[strlen(text)+1];
137      strcpy(this->text, text);
138    }
139    else
140      this->text = NULL;
141  }
142
143  // setting up the Text-Width if DYNAMIC
144  if (this->type & TEXT_RENDER_DYNAMIC && this->getAlignment() != TEXT_ALIGN_LEFT && this->font != NULL)
145  {
146    Glyph** glyphArray = this->font->getGlyphArray();
147
148    int width = 0;
149    const char* tmpText = this->externText;
150    if (this->externText == NULL)
151      tmpText = this->text;
152    if (tmpText != NULL)
153    {
154      while (*tmpText != '\0')
155      {
156        if(glyphArray[*tmpText])
157        {
158          width += glyphArray[*tmpText]->width;
159        }
160        tmpText++;
161      }
162      this->width = width;
163    }
164  }
165}
166
167
168/**
169 *  creates a texture out of the given parameters
170 *
171 * this has to be called every time by the user, to if changes were made.
172 * this is only for TEXT_STATIC-mode
173 */
174void Text::createTexture()
175{
176  SDL_Surface* tmpSurf = NULL;
177  if (this->texture)
178    glDeleteTextures(1, &this->texture);
179  if (likely(this->font != NULL))
180  {
181    SDL_Color theColor = { (int)(this->color.x*255), (int)(this->color.y*255), (int)(this->color.z*255) };
182    tmpSurf = TTF_RenderText_Blended(this->font->font,
183                                     this->text,
184                                     theColor);
185  }
186  if (tmpSurf != NULL)
187  {
188    this->texture = loadTexture(tmpSurf, &this->texCoord);
189
190    this->width = tmpSurf->w;
191    this->height = tmpSurf->h;
192    SDL_FreeSurface(tmpSurf);
193  }
194}
195
196/**
197 *  draws the Text
198 */
199void Text::draw() const
200{
201  glPushMatrix();
202  // transform for alignment.
203  if (this->getAlignment() == TEXT_ALIGN_RIGHT)
204    glTranslatef(-this->width, 0, 0);
205  else if (this->getAlignment() == TEXT_ALIGN_CENTER || this->getAlignment() == TEXT_ALIGN_SCREEN_CENTER)
206    glTranslatef(-this->width/2, 0, 0);
207
208  // drawing this Text.
209  // setting the Blending effects
210  glColor4f(this->color.x, this->color.y, this->color.z, this->blending);
211  glEnable(GL_BLEND);
212  glEnable(GL_TEXTURE_2D);
213  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
214
215  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_MODULATE );
216
217  if(likely(type & TEXT_RENDER_DYNAMIC ))
218  {
219    Glyph** glyphArray;
220    if (likely (this->font != NULL))
221    {
222      glyphArray = this->font->getGlyphArray();
223      glBindTexture(GL_TEXTURE_2D, font->getFastTextureID());
224    }
225    else
226    {
227      if (unlikely(Font::getDefaultFont() == NULL))
228        Font::initDefaultFont();
229      glyphArray = Font::getDefaultFont()->getGlyphArray();
230      glBindTexture(GL_TEXTURE_2D, Font::getDefaultFont()->getFastTextureID());
231    }
232    glTranslatef(getAbsCoor2D().x, getAbsCoor2D().y, 0);
233//      glRotatef(this->getAbsDir2D(), 0,0,1);
234    const char* tmpText = this->externText;
235    if (this->externText == NULL)
236      tmpText = this->text;
237    if (likely(tmpText != NULL))
238    {
239      while (likely(*tmpText != '\0'))
240      {
241        if(likely(glyphArray[*tmpText] != NULL))
242        {
243          glCallList(glyphArray[*tmpText]->displayList);
244          glTranslatef(glyphArray[*tmpText]->width, 0, 0);
245        }
246        tmpText++;
247      }
248    }
249  }
250  else //(if type & TEXT_RENDER_STATIC)
251  {
252    glBindTexture(GL_TEXTURE_2D, this->texture);
253    glBegin(GL_QUADS);
254
255    glTexCoord2f(this->texCoord.minU, this->texCoord.minV);
256    glVertex2f(this->getAbsCoor2D().x,   this->getAbsCoor2D().);
257
258    glTexCoord2f(this->texCoord.maxU, this->texCoord.minV);
259    glVertex2f(this->getAbsCoor2D().x + this->width, this->getAbsCoor2D().);
260
261    glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);
262    glVertex2f(this->getAbsCoor2D().x + this->width, getAbsCoor2D().y + this->height);
263
264    glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);
265    glVertex2f(getAbsCoor2D().x, getAbsCoor2D().y + this->height);
266
267    glEnd();
268
269  }
270  glPopMatrix();
271}
272
273/**
274 *  prints out some nice debug information about this text
275 */
276void Text::debug() const
277{
278  if (this->externText == NULL)
279    PRINT(0)("=== TEXT: %s ===\n", this->text);
280  else
281    PRINT(0)("=== TEXT: %s ===\n", this->externText);
282
283  if (this->getBindNode())
284    PRINT(0)("is bind to %s; ref=%p\n", this->getBindNode()->getName(), this->getBindNode());
285  PRINT(0)("Color: %0.2f %0.2f %0.2f\n", this->color.x, this->color.y, this->color.z);
286}
287
288
289////////////
290/// UTIL ///
291////////////
292/**
293 * Loads a Font from an SDL_surface into a texture.
294 * @param surface The surface to make the texture of
295 * @param texCoord The texture coordinates of the 4 corners of the texture
296 * @returns the ID of the texture
297 */
298GLuint Text::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
299{
300  GLuint texture;
301  int w, h;
302  SDL_Surface *image;
303  SDL_Rect area;
304  Uint32 saved_flags;
305  Uint8  saved_alpha;
306
307  /* Use the surface width and height expanded to powers of 2 */
308  w = powerOfTwo(surface->w);
309  h = powerOfTwo(surface->h);
310  if (texCoord != NULL)
311  {
312    texCoord->minU = 0.0f;
313    texCoord->minV = 0.0f;
314    texCoord->maxU = (GLfloat)surface->w / w;
315    texCoord->maxV = (GLfloat)surface->h / h;
316  }
317  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
318                               w, h,
319                               32,
320#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
321                               0x000000FF,
322                               0x0000FF00,
323                               0x00FF0000,
324                               0xFF000000
325#else
326                                   0xFF000000,
327                               0x00FF0000,
328                               0x0000FF00,
329                               0x000000FF
330#endif
331                              );
332  if ( image == NULL ) {
333    return 0;
334  }
335
336  /* Save the alpha blending attributes */
337  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
338  saved_alpha = surface->format->alpha;
339  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
340    SDL_SetAlpha(surface, 0, 0);
341  }
342
343  /* Copy the surface into the GL texture image */
344  area.x = 0;
345  area.y = 0;
346  area.w = surface->w;
347  area.h = surface->h;
348  SDL_BlitSurface(surface, &area, image, &area);
349
350  /* Restore the alpha blending attributes */
351  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
352    SDL_SetAlpha(surface, saved_flags, saved_alpha);
353  }
354
355  /* Create an OpenGL texture for the image */
356  glGenTextures(1, &texture);
357  glBindTexture(GL_TEXTURE_2D, texture);
358  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
359  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
360  glTexImage2D(GL_TEXTURE_2D,
361               0,
362               GL_RGBA,
363               w, h,
364               0,
365               GL_RGBA,
366               GL_UNSIGNED_BYTE,
367               image->pixels);
368  SDL_FreeSurface(image); /* No longer needed the data */
369
370  return texture;
371}
372
373/**
374 *  Quick utility function for texture creation
375 * @param input an integer
376 * @returns the next bigger 2^n-integer than input
377 */
378int Text::powerOfTwo(int input)
379{
380  int value = 1;
381
382  while ( value < input )
383    value <<= 1;
384  return value;
385}
Note: See TracBrowser for help on using the repository browser.