Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: split open the text-engine

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