Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: font do no more handle any displayLists of Glyphs

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