Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/2d-recalc/src/lib/graphics/text_engine/text.cc @ 5855

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

orxonox/trunk: some 2d-adaptions

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