Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fancy effects in Shell

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