font_generator.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 
00028 #include <string>
00029 
00030 #include "nel/misc/types_nl.h"
00031 #include "nel/misc/debug.h"
00032 #include "nel/misc/common.h"
00033 #include "nel/misc/path.h"
00034 
00035 #include "3d/font_generator.h"
00036 
00037 using namespace std;
00038 
00039 #ifndef NL_DONT_USE_EXTERNAL_CODE
00040 
00041 #include <freetype/freetype.h>
00042 
00043 // for freetype 2.0
00044 #ifdef FTERRORS_H
00045 #undef FTERRORS_H
00046 #endif
00047 
00048 // for freetype 2.0.1
00049 #ifdef __FTERRORS_H__
00050 #undef __FTERRORS_H__
00051 #endif
00052 
00053 #define FT_ERRORDEF( e, v, s )  { e, s },
00054 #define FT_ERROR_START_LIST  {
00055 #define FT_ERROR_END_LIST    { 0, 0 } };
00056 
00057 const struct
00058 {
00059 int          err_code;
00060 const char*  err_msg;
00061 } ft_errors[] = 
00062 
00063 #include <freetype/fterrors.h>
00064 
00065 using namespace NLMISC;
00066 
00067 namespace NL3D {
00068 
00069 FT_Library      CFontGenerator::_Library;
00070 bool            CFontGenerator::_LibraryInit = false;
00071 uint32          CFontGenerator::_FontGeneratorCounterUID = 1;
00072 
00073 const char *CFontGenerator::getFT2Error(FT_Error fte)
00074 {
00075         NL_ALLOC_CONTEXT (FreeTyp);
00076 
00077         static char ukn[1024];
00078 
00079         for (uint32 i = 0; ft_errors[i].err_code != 0 || ft_errors[i].err_msg != 0; i++)
00080         {
00081                 if (ft_errors[i].err_code == fte)
00082                         return ft_errors[i].err_msg;
00083         }
00084         smprintf (ukn, 1024, "Unknown freetype2 error, errcode: 0x%x", fte);
00085         return ukn;
00086 }
00087 
00088 
00089  
00090 /*
00091  * Constructor
00092  */
00093 CFontGenerator::CFontGenerator (const std::string &fontFileName, const std::string &fontExFileName)
00094 {
00095         NL_ALLOC_CONTEXT (FreeTyp);
00096 
00097         _UID = _FontGeneratorCounterUID;
00098         _FontGeneratorCounterUID++;
00099         _FontFileName = fontFileName;
00100 
00101         FT_Error error;
00102 
00103         if (!_LibraryInit)
00104         {
00105                 error = FT_Init_FreeType (&_Library);
00106                 if (error)
00107                 {
00108                         nlerror ("FT_Init_FreeType() failed: %s", getFT2Error(error));
00109                 }
00110                 _LibraryInit = true;
00111         }
00112 
00113         error = FT_New_Face (_Library, fontFileName.c_str (), 0, &_Face);
00114         if (error)
00115         {
00116                 nlerror ("FT_New_Face() failed with file '%s': %s", fontFileName.c_str(), getFT2Error(error));
00117         }
00118 
00119         string fontEx = fontExFileName;
00120         if (fontEx == "")
00121         {
00122                 // try to see if the ex filename exists based on the fontExFileName
00123                 fontEx = CPath::lookup(CFile::getFilenameWithoutExtension (fontFileName)+".afm", false, false);
00124         }
00125 
00126         if (fontEx != "")
00127         {
00128                 error = FT_Attach_File (_Face, fontEx.c_str ());
00129                 if (error)
00130                 {
00131                         nlwarning ("FT_Attach_File() failed with file '%s': %s", fontEx.c_str(), getFT2Error(error));
00132                 }
00133         }
00134 
00135         error = FT_Select_Charmap (_Face, ft_encoding_unicode);
00136         if (error)
00137         {
00138                 nlerror ("FT_Select_Charmap() failed with file '%s': %s", fontFileName.c_str(), getFT2Error(error));
00139         }
00140 }
00141 
00142 CFontGenerator::~CFontGenerator ()
00143 {
00144 }
00145 
00146 void CFontGenerator::getSizes (ucchar c, uint32 size, uint32 &width, uint32 &height)
00147 {
00148         NL_ALLOC_CONTEXT (FreeTyp);
00149 
00150         FT_Error error;
00151 
00152         error = FT_Set_Pixel_Sizes (_Face, size, size);
00153         if (error)
00154         {
00155                 nlerror ("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error));
00156         }
00157 
00158         // retrieve glyph index from character code
00159         FT_UInt glyph_index = FT_Get_Char_Index (_Face, c);
00160 
00161         // load glyph image into the slot (erase previous one)
00162         error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT);
00163         if (error)
00164         {
00165                 nlerror ("FT_Load_Glyph() failed: %s", getFT2Error(error));
00166         }
00167 
00168         // convert 24.6 fixed point into integer
00169         width = _Face->glyph->metrics.width >> 6;
00170         height = _Face->glyph->metrics.height >> 6;
00171 }
00172 
00173 uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex)
00174 {
00175         NL_ALLOC_CONTEXT (FreeTyp);
00176 
00177         FT_Error error;
00178 
00179         error = FT_Set_Pixel_Sizes (_Face, size, size);
00180         if (error)
00181         {
00182                 nlerror ("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error));
00183         }
00184 
00185         // retrieve glyph index from character code
00186         FT_UInt glyph_index = FT_Get_Char_Index (_Face, c);
00187 
00188         // load glyph image into the slot (erase previous one)
00189         error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT);
00190         if (error)
00191         {
00192                 nlerror ("FT_Load_Glyph() failed: %s", getFT2Error(error));
00193         }
00194 
00195         if (size == 0)
00196         {
00197                 width = 0;
00198                 height = 0;
00199                 pitch = 0;
00200                 left = 0;
00201                 top = 0;
00202                 advx = 0;
00203                 glyphIndex = glyph_index;
00204                 return NULL;
00205         }
00206 
00207         // convert to an anti-aliased bitmap
00208         error = FT_Render_Glyph (_Face->glyph, ft_render_mode_normal);
00209         if (error)
00210         {
00211                 nlerror ("FT_Render_Glyph() failed: %s", getFT2Error(error));
00212         }
00213 
00214         width = _Face->glyph->bitmap.width;
00215         height = _Face->glyph->bitmap.rows;
00216         pitch = _Face->glyph->bitmap.pitch;
00217 
00218         left = _Face->glyph->bitmap_left;
00219         top = _Face->glyph->bitmap_top;
00220 
00221         advx = _Face->glyph->advance.x >> 6;
00222 
00223         glyphIndex = glyph_index;
00224 
00225         return (uint8 *) _Face->glyph->bitmap.buffer;
00226 }
00227 
00228 
00229 
00230 void CFontGenerator::getKerning (ucchar left, ucchar right, sint32 &kernx)
00231 {
00232         NL_ALLOC_CONTEXT (FreeTyp);
00233 
00234         if (!FT_HAS_KERNING(_Face))
00235         {
00236                 kernx = 0;
00237         }
00238         else
00239         {
00240                 FT_Vector  kerning;
00241                 FT_Error error = FT_Get_Kerning (_Face, left, right, ft_kerning_default, &kerning);
00242                 if (error)
00243                 {
00244                         nlerror ("FT_Get_Kerning() failed: %s", getFT2Error(error));
00245                 }
00246                 kernx = kerning.x;
00247         }
00248 }
00249 
00250 
00251 
00252 uint32   CFontGenerator::getCharIndex (ucchar c)
00253 {
00254         NL_ALLOC_CONTEXT (FreeTyp);
00255 
00256         return FT_Get_Char_Index (_Face, c);
00257 }
00258 
00259 } // NL3D
00260 
00261 #else // NL_DONT_USE_EXTERNAL_CODE
00262 
00263 #include <windows.h>
00264 
00265 using namespace NLMISC;
00266 
00267 namespace NL3D {
00268  
00269 HBITMAP Dib;
00270 uint32 *Buffer;
00271 HDC hdcDib;
00272 int Width = 100;
00273 int Height = 100;
00274 
00275 /*
00276  * Constructor
00277  */
00278 CFontGenerator::CFontGenerator (const std::string &fontFileName, const std::string &fontExFileName)
00279 {
00280 
00281 //      HWND win=(HWND)winHack;
00282 //      WindowHandle = win;
00283 //      Format = format;
00284 //      RECT rect;
00285 //      BOOL ret = GetClientRect( WindowHandle, &rect);
00286 //      assert (ret);
00287 
00288 //      uint f = AddFontResource ("");
00289 //      nlassert (f);
00290 
00291         BITMAPINFO info;
00292         info.bmiHeader.biWidth = Width;
00293         info.bmiHeader.biHeight= -Height;
00294         info.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
00295         info.bmiHeader.biPlanes = 1; 
00296         info.bmiHeader.biBitCount = 32;
00297         info.bmiHeader.biCompression = BI_RGB;
00298         info.bmiHeader.biSizeImage = 4*Width*Height;
00299         info.bmiHeader.biXPelsPerMeter = 1;
00300         info.bmiHeader.biYPelsPerMeter = 1;
00301         info.bmiHeader.biClrUsed = 0;
00302         info.bmiHeader.biClrImportant = 0;
00303 
00304         HDC hdc = GetDC (NULL);
00305         nlassert (hdc);
00306         Dib = CreateDIBSection (hdc, &info, DIB_RGB_COLORS, (void**)&Buffer, NULL, NULL);
00307 
00308         hdcDib = CreateCompatibleDC (hdc);
00309         nlassert (hdcDib);
00310 
00311 
00312         ReleaseDC (NULL, hdc);
00313 
00314         SetTextAlign (hdcDib, TA_TOP | TA_LEFT | TA_NOUPDATECP);
00315         SetBkColor (hdcDib, RGB (0,0,0));
00316         SetTextColor (hdcDib, RGB (255, 255, 255));
00317         
00318         /*FT_Error error;
00319 
00320         if (!_LibraryInit)
00321         {
00322                 error = FT_Init_FreeType (&_Library);
00323                 if (error)
00324                 {
00325                         nlerror ("FT_Init_FreeType() failed: %s", getFT2Error(error));
00326                 }
00327                 _LibraryInit = true;
00328         }
00329 
00330         error = FT_New_Face (_Library, fontFileName.c_str (), 0, &_Face);
00331         if (error)
00332         {
00333                 nlerror ("FT_New_Face() failed with file '%s': %s", fontFileName.c_str(), getFT2Error(error));
00334         }
00335 
00336         if (fontExFileName != "")
00337         {
00338                 error = FT_Attach_File (_Face, fontExFileName.c_str ());
00339                 if (error)
00340                 {
00341                         nlwarning ("FT_Attach_File() failed with file '%s': %s", fontExFileName.c_str(), getFT2Error(error));
00342                 }
00343         }*/
00344 }
00345 
00346 CFontGenerator::~CFontGenerator ()
00347 {
00348         DeleteObject (Dib);
00349 
00350         DeleteDC (hdcDib);
00351 }
00352 
00353 void CFontGenerator::getSizes (ucchar c, uint32 size, uint32 &width, uint32 &height)
00354 {
00355 /*      FT_Error error;
00356 
00357         error = FT_Set_Pixel_Sizes (_Face, size, size);
00358         if (error)
00359         {
00360                 nlerror ("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error));
00361         }
00362 
00363         // retrieve glyph index from character code
00364         FT_UInt glyph_index = FT_Get_Char_Index (_Face, c);
00365 
00366         // load glyph image into the slot (erase previous one)
00367         error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT);
00368         if (error)
00369         {
00370                 nlerror ("FT_Load_Glyph() failed: %s", getFT2Error(error));
00371         }
00372 
00373         // convert 24.6 fixed point into integer
00374         width = _Face->glyph->metrics.width >> 6;
00375         height = _Face->glyph->metrics.height >> 6;
00376         */
00377 }
00378 
00379 HFONT hFont = NULL;
00380 uint32 CurrentFontSize = 0;
00381 
00382 uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex)
00383 {
00384 /*      FT_Error error;
00385 
00386         error = FT_Set_Pixel_Sizes (_Face, size, size);
00387         if (error)
00388         {
00389                 nlerror ("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error));
00390         }
00391 
00392         // retrieve glyph index from character code
00393         FT_UInt glyph_index = FT_Get_Char_Index (_Face, c);
00394 
00395         // load glyph image into the slot (erase previous one)
00396         error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT);
00397         if (error)
00398         {
00399                 nlerror ("FT_Load_Glyph() failed: %s", getFT2Error(error));
00400         }
00401 
00402         if (size == 0)
00403         {
00404                 width = 0;
00405                 height = 0;
00406                 pitch = 0;
00407                 left = 0;
00408                 top = 0;
00409                 advx = 0;
00410                 glyphIndex = glyph_index;
00411                 return NULL;
00412         }
00413 
00414         // convert to an anti-aliased bitmap
00415         error = FT_Render_Glyph (_Face->glyph, ft_render_mode_normal);
00416         if (error)
00417         {
00418                 nlerror ("FT_Render_Glyph() failed: %s", getFT2Error(error));
00419         }
00420 
00421         width = _Face->glyph->bitmap.width;
00422         height = _Face->glyph->bitmap.rows;
00423         pitch = _Face->glyph->bitmap.pitch;
00424 
00425         left = _Face->glyph->bitmap_left;
00426         top = _Face->glyph->bitmap_top;
00427 
00428         advx = _Face->glyph->advance.x >> 6;
00429 
00430         glyphIndex = glyph_index;
00431 
00432         return (uint8 *) _Face->glyph->bitmap.buffer;
00433 */
00434 
00435         if (size == 0)
00436         {
00437                 width = 0;
00438                 height = 0;
00439                 pitch = 0;
00440                 left = 0;
00441                 top = 0;
00442                 advx = 0;
00443                 glyphIndex = 0;
00444                 return NULL;
00445         }
00446 
00447         // Create the font
00448         if (hFont ==  NULL || CurrentFontSize != size)
00449         {
00450                 if (hFont !=  NULL)
00451                 {
00452                         DeleteObject (hFont);
00453                 }
00454 
00455                 hFont=CreateFont
00456                 (
00457                         size,                                   // logical height of font
00458                         0,                                      // logical average character width
00459                         0,                                      // angle of escapement
00460                         0,                                      // base-line orientation angle
00461                         FW_DONTCARE, //FW_NORMAL,                       // font weight
00462                         FALSE,                          // italic attribute flag
00463                         FALSE,                          // underline attribute flag
00464                         FALSE,                          // strikeout attribute flag
00465                         DEFAULT_CHARSET,        // character set identifier
00466                         OUT_DEVICE_PRECIS,  // output precision
00467                         CLIP_DEFAULT_PRECIS,    // clipping precision
00468                         DEFAULT_QUALITY,        // output quality
00469                         DEFAULT_PITCH|FF_DONTCARE,  // pitch and family
00470                         "Arial Unicode MS Normal"         // pointer to typeface name string
00471                 );
00472                 nlassert (hFont);
00473 
00474                 CurrentFontSize = size;
00475         }
00476 
00477         SelectObject (hdcDib, hFont);
00478         SelectObject (hdcDib, Dib);
00479         
00480         const char cc = (char) c;
00481 
00482         RECT rect;
00483         rect.bottom = Height;
00484         rect.top = 0;
00485         rect.left = 0;
00486         rect.right = Width;
00487 
00488         int res = DrawText (hdcDib, &cc, 1, &rect, DT_LEFT | DT_TOP);
00489 
00490         POINT point;
00491         point.y = res;
00492 
00493         int w = res;
00494         BOOL rey = GetCharWidth32 (hdcDib, (uint8) cc,  (uint8) cc, &w);
00495         nlassert (rey);
00496         point.x = w;
00497 
00498 //      ABC abc;
00499 //      BOOL rey = GetCharABCWidths (hdcDib, (uint8) cc, (uint8) cc, &abc);
00500 //      nlassert (rey);
00501 //      point.x = abc.abcA;
00502 
00503         SIZE s;
00504         GetTextExtentPoint32 (hdcDib, &cc, 1, &s);
00505         
00506         BOOL ret = LPtoDP (hdcDib, &point, 1);
00507         nlassert (ret);
00508 
00509         static uint8 buf[100*100];
00510 
00511         sint32 _top = 0, _left = point.x;
00512         sint32 right = 0, bottom = point.y;
00513         bool emptyLine;
00514         for (sint y = 0; y < point.y; y++)
00515         {
00516                 emptyLine = true;
00517                 for (sint x = 0; x < point.x; x++)
00518                 {
00519                         buf[y*100+x] = (uint8) Buffer[y*100+x];
00520                         if (buf[y*100+x])
00521                         {
00522                                 emptyLine = false;
00523                                 if (x < _left)
00524                                         _left = x;
00525                                 if (x > right)
00526                                         right = x;
00527                         }
00528 
00529 //                      printf (buf[y*100+x]?"*":".");
00530                 }
00531                 if (!emptyLine)
00532                 {
00533                         if (_top == 0)
00534                                 _top = y;
00535 
00536                         bottom = y;
00537                 }
00538 
00539 //              printf ("\n");
00540         }
00541         width = right - _left + 1;
00542         if (right - _left + 1 < 0) width = 0;
00543         height = bottom - _top + 1;
00544         if (bottom - _top + 1 < 0) height = 0;
00545         pitch = 100;
00546         advx = point.x;
00547         
00548         WORD ag = 0;
00549         /*uint t = GetGlyphIndices (hdcDib, &cc, 1, &ag, 0);
00550         if (t == GDI_ERROR)
00551         {
00552                 nlstop;
00553         }
00554 */
00555         glyphIndex = ag;
00556 
00557         top = -_top;
00558         left = -_left;
00559 
00560 /*      {
00561                 for (sint y = _top; y < _top + height; y++)
00562                 {
00563                         for (sint x = _left; x < _left + width; x++)
00564                         {
00565                                 printf (buf[y*100+x]?"*":".");
00566                         }
00567                         printf ("\n");
00568                 }
00569                 printf ("w: %d h: %d s: %d a: %d l: %d t: %d", width, height, size, advx, left, top);
00570                 getchar();
00571         }
00572 */
00573         _top = _left = top = left = 0;
00574         top = s.cy;
00575         width = s.cx;
00576         height = s.cy;
00577 
00578         return buf + _top * 100 + _left;
00579 }
00580 
00581 
00582 
00583 
00584 void CFontGenerator::getKerning (ucchar left, ucchar right, sint32 &kernx)
00585 {
00586 /*      if (!FT_HAS_KERNING(_Face))
00587         {
00588                 kernx = 0;
00589         }
00590         else
00591         {
00592                 FT_Vector  kerning;
00593                 FT_Error error = FT_Get_Kerning (_Face, left, right, ft_kerning_default, &kerning);
00594                 if (error)
00595                 {
00596                         nlerror ("FT_Get_Kerning() failed: %s", getFT2Error(error));
00597                 }
00598                 kernx = kerning.x;
00599         }*/
00600 }
00601 
00602 
00603 
00604 uint32   CFontGenerator::getCharIndex (ucchar c)
00605 {
00606 //      return FT_Get_Char_Index (_Face, c);
00607         return 0;
00608 }
00609 
00610 
00611 } // NL3D
00612 
00613 #endif // NL_DONT_USE_EXTERNAL_CODE
00614 

Generated on Tue Mar 16 06:25:03 2004 for NeL by doxygen 1.3.6