Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

oroxnox/trunk: gui extends element2D

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