font_ttf.cpp

Go to the documentation of this file.
00001 //#define WANT_TRACE
00002 
00003 #include "SDL.h"
00004 #include "SDL_ttf.h"
00005 #include "SDL_opengl.h"
00006 
00007 #include "log.h"
00008 #include "font_ttf.h"
00009 
00010 
00011 /* ***** SDL_UTILS **** */
00012 inline Uint32 getpixel(SDL_Surface *surface, int x, int y)
00013 {
00014     int bpp = surface->format->BytesPerPixel;
00015     /* Here p is the address to the pixel we want to retrieve */
00016     Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
00017 
00018     switch(bpp) {
00019     case 1:
00020         return *p;
00021 
00022     case 2:
00023         return *(Uint16 *)p;
00024 
00025     case 3:
00026         if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
00027             return p[0] << 16 | p[1] << 8 | p[2];
00028         else
00029             return p[0] | p[1] << 8 | p[2] << 16;
00030 
00031     case 4:
00032         return *(Uint32 *)p;
00033 
00034     default:
00035         return 0;       /* shouldn't happen, but avoids warnings */
00036     }
00037 }
00038 
00039 inline void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
00040 {
00041     int bpp = surface->format->BytesPerPixel;
00042     /* Here p is the address to the pixel we want to set */
00043     Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
00044 
00045     switch(bpp) {
00046     case 1:
00047         *p = pixel;
00048         break;
00049 
00050     case 2:
00051         *(Uint16 *)p = pixel;
00052         break;
00053 
00054     case 3:
00055         if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00056             p[0] = (pixel >> 16) & 0xff;
00057             p[1] = (pixel >> 8) & 0xff;
00058             p[2] = pixel & 0xff;
00059         } else {
00060             p[0] = pixel & 0xff;
00061             p[1] = (pixel >> 8) & 0xff;
00062             p[2] = (pixel >> 16) & 0xff;
00063         }
00064         break;
00065 
00066     case 4:
00067         *(Uint32 *)p = pixel;
00068         break;
00069     }
00070 }
00071 
00072 /* *** END OF UTILS *** */
00073 
00074 FontTTF::FontTTF(const char* file, int ptsize)
00075 {
00076         // Inicializing SDL_ttf
00077         if (!TTF_WasInit() && TTF_Init() == -1)
00078         {
00079                 LOGE << "Unable to init TTF: " << TTF_GetError() << endl;
00080                 DIE();
00081         }
00082         
00083         // Loading Font
00084         mFont = TTF_OpenFont(file, ptsize);
00085         if (!mFont)
00086         {
00087                 LOGE << "TTF_OpenFont: " << TTF_GetError() << endl;
00088                 DIE();
00089         }
00090 
00091         mWwidth = -1;
00092 }
00093 
00094 FontTTF::~FontTTF()
00095 {
00096         if (mFont)
00097         {
00098                 TTF_CloseFont(mFont);
00099                 mFont = 0;
00100         }
00101 
00102         // clearing the cache
00103         cleanCache();
00104         cleanCache();
00105         cleanCache();
00106 }
00107 
00108 SDL_Surface * ConvertToRGBA(SDL_Surface *surf)
00109 {
00110         TIN;
00111         
00112         SDL_PixelFormat rgba;
00113         rgba.palette       = 0;
00114         rgba.BitsPerPixel  = 32;
00115         rgba.BytesPerPixel = 4;
00116         rgba.Rloss         = 0;
00117         rgba.Gloss         = 0;
00118         rgba.Bloss         = 0;
00119         rgba.Aloss         = 0;
00120 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
00121         rgba.Rmask  = 0x000000FF;
00122         rgba.Gmask  = 0x0000FF00;
00123         rgba.Bmask  = 0x00FF0000;
00124         rgba.Amask  = 0xFF000000;
00125         rgba.Rshift = 0;
00126         rgba.Gshift = 8;
00127         rgba.Bshift = 16;
00128         rgba.Ashift = 24;
00129 #else
00130         rgba.Rmask  = 0xFF000000;
00131         rgba.Gmask  = 0x00FF0000;
00132         rgba.Bmask  = 0x0000FF00;
00133         rgba.Amask  = 0x000000FF;
00134         rgba.Rshift = 24;
00135         rgba.Gshift = 16;
00136         rgba.Bshift = 8;
00137         rgba.Ashift = 0;
00138 #endif
00139         rgba.colorkey = 0;
00140         rgba.alpha    = 0;
00141         
00142         
00143         SDL_Surface *tmp = SDL_ConvertSurface(surf, &rgba, SDL_SWSURFACE);
00144         
00145 
00146         SDL_LockSurface(surf);
00147         SDL_LockSurface(tmp);
00148         
00149         for (int x = 0; x < tmp->w; x++)
00150                 for (int y = 0; y < tmp->h; y++)
00151                 {
00152                         Uint32 col = getpixel(surf, x, y);
00153                         if (col == surf->format->colorkey || col == 0)
00154                         {
00155                                 col = SDL_MapRGBA(tmp->format, 250, 0, 0, 0);
00156                                 putpixel(tmp, x, y, col);
00157                         }
00158 
00159                 }
00160 
00161         SDL_UnlockSurface(surf);
00162         SDL_UnlockSurface(tmp);
00163 
00164         
00165         return tmp;
00166 }
00167 
00168 void SwapRows(SDL_Surface *surf)
00169 {
00170         TIN;
00171 
00172         Uint8 *hi_row, *lo_row, *tmp_row;
00173 
00174         tmp_row = new Uint8[surf->pitch];
00175 
00176         if (SDL_LockSurface(surf) == -1)
00177         {
00178                 LOGE << "Unable to lock surface" << endl;
00179                 DIE();
00180         }
00181         
00182         hi_row = (Uint8 *)surf->pixels;
00183         lo_row = hi_row + (surf->h*surf->pitch) - surf->pitch;
00184 
00185 
00186         for(int i = 0; i < surf->h / 2; i++)
00187         {
00188                 memcpy(tmp_row, hi_row, surf->pitch);
00189                 memcpy(hi_row,  lo_row, surf->pitch);
00190                 memcpy(lo_row, tmp_row, surf->pitch);
00191 
00192                 hi_row += surf->pitch;
00193                 lo_row -= surf->pitch;
00194         }
00195 
00196         SDL_UnlockSurface(surf);
00197 
00198         delete [] tmp_row;
00199 }
00200 
00201 void FontTTF::RenderUTF8(const std::string &utf8str, float x, float y)
00202 {
00203         TIN;
00204         
00205         
00206         SCacheMember *scm;
00207         
00208         // searching in cache
00209         TStringHash::iterator it = mRenderedCache.find(utf8str);
00210         
00211         // Create new string not foutn on cache
00212         if (it == mRenderedCache.end())
00213         {
00214                 LOGT << "creating new text" << endl;
00215                 
00216                 // TTF_Render has problem with empty strings
00217                 if (utf8str.empty()) return;
00218                 
00219                 // creating new record if not found
00220                 SDL_Color col = {255,255,255};
00221 //              SDL_Surface *surf = TTF_RenderUTF8_Blended(mFont, utf8str.c_str(), col);
00222 //              SDL_Surface *surf = TTF_RenderUTF8_Solid(mFont, utf8str.c_str(), col);
00223                 SDL_Surface *surf = TTF_RenderUTF8_Solid(mFont, utf8str.c_str(), col);
00224                 if (!surf)
00225                 {
00226                         LOGE << "Unable to render '" << utf8str << "': " << TTF_GetError() << endl;
00227                         return;
00228         //              DIE();
00229                 }
00230         
00231                 // Upgrading the surface :-)
00232                 SwapRows(surf);
00233         
00234                 // convert to texture
00235                 scm = new SCacheMember;
00236                 if (!scm)
00237                 {
00238                         DIE("new failed");
00239                 }
00240                 scm->usages  = 0;
00241                 scm->w       = surf->w;
00242                 scm->h       = surf->h;
00243                 scm->surface = ConvertToRGBA(surf);
00244                 // scm.texture = TextureManager::getInstance()->add(surf);
00245 
00246                 SDL_FreeSurface(surf);
00247 
00248                 mRenderedCache.insert(make_pair(utf8str, scm));
00249         }
00250         else
00251         {
00252                 scm = it->second;
00253         }
00254         
00255         
00256         // Draw the text 
00257         glEnable(GL_BLEND);
00258         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00259         
00260         glRasterPos2f(x, y);
00261 
00262         SDL_LockSurface(scm->surface);
00263         glDrawPixels( scm->w, scm->h, GL_RGBA, GL_UNSIGNED_BYTE, scm->surface->pixels);
00264         SDL_UnlockSurface(scm->surface);
00265 
00266         glDisable(GL_BLEND);
00267 
00268         scm->usages++;
00269 }
00270 
00271 void FontTTF::cleanCache()
00272 {
00273         LOGT << "Cleaning TTF chache. Size before: " << mRenderedCache.size() << endl;
00274 
00275         TStringHash::iterator it  = mRenderedCache.begin();
00276         
00277         while(it != mRenderedCache.end())
00278         {
00279                 if (it->second->usages == 0)
00280                 {
00281                 // Removing cache
00282                 
00283                         // 1. Free SDL_Surface
00284                         if (it->second->surface)
00285                         {
00286                                 SDL_FreeSurface(it->second->surface);
00287                                 it->second->surface = 0;
00288                         }
00289                         
00290                         // 2. Remove from hash table
00291                         if (it == mRenderedCache.begin())
00292                         {
00293                                 mRenderedCache.erase(it);
00294                                 it = mRenderedCache.begin();
00295                         }
00296                         else
00297                         {
00298                                 TStringHash::iterator it2 = it;
00299                                 ++it2; 
00300                                 mRenderedCache.erase(it);
00301                                 it = it2;
00302                         }
00303 
00304                 }
00305                 else
00306                 {
00307                         // Just reset usages to zero
00308                         it->second->usages = 0;
00309                         ++it;
00310                 }
00311         }
00312         
00313         LOGT << "Cleaning TTF chache. Size after: " << mRenderedCache.size() << endl;
00314 }
00315 
00316 
00317 int     FontTTF::Ascent()
00318 {
00319         assertL(mFont);
00320         
00321         return TTF_FontAscent(mFont);
00322 }
00323 
00324 int FontTTF::getWwidth()
00325 {
00326         assertL(mFont);
00327 
00328         if (mWwidth == -1)
00329         {
00330                 TTF_SizeText(mFont, "W", &mWwidth, 0);
00331         }
00332 
00333         return mWwidth;
00334 }
00335         
00336 int FontTTF::getTextWidth(const std::string &utf8str)
00337 {
00338         assertL(mFont);
00339 
00340         if (utf8str.empty()) return 0;
00341 
00342         int w;
00343         TTF_SizeUTF8(mFont, utf8str.c_str(), &w, 0);
00344 
00345         return w;
00346 }

Generated on Wed Apr 12 13:55:28 2006 for bjs by  doxygen 1.4.5