Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/graphics/font/glfont.cc @ 3716

Last change on this file since 3716 was 3716, checked in by bensch, 20 years ago

orxonox/branches/textEngine: now the text is really placed on top of a given world-entity

File size: 15.4 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   * This file is extended to the needs of the orxonox-project.         *
17   * the Copyright of the original file is below this copyright         *
18   *                                                                  ***
19
20   for some fonts and licenses visit: =http://www.dafont.com/en/font.php=
21
22   !! IMPORTANT !! When using ttf fonts clear the license issues prior to
23   adding them to orxonox. This is really important, because we do not
24   want to defend anyone.
25*/
26
27/*
28  glfont:  An example of using the SDL_ttf library with OpenGL.
29  Copyright (C) 1997-2004 Sam Lantinga
30 
31  This library is free software; you can redistribute it and/or
32  modify it under the terms of the GNU Library General Public
33  License as published by the Free Software Foundation; either
34  version 2 of the License, or (at your option) any later version.
35 
36  This library is distributed in the hope that it will be useful,
37  but WITHOUT ANY WARRANTY; without even the implied warranty of
38  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39  Library General Public License for more details.
40 
41  You should have received a copy of the GNU Library General Public
42  License along with this library; if not, write to the Free
43  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 
45  The SDL_GL_* functions in this file are available in the public domain.
46 
47  Sam Lantinga
48  slouken@libsdl.org
49*/
50
51#include "glfont.h"
52
53#include <stdlib.h>
54#include <stdio.h>
55#include <string.h>
56
57#include "graphics_engine.h"
58#include "p_node.h"
59#include "vector.h"
60#include "debug.h"
61
62/**
63   \brief constructs a Font
64   \param fontFile the File to load the font from
65*/
66GLFont::GLFont(const char* fontFile)
67{
68  this->init(fontFile);
69}
70
71/**
72   \brief destructs a font
73*/
74GLFont::~GLFont(void)
75{
76  delete this->currentText;
77
78  if (this->font)
79    TTF_CloseFont(this->font);
80}
81
82/**
83   \brief function to enable TTF_Fonts
84*/
85void GLFont::enableFonts(void)
86{
87  if (!GLFont::ttfInitialized)
88    {
89      if(TTF_Init()==-1)
90        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
91
92      GLFont::checkVersion();
93      GLFont::ttfInitialized = true;
94    }
95  else
96    PRINTF(4)("Fonts already initialized\n");
97     
98}
99
100/**
101   \brief function to disable TTF_fonts
102*/
103void GLFont::disableFonts(void)
104{
105  if (GLFont::ttfInitialized)
106    {
107      TTF_Quit();
108      GLFont::ttfInitialized = false;
109    }
110  else
111    PRINTF(4)("Fonts were not initialized.\n");
112}
113
114//! A simple variable for checking if ttf was initialized
115bool GLFont::ttfInitialized = false;
116
117/**
118   \brief initializes a new Font
119   \param fontFile The file to load a Font from
120   \param fontSize the Size in pixels of the Font
121*/
122bool GLFont::init(const char* fontFile, unsigned int fontSize)
123{
124  if (!GLFont::ttfInitialized)
125    GLFont::enableFonts();
126
127  // setting default values.
128  this->font = NULL;
129  this->fontFile = NULL;
130
131  this->currentText = new Text;
132
133  this->currentText->bindNode = NULL;
134  this->currentText->text = NULL;
135  this->currentText->texture = 0;
136 
137  this->setSize(fontSize);
138 
139  this->currentText->renderStyle = TTF_STYLE_NORMAL;
140
141  this->setFont(fontFile);
142
143  this->setColor(0, 255, 0);
144
145  this->setText(FONT_DEFAULT_TEXT);
146
147  this->createTexture();
148}
149
150/**
151   \brief sets The Font.
152   \param fontFile The file containing the font.
153   \returns true if loaded, false if something went wrong, or if a font was loaded before.
154*/
155bool GLFont::setFont(const char* fontFile)
156{
157  if (!this->fontFile)
158    {
159      this->fontFile = new char[strlen(fontFile)+1];
160      strcpy(this->fontFile, fontFile);
161     
162      this->font = TTF_OpenFont(this->fontFile, this->fontSize);
163      if(!this->font) 
164        {
165          PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());
166          return false;
167      }
168      return true;
169    }
170  else
171    {
172      PRINTF(2)("Font already initialized, unable to change it now.\n");
173      return false;
174    }
175}
176
177void GLFont::setBindNode(PNode* bindNode)
178{
179  this->currentText->bindNode = bindNode;
180}
181
182
183/**
184   \brief Sets a new Text to the font
185   \param text the new text to set
186*/
187void GLFont::setText(const char* text)
188{
189  if (this->currentText->text)
190    delete []this->currentText->text;
191  this->currentText->text = new char[strlen(text)+1];
192  strcpy(this->currentText->text, text);
193}
194
195/**
196   \brief sets a specific renderStyle
197   \param renderStyle the Style to render: a char-array containing:
198   i: italic, b: bold, u, underline
199*/
200void GLFont::setStyle(char* renderStyle)
201{
202  this->currentText->renderStyle = TTF_STYLE_NORMAL;
203 
204  for (int i = 0; i < strlen(renderStyle); i++)
205    if (strncmp(renderStyle+i, "b", 1) == 0) 
206      this->currentText->renderStyle |= TTF_STYLE_BOLD;
207    else if (strncmp(renderStyle+i, "i", 1) == 0)
208      this->currentText->renderStyle |= TTF_STYLE_ITALIC;
209    else if (strncmp(renderStyle+i, "u", 1) == 0) 
210      this->currentText->renderStyle |= TTF_STYLE_UNDERLINE;
211
212  if (this->font)
213    TTF_SetFontStyle(this->font, this->currentText->renderStyle);
214  else
215    PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");
216}
217
218/**
219   \brief Sets a new Size to the font
220   \param fontSize The new Size in pixels.
221*/
222void GLFont::setSize(unsigned int fontSize)
223{
224  this->fontSize = fontSize;
225}
226
227/**
228   \brief sets a new color to the font
229   \param r Red
230   \param g Green
231   \param b Blue
232*/
233void GLFont::setColor(Uint8 r, Uint8 g, Uint8 b)
234{
235  this->currentText->color.r = r;
236  this->currentText->color.g = g;
237  this->currentText->color.b = b;
238}
239
240/**
241   \brief sets a Position.
242   \param x the x-position in pixels from the left border
243   \param y the y-position in pixels from the top border
244*/
245void GLFont::setPosition(int x, int y)
246{
247  this->currentText->textPosSize.x = x;
248  this->currentText->textPosSize.y = y;
249}
250
251/**
252   \brief draws the Font
253   \todo FIX this is to slow/static
254*/
255void GLFont::draw(void)
256{
257  GLdouble modMat[16];
258  GLint viewPort[4];
259  glGetDoublev(GL_PROJECTION_MATRIX, this->projMat);
260  glGetDoublev(GL_MODELVIEW_MATRIX, modMat);
261  glGetIntegerv(GL_VIEWPORT, viewPort);
262  this->enter2DMode();
263
264
265  Vector pos;
266  if (this->currentText->bindNode)
267    {
268      GLdouble x = this->currentText->bindNode->getAbsCoor().x;
269      GLdouble y = this->currentText->bindNode->getAbsCoor().y;
270      GLdouble z = this->currentText->bindNode->getAbsCoor().z;
271      GLdouble tmp[3];
272      gluProject(x, y, z, modMat, projMat, viewPort, tmp, tmp+1, tmp+2);
273      printf("test %f %f %f,\n", tmp[0], tmp[1], tmp[2]);
274      pos.x = tmp[0];
275      pos.y = GraphicsEngine::getInstance()->getResolutionY() - tmp[1];
276      pos.z = tmp[2];
277    }
278
279  glBindTexture(GL_TEXTURE_2D, this->currentText->texture);
280  glEnable(GL_TEXTURE_2D);
281  glBegin(GL_QUADS);
282 
283  glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.minV);
284  glVertex2i(pos.x,   pos.);
285
286  glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.minV);
287  glVertex2i(pos.x + this->currentText->textPosSize.w, pos.);
288
289  glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.maxV);
290  glVertex2i(pos.x + this->currentText->textPosSize.w, pos.y + this->currentText->textPosSize.h);
291
292  glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.maxV);
293  glVertex2i(pos.x, pos.y + this->currentText->textPosSize.h);
294
295  glEnd();
296
297  this->leave2DMode();
298}
299
300/**
301   \brief creates a texture out of the given parameters
302
303   this has to be called every time by the user, to if changes were made.
304*/
305void GLFont::createTexture(void)
306{
307  SDL_Surface* tmpSurf;
308  if (this->currentText->texture)
309    glDeleteTextures(1, &this->currentText->texture);
310  tmpSurf = TTF_RenderText_Blended(this->font,
311                                   this->currentText->text,
312                                   this->currentText->color);
313  if (tmpSurf)
314    this->currentText->texture = loadTexture(tmpSurf, &this->currentText->texCoord);
315
316  this->currentText->textPosSize.w = tmpSurf->w;
317  this->currentText->textPosSize.h = tmpSurf->h;
318  SDL_FreeSurface(tmpSurf);
319}
320
321
322/**
323   \returns the maximum height of the Font, if the font was initialized, 0 otherwise
324*/
325int GLFont::getMaxHeight(void)
326{
327  if (this->font)
328    return TTF_FontHeight(this->font);
329  else
330    return 0;
331}
332
333/**
334   \returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
335
336   the ascent is the pixels of the font above the baseline
337*/
338int GLFont::getMaxAscent(void)
339{
340  if (this->font)
341    return TTF_FontAscent(this->font);
342  else
343    return 0;
344}
345
346/**
347   \returns the maximum descent of the Font, if the font was initialized, 0 otherwise
348
349   the descent is the pixels of the font below the baseline
350*/
351int GLFont::getMaxDescent(void)
352{
353  if (this->font)
354    return TTF_FontDescent(this->font);
355  else
356    return 0;
357}
358
359/**
360   \param character The character to get info about.
361   \returns a Glyph struct of a character.
362
363   This only works for horizontal fonts. see
364   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
365   for more info about vertical Fonts
366*/
367Glyph GLFont::getGlyphMetrics(Uint16 character)
368{
369  Glyph rg;
370  rg.character = character;
371  TTF_GlyphMetrics(this->font, rg.character,
372                   &rg.minX, &rg.maxX,
373                   &rg.minY, &rg.maxY,
374                   &rg.advance);
375  rg.height = rg.maxY - rg.minY;
376  rg.width = rg.maxX - rg.minX;
377  rg.bearingX = (rg.advance - rg.width) / 2;
378  rg.bearingY = rg.maxY;
379  return rg;
380}
381
382/**
383   \brief entering 2D Mode
384   
385   this is a GL-Projection-mode, that is orthogonal, for placing the font in fron of everything else
386*/
387void GLFont::enter2DMode(void)
388{
389  SDL_Surface *screen = SDL_GetVideoSurface();
390 
391  /* Note, there may be other things you need to change,
392     depending on how you have your OpenGL state set up.
393  */
394  glPushAttrib(GL_ENABLE_BIT);
395  glDisable(GL_DEPTH_TEST);
396  glDisable(GL_CULL_FACE);
397  glDisable(GL_LIGHTING);  // will be set back when leaving 2D-mode
398  glEnable(GL_TEXTURE_2D);
399
400  /* This allows alpha blending of 2D textures with the scene */
401  glEnable(GL_BLEND);
402  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
403 
404  glViewport(0, 0, screen->w, screen->h);
405 
406  glMatrixMode(GL_PROJECTION);
407  glPushMatrix();
408  glLoadIdentity();
409 
410  glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
411 
412  glMatrixMode(GL_MODELVIEW);
413  glPushMatrix();
414  glLoadIdentity();
415 
416  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
417}
418
419/**
420   \brief leaves the 2DMode again also \see GLFont::enter2DMode(void)
421*/
422void GLFont::leave2DMode(void)
423{
424        glMatrixMode(GL_MODELVIEW);
425        glPopMatrix();
426
427        glMatrixMode(GL_PROJECTION);
428        glPopMatrix();
429
430        glPopAttrib();
431}
432
433/**
434   \brief Loads a Font from an SDL_surface into a texture.
435   \param surface The surface to make the texture of
436   \param texCoord The texture coordinates of the 4 corners of the texture
437   \returns the ID of the texture
438*/
439GLuint GLFont::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
440{
441  GLuint texture;
442  int w, h;
443  SDL_Surface *image;
444  SDL_Rect area;
445  Uint32 saved_flags;
446  Uint8  saved_alpha;
447 
448  /* Use the surface width and height expanded to powers of 2 */
449  w = powerOfTwo(surface->w);
450  h = powerOfTwo(surface->h);
451  texCoord->minU = 0.0f;
452  texCoord->minV = 0.0f;
453  texCoord->maxU = (GLfloat)surface->w / w;
454  texCoord->maxV = (GLfloat)surface->h / h;
455 
456  image = SDL_CreateRGBSurface(
457                               SDL_SWSURFACE,
458                               w, h,
459                               32,
460#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
461                               0x000000FF, 
462                               0x0000FF00, 
463                               0x00FF0000, 
464                               0xFF000000
465#else
466                               0xFF000000,
467                               0x00FF0000, 
468                               0x0000FF00, 
469                               0x000000FF
470#endif
471                               );
472  if ( image == NULL ) {
473    return 0;
474  }
475 
476  /* Save the alpha blending attributes */
477  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
478  saved_alpha = surface->format->alpha;
479  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
480    SDL_SetAlpha(surface, 0, 0);
481  }
482 
483  /* Copy the surface into the GL texture image */
484  area.x = 0;
485  area.y = 0;
486  area.w = surface->w;
487  area.h = surface->h;
488  SDL_BlitSurface(surface, &area, image, &area);
489 
490  /* Restore the alpha blending attributes */
491  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
492    SDL_SetAlpha(surface, saved_flags, saved_alpha);
493  }
494 
495  /* Create an OpenGL texture for the image */
496  glGenTextures(1, &texture);
497  glBindTexture(GL_TEXTURE_2D, texture);
498  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
499  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
500  glTexImage2D(GL_TEXTURE_2D,
501               0,
502               GL_RGBA,
503               w, h,
504               0,
505               GL_RGBA,
506               GL_UNSIGNED_BYTE,
507               image->pixels);
508  SDL_FreeSurface(image); /* No longer needed */
509 
510  return texture;
511}
512
513/**
514   \brief Quick utility function for texture creation
515   \param input an integer
516   \returns the next bigger 2^n-integer than input
517*/
518int GLFont::powerOfTwo(int input)
519{
520  int value = 1;
521 
522  while ( value < input ) {
523    value <<= 1;
524  }
525  return value;
526}
527
528
529/**
530   \brief checks if the compiled version and the local version of SDL_ttf match.
531   \returns true if match, false otherwise
532*/
533bool GLFont::checkVersion(void)
534{
535  SDL_version compile_version;
536  SDL_version link_version;
537  TTF_VERSION(&compile_version);
538  link_version = *TTF_Linked_Version();
539
540  if (compile_version.major == link_version.major &&
541      compile_version.minor == link_version.minor &&
542      compile_version.patch == link_version.patch)
543    {
544      return true;
545    }
546  else
547    {
548      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n", 
549                compile_version.major,
550                compile_version.minor,
551                compile_version.patch);
552     
553      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n", 
554                link_version.major,
555                link_version.minor,
556                link_version.patch);
557      return false;
558    }
559}
560
561
562
563/**
564   \brief a simple function to get some interesting information about this class
565*/
566void GLFont::debug(void)
567{
568
569  // print the loaded font's style
570  int style;
571  style=TTF_GetFontStyle(this->font);
572  PRINTF(0)("The font style is:");
573  if(style==TTF_STYLE_NORMAL)
574    PRINTF(0)(" normal");
575  else {
576    if(style&TTF_STYLE_BOLD)
577      PRINTF(0)(" bold");
578    if(style&TTF_STYLE_ITALIC)
579      PRINTF(0)(" italic");
580    if(style&TTF_STYLE_UNDERLINE)
581      PRINTF(0)(" underline");
582  }
583  PRINTF(0)("\n");
584
585
586}
587
588
589void m_inverse(const float *m, float *out)
590{
591    float det;
592    det=  m[0]*m[5]*m[10];
593    det+= m[4]*m[9]*m[2];
594    det+= m[8]*m[1]*m[6];
595    det-= m[8]*m[5]*m[2];
596    det-= m[4]*m[1]*m[10];
597    det-= m[0]*m[9]*m[6];
598   
599    if(det!= 0.0)
600        det=1.0/det;
601    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
602    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
603    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
604    out[3]= 0.0;
605    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
606    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
607    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
608    out[7]= 0.0;
609    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
610    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
611    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
612    out[11]= 0.0;
613    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
614    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
615    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
616    out[15]= 1.0;
617}
618
619
620Vector mvMult(const float *mat, const Vector* vec)
621{
622  Vector tmp;
623  tmp.x = mat[0]*vec->x+mat[1]*vec->y+mat[2]*vec->z;
624  tmp.y = mat[4]*vec->x+mat[5]*vec->y+mat[6]*vec->z;
625  tmp.z = mat[8]*vec->x+mat[9]*vec->y+mat[10]*vec->z;
626  return tmp;
627}
Note: See TracBrowser for help on using the repository browser.