# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

texture_font.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 #include <map>
00028 
00029 #include "3d/texture_font.h"
00030 #include "3d/font_generator.h"
00031 
00032 #include "nel/misc/common.h"
00033 #include "nel/misc/rect.h"
00034 #include "nel/misc/file.h"
00035 
00036 
00037 using namespace std;
00038 using namespace NLMISC;
00039 
00040 namespace NL3D
00041 {
00042 
00043 // Config 1
00044 const int TextureSizeX = 1024;
00045 const int TextureSizeY = 1024; // If change this value -> change NbLine too
00046 const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32, 64 };
00047 const int NbLine[TEXTUREFONT_NBCATEGORY] = { 8, 24, 16, 4, 1 }; // Based on textsize
00048 
00049 /*      
00050 const int TextureSizeX = 256;
00051 const int TextureSizeY = 256;
00052 const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32 };
00053 const int NbLine[TEXTUREFONT_NBCATEGORY] = { 4, 6, 4, 1 }; // Based on textsize
00054 */
00055 // ---------------------------------------------------------------------------
00056 inline uint32 CTextureFont::SLetterKey::getVal()
00057 {
00058         return Char + ((Size&255)<<16) + ((((uint32)FontGenerator)&255)<<24);
00059 }
00060 
00061 /*bool CTextureFont::SLetterKey::operator < (const CTextureFont::SLetterKey&k) const
00062 {
00063         if (Char < k.Char)
00064                 return true;
00065         if (Char > k.Char)
00066                 return false;
00067         if (Size < k.Size)
00068                 return true;
00069         if (Size > k.Size)
00070                 return false;
00071         if (FontGenerator < k.FontGenerator)
00072                 return true;
00073         if (FontGenerator > k.FontGenerator)
00074                 return false;
00075         return false;
00076 }
00077 
00078 // ---------------------------------------------------------------------------
00079 bool CTextureFont::SLetterKey::operator == (const CTextureFont::SLetterKey&k) const
00080 {
00081         if ((Char == k.Char) && (Size == k.Size) && (FontGenerator == k.FontGenerator))
00082                 return true;
00083         else
00084                 return false;
00085 }
00086 */
00087 // ---------------------------------------------------------------------------
00088 CTextureFont::CTextureFont()
00089 {
00090         uint i;
00091 
00092         setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
00093 
00094         setWrapS (ITexture::Repeat);
00095         setWrapT (ITexture::Repeat);
00096 
00097         setUploadFormat (Alpha);
00098 
00099         setReleasable (false);
00100 
00101         resize (TextureSizeX, TextureSizeY, CBitmap::Alpha);
00102         for(i = 0; i < TextureSizeX*TextureSizeY; ++i)
00103                 getPixels()[i] = 0;
00104         // convertToType (CBitmap::Alpha);
00105 
00106         sint posY = 0;
00107 
00108         for(i = 0; i < TEXTUREFONT_NBCATEGORY; ++i)
00109         {
00110                 // Number of chars per cache
00111                 Letters[i].resize ((TextureSizeX/Categories[i])*NbLine[i]);
00112 
00113                 for(uint32 j = 0; j < Letters[i].size(); ++j)
00114                 {
00115                         SLetterInfo &rLetter = Letters[i][j];
00116                         rLetter.Char = 0xffff;
00117                         rLetter.FontGenerator = NULL;
00118 
00119                         // The less recently used infos
00120                         if (j < Letters[i].size()-1)
00121                                 rLetter.Next = &Letters[i][j+1];
00122                         else
00123                                 rLetter.Next = NULL;
00124 
00125                         if (j > 0)
00126                                 rLetter.Prev = &Letters[i][j-1];
00127                         else
00128                                 rLetter.Prev = NULL;
00129 
00130                         rLetter.Cat = i;
00131 
00132                         sint sizeX = TextureSizeX/Categories[i];
00133                         rLetter.U = (Categories[i]*(j%sizeX)) / ((float)TextureSizeX);
00134                         rLetter.V = (posY + Categories[i]*((sint)(j/sizeX))) / ((float)TextureSizeY);
00135 
00137                         
00138                         rLetter.CharWidth = rLetter.CharHeight = 0;
00139                         rLetter.GlyphIndex = rLetter.Top = rLetter.Left = rLetter.AdvX = 0;
00140                 }
00141                 Front[i] = &Letters[i][0];
00142                 Back[i] = &Letters[i][Letters[i].size()-1];
00143                 posY += NbLine[i] * Categories[i];
00144         }
00145 }
00146 
00147 
00148 CTextureFont::~CTextureFont()
00149 {
00150 }
00151 
00152 
00153 // ---------------------------------------------------------------------------
00154 void CTextureFont::dumpTextureFont(const char *filename)
00155 {
00156         CBitmap b;
00157         COFile f( filename );
00158         b.resize (TextureSizeX, TextureSizeY, CBitmap::RGBA);
00159         vector<uint8>&bits = b.getPixels();
00160         vector<uint8>&src = getPixels();
00161 
00162         for (uint i = 0; i < (TextureSizeX*TextureSizeY); ++i)
00163         {
00164                 bits[i*4+0] = bits[i*4+1] = bits[i*4+2] = bits[i*4+3] = src[i];
00165         }
00166 
00167         b.writeTGA (f, 32);
00168 }
00169 
00170 
00171 // ---------------------------------------------------------------------------
00172 // cat : categories where the letter is
00173 // x : pos x of the letter
00174 // y : pos y of the letter
00175 void CTextureFont::rebuildLetter (sint cat, sint x, sint y)
00176 {
00177         sint sizex = TextureSizeX / Categories[cat];
00178         sint index = x + y*sizex;
00179         SLetterInfo &rLetter = Letters[cat][index];
00180 
00181         if (rLetter.FontGenerator == NULL)
00182                 return;
00183 
00184         sint catTopY = 0;
00185         sint c = 0;
00186         while (c < cat)
00187         {
00188                 catTopY += NbLine[c] * Categories[c];
00189                 ++c;
00190         }
00191         // Destination position in pixel of the letter
00192         sint posx = x * Categories[cat];
00193         sint posy = catTopY + y * Categories[cat];
00194 
00195         uint32 pitch = 0;
00196         uint8 *bitmap = rLetter.FontGenerator->getBitmap (      rLetter.Char, rLetter.Size,
00197                                                                                                                 rLetter.CharWidth, rLetter.CharHeight,
00198                                                                                                                 pitch, rLetter.Left, rLetter.Top, 
00199                                                                                                                 rLetter.AdvX, rLetter.GlyphIndex );
00200 
00201         // Copy FreeType buffer
00202         uint i;
00203         for (i = 0; i < rLetter.CharHeight; ++i)
00204         {
00205                 uint8 *pDst = &_Data[0][posx + (posy+i)*TextureSizeY];
00206                 uint8 *pSrc = &bitmap[i*pitch];
00207                 for (uint j = 0; j < rLetter.CharWidth; ++j)
00208                 {
00209                         *pDst = *pSrc;
00210                         ++pDst;
00211                         ++pSrc;
00212                 }
00213         }
00214 
00215         // Black border bottom and right
00216         for (i = 0; i < rLetter.CharHeight+1; ++i)
00217         {
00218                 _Data[0][posx + rLetter.CharWidth + (posy+i)*TextureSizeY] = 0;
00219         }
00220 
00221         for (i = 0; i < rLetter.CharWidth+1; ++i)
00222         {
00223                 _Data[0][posx + i + (posy+rLetter.CharHeight)*TextureSizeY] = 0;
00224         }
00225 
00226         /*
00227         dumpTextureFont (this);
00228         int a = 5;
00229         a++;
00230         */
00231 }
00232 
00233 // ---------------------------------------------------------------------------
00234 void CTextureFont::doGenerate()
00235 {
00236         // Rectangle invalidate ?
00237         if (_ListInvalidRect.begin()!=_ListInvalidRect.end())
00238         {
00239                 // Yes, rebuild only those rectangles.
00240 
00241                 // For each rectangle to compute
00242                 std::list<NLMISC::CRect>::iterator ite=_ListInvalidRect.begin();
00243                 while (ite!=_ListInvalidRect.end())
00244                 {
00245                         // Compute rectangle coordinates
00246                         sint x = ite->left();
00247                         sint y = ite->bottom();
00248 
00249                         // Look in wich category is the rectangle
00250                         sint cat = 0;
00251                         sint catTopY = 0;
00252                         sint catBotY = NbLine[cat] * Categories[cat];
00253                         while (y >  catBotY)
00254                         {
00255                                 if (y < catBotY)
00256                                         break;
00257                                 ++cat;
00258                                 nlassert (cat < TEXTUREFONT_NBCATEGORY);
00259                                 catTopY = catBotY;
00260                                 catBotY += NbLine[cat] * Categories[cat];
00261                         }
00262 
00263                         x = x / Categories[cat];
00264                         y = ite->top();
00265                         y = y - catTopY;
00266                         y = y / Categories[cat];
00267                         
00268                         rebuildLetter (cat, x, y);
00269 
00270                         // Next rectangle
00271                         ite++;
00272                 }
00273         }
00274         else
00275         {
00276                 for(int cat = 0; cat < TEXTUREFONT_NBCATEGORY; ++cat)
00277                 {
00278                         sint sizex = TextureSizeX / Categories[cat];
00279                         sint sizey = NbLine[cat];
00280                         for (sint y = 0; y < sizey; y++)
00281                         for (sint x = 0; x < sizex; x++)
00282                         {
00283                                 rebuildLetter (cat, x, y);
00284                         }
00285                 }
00286         }
00287 /*
00288         dumpTextureFont (this);
00289         int a = 5;
00290 */
00291 }
00292 
00293 // ---------------------------------------------------------------------------
00294 CTextureFont::SLetterInfo* CTextureFont::getLetterInfo (SLetterKey& k)
00295 {
00296         sint cat;
00297         map<uint32, SLetterInfo*>::iterator itAccel = Accel.find (k.getVal());
00298         if (itAccel != Accel.end())
00299         {
00300                 // Put it in the first place
00301                 SLetterInfo *pLetterToMove = itAccel->second;
00302                 cat = pLetterToMove->Cat;
00303                 if (pLetterToMove != Front[cat])
00304                 {
00305                         pLetterToMove->Prev->Next = pLetterToMove->Next;
00306 
00307                         if (pLetterToMove == Back[cat])
00308                         {
00309                                 Back[cat] = pLetterToMove->Prev;
00310                         }
00311                         else
00312                         {
00313                                 pLetterToMove->Next->Prev = pLetterToMove->Prev;
00314                         }
00315                         pLetterToMove->Prev = NULL;
00316                         pLetterToMove->Next = Front[cat];
00317                         Front[cat]->Prev = pLetterToMove;
00318                         Front[cat] = pLetterToMove;
00319                 }
00320                 return pLetterToMove;
00321         }
00322 
00323         // The letter is not already present
00324         // Found the category of the new letter
00325         uint32 width, height;
00326 
00327         //k.FontGenerator->getSizes (k.Char, k.Size, width, height);
00328         // \todo mat : Temporaire !!! Essayer de faire intervenir le cache de freetype
00329         uint32 nPitch, nGlyphIndex;
00330         sint32 nLeft, nTop, nAdvX;
00331         k.FontGenerator->getBitmap (k.Char, k.Size, width, height, nPitch, nLeft, nTop, 
00332                                                                                                                 nAdvX, nGlyphIndex );
00333 
00334         // Add 1 pixel space for black border to get correct category
00335         cat = 0;
00336         if (((sint)width+1 > Categories[TEXTUREFONT_NBCATEGORY-1]) ||
00337                 ((sint)height+1 > Categories[TEXTUREFONT_NBCATEGORY-1]))
00338                 return NULL;
00339 
00340         while (((sint)width+1 > Categories[cat]) || ((sint)height+1 > Categories[cat]))
00341         {
00342                 ++cat;
00343                 nlassert (cat != TEXTUREFONT_NBCATEGORY);
00344         }
00345 
00346         // And replace the less recently used letter
00347         SLetterKey k2;
00348         k2.Char = Back[cat]->Char;
00349         k2.FontGenerator = Back[cat]->FontGenerator;
00350         k2.Size = Back[cat]->Size;
00351 
00352         itAccel = Accel.find (k2.getVal());
00353         if (itAccel != Accel.end())
00354         {
00355                 Accel.erase (itAccel);
00356         }
00357 
00358         SLetterInfo *NewBack = Back[cat]->Prev;
00359         NewBack->Next = NULL;
00360         Back[cat]->Cat = cat;
00361         Back[cat]->Char = k.Char;
00362         Back[cat]->FontGenerator = k.FontGenerator;
00363         Back[cat]->Size = k.Size;
00364         Back[cat]->CharWidth = width;
00365         Back[cat]->CharHeight = height;
00366         Back[cat]->Top = nTop;
00367         Back[cat]->Left = nLeft;
00368         Back[cat]->AdvX = nAdvX;
00369         Back[cat]->Prev = NULL;
00370         Back[cat]->Next = Front[cat];
00371         Front[cat]->Prev = Back[cat];
00372         Front[cat] = Back[cat];
00373         Back[cat] = NewBack;
00374 
00375         Accel.insert (map<uint32, SLetterInfo*>::value_type(k.getVal(),Front[cat]));
00376 
00377         // Invalidate the zone
00378         sint index = (Front[cat] - &Letters[cat][0]);// / sizeof (SLetterInfo);
00379         sint sizex = TextureSizeX / Categories[cat];
00380         sint x = index % sizex;
00381         sint y = index / sizex;
00382         x = x * Categories[cat];
00383         y = y * Categories[cat];
00384 
00385         sint c = 0;
00386         while (c < cat)
00387         {
00388                 y = y + NbLine[c] * Categories[c];
00389                 ++c;
00390         }
00391 
00392         // must update the char, WITH the black borders
00393         CRect r (x, y, width+1, height+1);
00394 
00395         touchRect (r);
00396 
00397         return Front[cat];
00398 }
00399 
00400 } // NL3D