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
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
00044 #ifdef FTERRORS_H
00045 #undef FTERRORS_H
00046 #endif
00047
00048
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
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
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
00159 FT_UInt glyph_index = FT_Get_Char_Index (_Face, c);
00160
00161
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
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
00186 FT_UInt glyph_index = FT_Get_Char_Index (_Face, c);
00187
00188
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
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 }
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
00277
00278 CFontGenerator::CFontGenerator (const std::string &fontFileName, const std::string &fontExFileName)
00279 {
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
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
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
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
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
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
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
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
00448 if (hFont == NULL || CurrentFontSize != size)
00449 {
00450 if (hFont != NULL)
00451 {
00452 DeleteObject (hFont);
00453 }
00454
00455 hFont=CreateFont
00456 (
00457 size,
00458 0,
00459 0,
00460 0,
00461 FW_DONTCARE,
00462 FALSE,
00463 FALSE,
00464 FALSE,
00465 DEFAULT_CHARSET,
00466 OUT_DEVICE_PRECIS,
00467 CLIP_DEFAULT_PRECIS,
00468 DEFAULT_QUALITY,
00469 DEFAULT_PITCH|FF_DONTCARE,
00470 "Arial Unicode MS Normal"
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
00499
00500
00501
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
00530 }
00531 if (!emptyLine)
00532 {
00533 if (_top == 0)
00534 _top = y;
00535
00536 bottom = y;
00537 }
00538
00539
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
00550
00551
00552
00553
00554
00555 glyphIndex = ag;
00556
00557 top = -_top;
00558 left = -_left;
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
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
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 }
00601
00602
00603
00604 uint32 CFontGenerator::getCharIndex (ucchar c)
00605 {
00606
00607 return 0;
00608 }
00609
00610
00611 }
00612
00613 #endif // NL_DONT_USE_EXTERNAL_CODE
00614