# 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  

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