Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Apr 9, 2005, 4:19:55 PM (20 years ago)
Author:
bensch
Message:

orxonox/branches/textEngine: moved the fonts into a new File textEngine, and also implemented a TextEngine-Singleton-class

Location:
orxonox/branches/textEngine/src/lib/graphics/font
Files:
2 deleted
2 copied

Legend:

Unmodified
Added
Removed
  • orxonox/branches/textEngine/src/lib/graphics/font/text_engine.cc

    r3765 r3766  
    1010
    1111   ### File Specific:
    12    main-programmer: ...
     12   main-programmer: Benjamin Grauer
    1313   co-programmer: ...
    14 */
    15 
    16 //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
    17 
    18 #include "proto_singleton.h"
     14
     15   for some fonts and licenses visit: =http://www.dafont.com/en/font.php=
     16
     17   !! IMPORTANT !! When using ttf fonts clear the license issues prior to
     18   adding them to orxonox. This is really important, because we do not
     19   want to defend anyone.
     20*/
     21
     22#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_FONT
     23
     24#include "text_engine.h"
    1925
    2026using namespace std;
    2127
     28#include <stdlib.h>
     29#include <stdio.h>
     30#include <string.h>
     31
     32#include "graphics_engine.h"
     33#include "p_node.h"
     34#include "vector.h"
     35#include "debug.h"
     36
     37
     38////////////
     39/// FONT ///
     40////////////
     41
     42/**
     43   \brief constructs a Font
     44   \param fontFile the File to load the font from
     45*/
     46Font::Font(const char* fontFile)
     47{
     48  this->init(fontFile);
     49}
     50
     51/**
     52   \brief destructs a font
     53*/
     54Font::~Font(void)
     55{
     56  delete this->currentText;
     57
     58  if (this->glyphArray)
     59    {
     60      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
     61        delete this->glyphArray[i];
     62      delete []this->glyphArray;
     63    }
     64
     65  if (this->font)
     66    TTF_CloseFont(this->font);
     67}
     68
     69/**
     70   \brief initializes a new Font
     71   \param fontFile The file to load a Font from
     72   \param fontSize the Size in pixels of the Font
     73*/
     74bool Font::init(const char* fontFile, unsigned int fontSize)
     75{
     76  if (!TTF_WasInit())
     77    TextEngine::enableFonts();
     78
     79  // setting default values.
     80  this->font = NULL;
     81  this->fontFile = NULL;
     82  this->glyphArray = NULL;
     83  this->fastTextureID = 0;
     84
     85  this->currentText = new Text;
     86
     87  this->currentText->bindNode = NULL;
     88  this->currentText->text = NULL;
     89  this->currentText->texture = 0;
     90 
     91  this->setSize(fontSize);
     92  this->setType(TEXT_DYNAMIC);
     93 
     94  this->currentText->renderStyle = TTF_STYLE_NORMAL;
     95
     96  this->setFont(fontFile);
     97
     98  this->setColor(0, 255, 0);
     99  this->setPosition(0, 0);
     100
     101  this->setText(FONT_DEFAULT_TEXT);
     102 
     103  this->setColor(0,255,0);
     104
     105  this->createTexture();
     106
     107  this->fastTextureID = this->createFastTexture();
     108}
     109
     110/**
     111   \brief sets The Font.
     112   \param fontFile The file containing the font.
     113   \returns true if loaded, false if something went wrong, or if a font was loaded before.
     114*/
     115bool Font::setFont(const char* fontFile)
     116{
     117  if (!this->fontFile)
     118    {
     119      this->fontFile = new char[strlen(fontFile)+1];
     120      strcpy(this->fontFile, fontFile);
     121     
     122      this->font = TTF_OpenFont(this->fontFile, this->fontSize);
     123      if(!this->font)
     124        {
     125          PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());
     126          return false;
     127      }
     128      return true;
     129    }
     130  else
     131    {
     132      PRINTF(2)("Font already initialized, unable to change it now.\n");
     133      return false;
     134    }
     135}
     136
     137void Font::setBindNode(PNode* bindNode)
     138{
     139  this->currentText->bindNode = bindNode;
     140}
     141
     142/**
     143   \brief sets the Type of this Text
     144   \param type the type to set.
     145*/
     146void Font::setType(int type)
     147{
     148  this->currentText->type = type;
     149}
     150
     151
     152/**
     153   \brief Sets a new Text to the font
     154   \param text the new text to set
     155*/
     156void Font::setText(const char* text)
     157{
     158  if (this->currentText->text)
     159    delete []this->currentText->text;
     160  this->currentText->text = new char[strlen(text)+1];
     161  strcpy(this->currentText->text, text);
     162}
     163
     164/**
     165   \brief sets a specific renderStyle
     166   \param renderStyle the Style to render: a char-array containing:
     167   i: italic, b: bold, u, underline
     168*/
     169void Font::setStyle(char* renderStyle)
     170{
     171  this->currentText->renderStyle = TTF_STYLE_NORMAL;
     172 
     173  for (int i = 0; i < strlen(renderStyle); i++)
     174    if (strncmp(renderStyle+i, "b", 1) == 0)
     175      this->currentText->renderStyle |= TTF_STYLE_BOLD;
     176    else if (strncmp(renderStyle+i, "i", 1) == 0)
     177      this->currentText->renderStyle |= TTF_STYLE_ITALIC;
     178    else if (strncmp(renderStyle+i, "u", 1) == 0)
     179      this->currentText->renderStyle |= TTF_STYLE_UNDERLINE;
     180
     181  if (this->font)
     182    TTF_SetFontStyle(this->font, this->currentText->renderStyle);
     183  else
     184    PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");
     185}
     186
     187/**
     188   \brief Sets a new Size to the font
     189   \param fontSize The new Size in pixels.
     190*/
     191void Font::setSize(unsigned int fontSize)
     192{
     193  this->fontSize = fontSize;
     194}
     195
     196/**
     197   \brief sets a new color to the font
     198   \param r Red
     199   \param g Green
     200   \param b Blue
     201*/
     202void Font::setColor(Uint8 r, Uint8 g, Uint8 b)
     203{
     204  this->currentText->color.r = r;
     205  this->currentText->color.g = g;
     206  this->currentText->color.b = b;
     207}
     208
     209/**
     210   \brief sets a Position.
     211   \param x the x-position in pixels from the left border
     212   \param y the y-position in pixels from the top border
     213*/
     214void Font::setPosition(int x, int y)
     215{
     216  this->currentText->textPosSize.x = x;
     217  this->currentText->textPosSize.y = y;
     218}
     219
     220/**
     221   \brief draws the Font
     222   \todo FIX this is to slow/static
     223*/
     224void Font::draw(void)
     225{
     226  // storing all the Transformation Matrices.
     227  GLdouble modMat[16];
     228  GLint viewPort[4];
     229  glGetDoublev(GL_PROJECTION_MATRIX, this->projMat);
     230  glGetDoublev(GL_MODELVIEW_MATRIX, modMat);
     231  glGetIntegerv(GL_VIEWPORT, viewPort);
     232  this->enter2DMode();
     233
     234  // setting the Position of this Text.
     235  Vector pos;
     236  if (this->currentText->bindNode)
     237    {
     238      GLdouble x = this->currentText->bindNode->getAbsCoor().x;
     239      GLdouble y = this->currentText->bindNode->getAbsCoor().y;
     240      GLdouble z = this->currentText->bindNode->getAbsCoor().z;
     241      GLdouble tmp[3];
     242      gluProject(x, y, z, modMat, projMat, viewPort, tmp, tmp+1, tmp+2);
     243      printf("test %f %f %f,\n", tmp[0], tmp[1], tmp[2]);
     244      pos.x = tmp[0] + this->currentText->textPosSize.x;
     245      pos.y = GraphicsEngine::getInstance()->getResolutionY() - tmp[1] + this->currentText->textPosSize.y;
     246      pos.z = tmp[2];
     247    }
     248  else
     249    {
     250      pos.x = this->currentText->textPosSize.x;
     251      pos.y = this->currentText->textPosSize.y;
     252      pos.z = 0;
     253    }
     254
     255  // drawing this Text.
     256  if(currentText->type == TEXT_STATIC)
     257    {
     258      glBindTexture(GL_TEXTURE_2D, this->currentText->texture);
     259      glEnable(GL_TEXTURE_2D);
     260      glBegin(GL_QUADS);
     261     
     262      glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.minV);
     263      glVertex2i(pos.x,   pos.y  );
     264     
     265      glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.minV);
     266      glVertex2i(pos.x + this->currentText->textPosSize.w, pos.y  );
     267     
     268      glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.maxV);
     269      glVertex2i(pos.x + this->currentText->textPosSize.w, pos.y + this->currentText->textPosSize.h);
     270     
     271      glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.maxV);
     272      glVertex2i(pos.x, pos.y + this->currentText->textPosSize.h);
     273     
     274      glEnd();
     275    }
     276  else //(if currentText->type & TEXT_DYNAMIC)
     277    {
     278      glBindTexture(GL_TEXTURE_2D, this->fastTextureID);
     279      //      glEnable(GL_TEXTURE_2D);
     280      glTranslatef(pos.x, pos.y, 0);
     281
     282      printf("%d, %d\n", this->fastTextureID, glyphArray[65]->displayList);
     283      char* tmpText = this->currentText->text;
     284      while (*tmpText != '\0')
     285        {
     286          if(glyphArray[*tmpText])
     287            {
     288              glCallList(this->glyphArray[*tmpText]->displayList);
     289              glTranslatef(this->glyphArray[*tmpText]->width, 0, 0);
     290            }
     291          tmpText++;
     292        }
     293    }
     294  this->leave2DMode();
     295}
     296
     297/**
     298   \brief creates a texture out of the given parameters
     299
     300   this has to be called every time by the user, to if changes were made.
     301*/
     302void Font::createTexture(void)
     303{
     304  SDL_Surface* tmpSurf;
     305  if (this->currentText->texture)
     306    glDeleteTextures(1, &this->currentText->texture);
     307  tmpSurf = TTF_RenderText_Blended(this->font,
     308                                   this->currentText->text,
     309                                   this->currentText->color);
     310  if (tmpSurf)
     311    this->currentText->texture = loadTexture(tmpSurf, &this->currentText->texCoord);
     312
     313  this->currentText->textPosSize.w = tmpSurf->w;
     314  this->currentText->textPosSize.h = tmpSurf->h;
     315  SDL_FreeSurface(tmpSurf);
     316}
     317
     318
     319/**
     320   \returns the maximum height of the Font, if the font was initialized, 0 otherwise
     321*/
     322int Font::getMaxHeight(void)
     323{
     324  if (this->font)
     325    return TTF_FontHeight(this->font);
     326  else
     327    return 0;
     328}
     329
     330/**
     331   \returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
     332
     333   the ascent is the pixels of the font above the baseline
     334*/
     335int Font::getMaxAscent(void)
     336{
     337  if (this->font)
     338    return TTF_FontAscent(this->font);
     339  else
     340    return 0;
     341}
     342
     343/**
     344   \returns the maximum descent of the Font, if the font was initialized, 0 otherwise
     345
     346   the descent is the pixels of the font below the baseline
     347*/
     348int Font::getMaxDescent(void)
     349{
     350  if (this->font)
     351    return TTF_FontDescent(this->font);
     352  else
     353    return 0;
     354}
     355
     356/**
     357   \param character The character to get info about.
     358   \returns a Glyph struct of a character. This Glyph is a pointer,
     359   and MUST be deleted by the user..
     360
     361   This only works for horizontal fonts. see
     362   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
     363   for more info about vertical Fonts
     364*/
     365Glyph* Font::getGlyphMetrics(Uint16 character)
     366{
     367  Glyph* rg = new Glyph;
     368  rg->character = character;
     369  TTF_GlyphMetrics(this->font, rg->character,
     370                   &rg->minX, &rg->maxX,
     371                   &rg->minY, &rg->maxY,
     372                   &rg->advance);
     373  rg->height = rg->maxY - rg->minY;
     374  rg->width = rg->maxX - rg->minX;
     375  rg->bearingX = (rg->advance - rg->width) / 2;
     376  rg->bearingY = rg->maxY;
     377  return rg;
     378}
     379
     380/**
     381   \brief entering 2D Mode
     382   
     383   this is a GL-Projection-mode, that is orthogonal, for placing the font in fron of everything else
     384*/
     385void Font::enter2DMode(void)
     386{
     387  SDL_Surface *screen = SDL_GetVideoSurface();
     388 
     389  /* Note, there may be other things you need to change,
     390     depending on how you have your OpenGL state set up.
     391  */
     392  glPushAttrib(GL_ENABLE_BIT);
     393  glDisable(GL_DEPTH_TEST);
     394  glDisable(GL_CULL_FACE);
     395  glDisable(GL_LIGHTING);  // will be set back when leaving 2D-mode
     396  glEnable(GL_TEXTURE_2D);
     397
     398  /* This allows alpha blending of 2D textures with the scene */
     399  glEnable(GL_BLEND);
     400  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     401 
     402  glViewport(0, 0, screen->w, screen->h);
     403 
     404  glMatrixMode(GL_PROJECTION);
     405  glPushMatrix();
     406  glLoadIdentity();
     407 
     408  glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
     409 
     410  glMatrixMode(GL_MODELVIEW);
     411  glPushMatrix();
     412  glLoadIdentity();
     413 
     414  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     415}
     416
     417/**
     418   \brief leaves the 2DMode again also \see Font::enter2DMode(void)
     419*/
     420void Font::leave2DMode(void)
     421{
     422        glMatrixMode(GL_MODELVIEW);
     423        glPopMatrix();
     424
     425        glMatrixMode(GL_PROJECTION);
     426        glPopMatrix();
     427
     428        glPopAttrib();
     429}
     430
     431
     432GLuint Font::createFastTexture(void)
     433{
     434  /* interesting GLYPHS:
     435   *  33-47: Special Characters.
     436   *  48-57: 0-9
     437   *  58-63: some more special chars (minor)
     438   *  65-90: A-Z
     439   *  97-122: a-z
     440   */
     441  int numberOfGlyphs = 90;
     442
     443  this->initGlyphs(33, numberOfGlyphs);
     444
     445  int rectSize = this->findOptimalFastTextureSize();
     446
     447  // setting default values. (maybe not needed afterwards)
     448  SDL_Color tmpColor;  tmpColor.r = tmpColor.g = tmpColor.b = 0;
     449  // Surface definition.
     450  SDL_Rect tmpRect; // this represents a Rectangle for blitting.
     451  SDL_Surface* tmpSurf =  SDL_CreateRGBSurface(SDL_SWSURFACE,
     452                                               rectSize, rectSize,
     453                                               32,
     454#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
     455                                               0x000000FF,
     456                                               0x0000FF00,
     457                                               0x00FF0000,
     458                                               0xFF000000
     459#else
     460                                               0xFF000000,
     461                                               0x00FF0000,
     462                                               0x0000FF00,
     463                                               0x000000FF
     464#endif
     465                                               );
     466  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
     467  SDL_SetClipRect(tmpSurf, &tmpRect);
     468  int maxLineHeight = 0;
     469
     470  // all the interessting Glyphs
     471  for (int i = 33; i <= 122; i++)
     472    {
     473      SDL_Surface* glyphSurf = NULL;
     474      Glyph* tmpGlyph;
     475
     476      if (tmpGlyph = this->glyphArray[i])
     477        {
     478          if (tmpGlyph->height > maxLineHeight)
     479            maxLineHeight = tmpGlyph->height;
     480         
     481          if (tmpRect.x+tmpGlyph->width > tmpSurf->w)
     482            {
     483              tmpRect.x = 0;
     484              tmpRect.y = tmpRect.y + maxLineHeight + 1;
     485              maxLineHeight = 0;
     486            }
     487          if (tmpRect.y + maxLineHeight > tmpSurf->h)
     488            {
     489              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
     490              break;
     491            }
     492          // reading in the new Glyph
     493          //glyphSurf = TTF_RenderGlyph_Shaded(this->font, i, this->currentText->color, tmpColor);
     494          glyphSurf = TTF_RenderGlyph_Blended(this->font, i, this->currentText->color);
     495          if( glyphSurf )
     496            {
     497
     498              SDL_SetAlpha(glyphSurf, 0, 0);
     499
     500              SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);
     501              TexCoord tmpTexCoord;
     502              tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;
     503              tmpTexCoord.maxU = (float)(tmpRect.x+tmpGlyph->width)/(float)tmpSurf->w;
     504              tmpTexCoord.minV = (float)tmpRect.y/(float)tmpSurf->w;
     505              tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;
     506              tmpGlyph->displayList = glGenLists(1);
     507
     508              glNewList(tmpGlyph->displayList, GL_COMPILE);
     509              glBegin(GL_QUADS);
     510              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);
     511              glVertex2d(0, 0);
     512              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
     513              glVertex2d(0, tmpGlyph->height);
     514              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
     515              glVertex2d(tmpGlyph->width, tmpGlyph->height);
     516              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
     517              glVertex2d(tmpGlyph->width, 0);
     518              glEnd();
     519              glEndList();
     520              SDL_FreeSurface(glyphSurf);
     521
     522              tmpRect.x += tmpGlyph->width + 1;
     523
     524              // Outputting Glyphs to BMP-files.
     525              /*
     526                char outname[64];
     527                if (i < 10)
     528                sprintf( outname, "glyph-00%d.bmp", i );
     529                else if (i <100)
     530                sprintf( outname, "glyph-0%d.bmp", i );
     531                else
     532                sprintf( outname, "glyph-%d.bmp", i );
     533                SDL_SaveBMP(tmpSurf, outname);
     534              */
     535            }
     536        }
     537    }
     538  GLuint texture;
     539  glGenTextures(1, &texture);
     540  glBindTexture(GL_TEXTURE_2D, texture);
     541  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     542  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     543  glTexImage2D(GL_TEXTURE_2D,
     544               0,
     545               GL_RGBA,
     546               tmpSurf->w, tmpSurf->h,
     547               0,
     548               GL_RGBA,
     549               GL_UNSIGNED_BYTE,
     550               tmpSurf->pixels);
     551  SDL_FreeSurface(tmpSurf);
     552  return texture;
     553}
     554
     555/**
     556   \brief Loads a Font from an SDL_surface into a texture.
     557   \param surface The surface to make the texture of
     558   \param texCoord The texture coordinates of the 4 corners of the texture
     559   \returns the ID of the texture
     560*/
     561GLuint Font::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
     562{
     563  GLuint texture;
     564  int w, h;
     565  SDL_Surface *image;
     566  SDL_Rect area;
     567  Uint32 saved_flags;
     568  Uint8  saved_alpha;
     569 
     570  /* Use the surface width and height expanded to powers of 2 */
     571  w = powerOfTwo(surface->w);
     572  h = powerOfTwo(surface->h);
     573  if (texCoord)
     574    {
     575      texCoord->minU = 0.0f;
     576      texCoord->minV = 0.0f;
     577      texCoord->maxU = (GLfloat)surface->w / w;
     578      texCoord->maxV = (GLfloat)surface->h / h;
     579    }
     580  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
     581                               w, h,
     582                               32,
     583#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
     584                               0x000000FF,
     585                               0x0000FF00,
     586                               0x00FF0000,
     587                               0xFF000000
     588#else
     589                               0xFF000000,
     590                               0x00FF0000,
     591                               0x0000FF00,
     592                               0x000000FF
     593#endif
     594                               );
     595  if ( image == NULL ) {
     596    return 0;
     597  }
     598 
     599  /* Save the alpha blending attributes */
     600  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
     601  saved_alpha = surface->format->alpha;
     602  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
     603    SDL_SetAlpha(surface, 0, 0);
     604  }
     605 
     606  /* Copy the surface into the GL texture image */
     607  area.x = 0;
     608  area.y = 0;
     609  area.w = surface->w;
     610  area.h = surface->h;
     611  SDL_BlitSurface(surface, &area, image, &area);
     612 
     613  /* Restore the alpha blending attributes */
     614  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
     615    SDL_SetAlpha(surface, saved_flags, saved_alpha);
     616  }
     617 
     618  /* Create an OpenGL texture for the image */
     619  glGenTextures(1, &texture);
     620  glBindTexture(GL_TEXTURE_2D, texture);
     621  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     622  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     623  glTexImage2D(GL_TEXTURE_2D,
     624               0,
     625               GL_RGBA,
     626               w, h,
     627               0,
     628               GL_RGBA,
     629               GL_UNSIGNED_BYTE,
     630               image->pixels);
     631  SDL_FreeSurface(image); /* No longer needed */
     632 
     633  return texture;
     634}
     635
     636/**
     637   \brief stores Glyph Metrics in an Array.
     638   \param from The Glyph to start from.
     639   \param count The number of Glyphs to start From.
     640*/
     641void Font::initGlyphs(Uint16 from, Uint16 count)
     642{
     643  /* initialize the Array, and set all its entries to NULL
     644   *  only if the Glyph-array has not been initialized
     645   */
     646  if (!this->glyphArray)
     647    {
     648      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
     649      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
     650        this->glyphArray[i] = NULL;
     651    }
     652 
     653  Uint16 lastGlyph = from + count;
     654 
     655  for (int i = from; i <= lastGlyph; i++)
     656    {
     657      // setting up all the Glyphs we like.
     658      glyphArray[i] = getGlyphMetrics(i);
     659    }
     660  return;
     661}
     662
     663/**
     664   \returns the optimal size to use as the texture size
     665
     666   \todo: this algorithm can be a lot more faster, althought it does
     667   not really matter within the init-context, and 128 glyphs.
     668
     669   This function searches for a 2^n sizes texture-size, this is for
     670   openGL-version < 1.2 compatibility. and because it is realy easy like this.
     671*/
     672int Font::findOptimalFastTextureSize(void)
     673{
     674  int i;
     675  int x,y; // the counters
     676  int maxLineHeight;
     677  int size = 32;      // starting Value, we have to start somewhere 32 seems reasonable.
     678  bool sizeOK = false;
     679  Glyph* tmpGlyph;
     680
     681  while (!sizeOK)
     682    {
     683      x = 0; y = 0;
     684      maxLineHeight = 0;
     685      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
     686        {
     687          if(tmpGlyph = this->glyphArray[i])
     688            {
     689              // getting the height of the highest Glyph in the Line.
     690              if (tmpGlyph->height > maxLineHeight)
     691                maxLineHeight = tmpGlyph->height;
     692
     693              if (x + tmpGlyph->width > size)
     694                {
     695                  x = 0;
     696                  y = y + maxLineHeight;
     697                  maxLineHeight = 0;
     698                }
     699              if (y + maxLineHeight + 1 > size)
     700                break;
     701              x += tmpGlyph->width + 1;
     702
     703            }
     704        }
     705      if (i == FONT_HIGHEST_KNOWN_CHAR)
     706        sizeOK = true;
     707      else
     708        size *= 2;
     709    }
     710  return size;
     711 
     712}
     713
     714/**
     715   \brief Quick utility function for texture creation
     716   \param input an integer
     717   \returns the next bigger 2^n-integer than input
     718*/
     719int Font::powerOfTwo(int input)
     720{
     721  int value = 1;
     722 
     723  while ( value < input ) {
     724    value <<= 1;
     725  }
     726  return value;
     727}
     728
     729
     730
     731/**
     732   \brief a simple function to get some interesting information about this class
     733*/
     734void Font::debug(void)
     735{
     736
     737  // print the loaded font's style
     738  int style;
     739  style=TTF_GetFontStyle(this->font);
     740  PRINTF(0)("The font style is:");
     741  if(style==TTF_STYLE_NORMAL)
     742    PRINTF(0)(" normal");
     743  else {
     744    if(style&TTF_STYLE_BOLD)
     745      PRINTF(0)(" bold");
     746    if(style&TTF_STYLE_ITALIC)
     747      PRINTF(0)(" italic");
     748    if(style&TTF_STYLE_UNDERLINE)
     749      PRINTF(0)(" underline");
     750  }
     751  PRINTF(0)("\n");
     752
     753
     754}
     755
     756
     757void m_inverse(const float *m, float *out)
     758{
     759    float det;
     760    det=  m[0]*m[5]*m[10];
     761    det+= m[4]*m[9]*m[2];
     762    det+= m[8]*m[1]*m[6];
     763    det-= m[8]*m[5]*m[2];
     764    det-= m[4]*m[1]*m[10];
     765    det-= m[0]*m[9]*m[6];
     766   
     767    if(det!= 0.0)
     768        det=1.0/det;
     769    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
     770    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
     771    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
     772    out[3]= 0.0;
     773    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
     774    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
     775    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
     776    out[7]= 0.0;
     777    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
     778    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
     779    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
     780    out[11]= 0.0;
     781    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
     782    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
     783    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
     784    out[15]= 1.0;
     785}
     786
     787
     788Vector mvMult(const float *mat, const Vector* vec)
     789{
     790  Vector tmp;
     791  tmp.x = mat[0]*vec->x+mat[1]*vec->y+mat[2]*vec->z;
     792  tmp.y = mat[4]*vec->x+mat[5]*vec->y+mat[6]*vec->z;
     793  tmp.z = mat[8]*vec->x+mat[9]*vec->y+mat[10]*vec->z;
     794  return tmp;
     795}
     796
     797
     798
     799
     800
     801
     802
     803
     804
     805
     806
     807
     808
     809
    22810
    23811/**
    24812   \brief standard constructor
    25813*/
    26 ProtoSingleton::ProtoSingleton ()
    27 {
    28    this->setClassName ("ProtoSingleton");
     814TextEngine::TextEngine ()
     815{
     816   this->setClassName ("TextEngine");
    29817
    30818}
     
    33821   \brief the singleton reference to this class
    34822*/
    35 ProtoSingleton* ProtoSingleton::singletonRef = NULL;
     823TextEngine* TextEngine::singletonRef = NULL;
    36824
    37825/**
    38826   \returns a Pointer to this Class
    39827*/
    40 ProtoSingleton* ProtoSingleton::getInstance(void)
    41 {
    42   if (!ProtoSingleton::singletonRef)
    43     ProtoSingleton::singletonRef = new ProtoSingleton();
    44   return ProtoSingleton::singletonRef;
     828TextEngine* TextEngine::getInstance(void)
     829{
     830  if (!TextEngine::singletonRef)
     831    TextEngine::singletonRef = new TextEngine();
     832  return TextEngine::singletonRef;
    45833}
    46834
     
    49837
    50838*/
    51 ProtoSingleton::~ProtoSingleton ()
    52 {
    53   ProtoSingleton::singletonRef = NULL;
    54 
    55 }
     839TextEngine::~TextEngine ()
     840{
     841  TextEngine::singletonRef = NULL;
     842
     843}
     844
     845/**
     846   \brief function to enable TTF_Fonts
     847*/
     848void TextEngine::enableFonts(void)
     849{
     850  if (!TTF_WasInit())
     851    {
     852      if(TTF_Init()==-1)
     853        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
     854
     855      TextEngine::checkVersion();
     856    }
     857  else
     858    PRINTF(4)("Fonts already initialized\n");
     859     
     860}
     861
     862/**
     863   \brief function to disable TTF_fonts
     864*/
     865void TextEngine::disableFonts(void)
     866{
     867  if (TTF_WasInit())
     868    {
     869      TTF_Quit();
     870    }
     871  else
     872    PRINTF(4)("Fonts were not initialized.\n");
     873}
     874
     875/**
     876   \brief checks if the compiled version and the local version of SDL_ttf match.
     877   \returns true if match, false otherwise
     878*/
     879bool TextEngine::checkVersion(void)
     880{
     881  SDL_version compile_version;
     882  SDL_version link_version;
     883  TTF_VERSION(&compile_version);
     884  link_version = *TTF_Linked_Version();
     885
     886  if (compile_version.major == link_version.major &&
     887      compile_version.minor == link_version.minor &&
     888      compile_version.patch == link_version.patch)
     889    {
     890      return true;
     891    }
     892  else
     893    {
     894      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n",
     895                compile_version.major,
     896                compile_version.minor,
     897                compile_version.patch);
     898     
     899      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n",
     900                link_version.major,
     901                link_version.minor,
     902                link_version.patch);
     903      return false;
     904    }
     905}
  • orxonox/branches/textEngine/src/lib/graphics/font/text_engine.h

    r3765 r3766  
    11/*!
    2     \file proto_singleton.h
    3     \brief Definition of the proto class template, used quickly start work
    4    
    5     a simple file to copy and create a singleton-class from
     2    \file text_engine.h
     3    \brief Definition of textEngine, the Font and the Text
     4
     5    Text is the text outputed.
     6    Font is a class that loads a certain ttf-file with a specific height into memory
     7    TextEngine is used to manage the all the different Fonts that might be included
     8
     9    for more information see the specific classes.
    610*/
    711
    8 #ifndef _PROTO_SINGLETON_H
    9 #define _PROTO_SINGLETON_H
     12#ifndef _TEXT_ENGINE_H
     13#define _TEXT_ENGINE_H
    1014
     15
     16#include "glincl.h"
     17#include "SDL_ttf.h"
     18
     19#include "vector.h"
    1120#include "base_object.h"
    1221
    13 // FORWARD DEFINITION \\
     22// FORWARD DECLARATION
     23class PNode;
     24template<class T> class tList;
    1425
    15 //! A default singleton class.
    16 class ProtoSingleton : public BaseObject {
     26
     27/* some default values */
     28#define FONT_DEFAULT_SIZE       50                   //!< default size of the Text
     29#define FONT_DEFAULT_TEXT       "orxonox 1234567890" //!< some default text to display
     30#define FONT_DEFAULT_COLOR_R    256                  //!< the default red part (color) of the text
     31#define FONT_DEFAULT_COLOR_G    256                  //!< the default red green (color) of the text
     32#define FONT_DEFAULT_COLOR_B    256                  //!< the default red blue (color) of the text
     33#define FONT_NUM_COLORS         256                  //!< The number of colors.
     34
     35#define FONT_HIGHEST_KNOWN_CHAR 128                  //!< The highest character known to the textEngine.
     36
     37#define TEXT_STATIC             0                    //!< Static Text
     38#define TEXT_DYNAMIC            1                    //!< Dynamic Text
     39/**
     40 * STATIC means: a font, that is only one GL-face.
     41 ** it is very fast, and can be used for all text
     42 ** that does not have to be changed anymore, or if
     43 ** the the text should look very nice
     44 * DYNAMIC means: a very fast font, that will is build
     45 ** from multiple quads.
     46 ** Use this type, if you want to create fast changing
     47 ** text like a counter.
     48 */
     49
     50
     51//! A Struct to handel Texture Coordinates for quads
     52struct TexCoord
     53{
     54  float minU;                      //!< The minimum U-Coordinate
     55  float maxU;                      //!< The maximum U-Coordinate
     56  float minV;                      //!< The minimum V-Coordinate
     57  float maxV;                      //!< The maximum V-Coordinate
     58};
     59
     60//! A struct for handling glyphs
     61/**
     62   a Glyph is one letter of a certain font
     63*/
     64struct Glyph
     65{
     66  // Glyph-specific (size and so on)
     67  Uint16 character;              //!< The character
     68  int minX;                      //!< The minimum distance from the origin in X
     69  int maxX;                      //!< The maximum distance from the origin in X
     70  int minY;                      //!< The minimum distance from the origin in Y
     71  int maxY;                      //!< The maximum distance from the origin in Y
     72  int width;                     //!< The width of the Glyph
     73  int height;                    //!< The height of the Glyph
     74  int bearingX;                  //!< How much is right of the Origin
     75  int bearingY;                  //!< How much is above the Origin
     76  int advance;                   //!< How big a Glyph would be in monospace-mode
     77 
     78  // OpenGL-specific
     79  //  TexCoord texCoord;             //!< A Texture Coordinate for this glyph.
     80  GLuint displayList;            //!< DiplayList to render this Glyph.
     81};
     82
     83//! A class to handle a Font
     84class Font
     85{
     86 public:
     87  Font(const char* fontFile);
     88  virtual ~Font();
     89
     90  // font
     91  bool setFont(const char* fontFile);
     92  void setSize(unsigned int fontSize);
     93  void setColor(Uint8 r, Uint8 g, Uint8 b);
     94
     95  // text
     96  void setBindNode(PNode* bindNode);
     97  void setType(int type);
     98  void setText(const char* text);
     99  void setStyle(char* renderStyle);
     100  void setPosition(int x, int y);
     101  void createTexture(void);
     102 
     103  virtual void draw(void);
     104
     105 private:
     106  // general purpose
     107  GLdouble projMat[16];             //!< The Projection Matrix
     108
     109  // information about the Font
     110  TTF_Font* font;                   //!< The font we use for this.
     111  char* fontFile;                   //!< The fontfile from whitch the font was loaded.
     112  unsigned int fontSize;            //!< The size of the font in pixels. each Font has one size.
     113 
     114  Glyph** glyphArray;               //!< An Array of all the Glyphs stored in the Array of Glyphs.
     115  GLuint fastTextureID;             //!< The fast textureID.
     116
     117  //! Represents one textElement.
     118  struct Text
     119  {
     120    int type;                   //!< The type of this Font.
     121    char* text;                      //!< The text to display
     122    SDL_Color color;                 //!< The color of the font.
     123    // placement in openGL
     124    GLuint texture;                  //!< A GL-texture to hold the text
     125    TexCoord texCoord;               //!< Texture-coordinates \todo fix this to have a struct
     126    SDL_Rect textPosSize;            //!< An SDL-Rectangle representing the position and size of the Text on the screen.
     127    int renderStyle;                 //!< The Renderstyle
     128
     129    PNode* bindNode;                 //!< A node the Text is bind to. (if NULL thr node will not be bound to anything.)
     130  };
     131  tList<Text>* textList;
     132  Text* currentText;
     133
     134  bool init(const char* fontFile, unsigned int fontSize = FONT_DEFAULT_SIZE);
     135  int getMaxHeight(void);
     136  int getMaxAscent(void);
     137  int getMaxDescent(void);
     138  Glyph* getGlyphMetrics(Uint16 character);
     139
     140  void enter2DMode(void);
     141  void leave2DMode(void);
     142
     143
     144  GLuint createFastTexture();
     145  GLuint loadTexture(SDL_Surface* surface, TexCoord* texCoord);
     146
     147  void initGlyphs(Uint16 from, Uint16 count);
     148  int findOptimalFastTextureSize(void);
     149  static int powerOfTwo(int input);
     150
     151  void debug(void);
     152
     153};
     154
     155void m_inverse(const float *m, float *out);
     156Vector mvMult(const float *mat, const Vector* vec);
     157
     158
     159///////////////////
     160/// TEXT-ENGINE ///
     161///////////////////
     162//! A singleton Class that operates as a Handler for generating and rendering Text in 2D
     163class TextEngine : public BaseObject {
    17164
    18165 public:
    19   static ProtoSingleton* getInstance(void);
    20   virtual ~ProtoSingleton(void);
     166  static TextEngine* getInstance(void);
     167  virtual ~TextEngine(void);
     168
     169  // general
     170  static void enableFonts(void);
     171  static void disableFonts(void);
     172  static bool checkVersion(void);
    21173
    22174 private:
    23   ProtoSingleton(void);
    24   static ProtoSingleton* singletonRef;
     175  TextEngine(void);
     176  static TextEngine* singletonRef;
     177
    25178};
    26179
    27 #endif /* _PROTO_SINGLETON_H */
     180#endif /* _TEXT_ENGINE_H */
Note: See TracChangeset for help on using the changeset viewer.