00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00044 const int TextureSizeX = 1024;
00045 const int TextureSizeY = 1024;
00046 const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32, 64 };
00047 const int NbLine[TEXTUREFONT_NBCATEGORY] = { 8, 24, 16, 4, 1 };
00048
00049
00050
00051
00052
00053
00054
00055
00056 inline uint32 CTextureFont::SLetterKey::getVal()
00057 {
00058 return Char + ((Size&255)<<16) + ((((uint32)FontGenerator)&255)<<24);
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
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
00105
00106 sint posY = 0;
00107
00108 for(i = 0; i < TEXTUREFONT_NBCATEGORY; ++i)
00109 {
00110
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
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
00173
00174
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
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
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
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
00228
00229
00230
00231 }
00232
00233
00234 void CTextureFont::doGenerate()
00235 {
00236
00237 if (_ListInvalidRect.begin()!=_ListInvalidRect.end())
00238 {
00239
00240
00241
00242 std::list<NLMISC::CRect>::iterator ite=_ListInvalidRect.begin();
00243 while (ite!=_ListInvalidRect.end())
00244 {
00245
00246 sint x = ite->left();
00247 sint y = ite->bottom();
00248
00249
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
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
00289
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
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
00324
00325 uint32 width, height;
00326
00327
00328
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
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
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
00378 sint index = (Front[cat] - &Letters[cat][0]);
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
00393 CRect r (x, y, width+1, height+1);
00394
00395 touchRect (r);
00396
00397 return Front[cat];
00398 }
00399
00400 }