font_manager.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. /*
  2. * Copyright 2013 Jeremie Roy. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #define USE_EDTAA3 0
  6. #include <bx/macros.h>
  7. #if BX_COMPILER_MSVC
  8. # define generic GenericFromFreeType // WinRT language extensions see "generic" as a keyword... this is stupid
  9. #endif // BX_COMPILER_MSVC
  10. BX_PRAGMA_DIAGNOSTIC_PUSH();
  11. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4245) // error C4245: '=' : conversion from 'int' to 'FT_UInt', signed/unsigned mismatch
  12. #if BX_COMPILER_MSVC || BX_COMPILER_GCC >= 40300
  13. #pragma push_macro("interface")
  14. #endif
  15. #undef interface
  16. #include <freetype/freetype.h>
  17. #if BX_COMPILER_MSVC || BX_COMPILER_GCC >= 40300
  18. #pragma pop_macro("interface")
  19. #endif
  20. BX_PRAGMA_DIAGNOSTIC_POP();
  21. #include "../common.h"
  22. #include <bgfx/bgfx.h>
  23. #if USE_EDTAA3
  24. # include <edtaa3/edtaa3func.cpp>
  25. #else
  26. # define SDF_IMPLEMENTATION
  27. # include <sdf/sdf.h>
  28. #endif // USE_EDTAA3
  29. #include <wchar.h> // wcslen
  30. #include <tinystl/allocator.h>
  31. #include <tinystl/unordered_map.h>
  32. namespace stl = tinystl;
  33. #include "font_manager.h"
  34. #include "../cube_atlas.h"
  35. struct FTHolder
  36. {
  37. FT_Library library;
  38. FT_Face face;
  39. };
  40. class TrueTypeFont
  41. {
  42. public:
  43. TrueTypeFont();
  44. ~TrueTypeFont();
  45. /// Initialize from an external buffer
  46. /// @remark The ownership of the buffer is external, and you must ensure it stays valid up to this object lifetime
  47. /// @return true if the initialization succeed
  48. bool init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight);
  49. /// return the font descriptor of the current font
  50. FontInfo getFontInfo();
  51. /// raster a glyph as 8bit alpha to a memory buffer
  52. /// update the GlyphInfo according to the raster strategy
  53. /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(char)
  54. bool bakeGlyphAlpha(CodePoint _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
  55. /// raster a glyph as 32bit subpixel rgba to a memory buffer
  56. /// update the GlyphInfo according to the raster strategy
  57. /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(uint32_t)
  58. bool bakeGlyphSubpixel(CodePoint _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
  59. /// raster a glyph as 8bit signed distance to a memory buffer
  60. /// update the GlyphInfo according to the raster strategy
  61. /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(char)
  62. bool bakeGlyphDistance(CodePoint _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
  63. private:
  64. FTHolder* m_font;
  65. };
  66. TrueTypeFont::TrueTypeFont() : m_font(NULL)
  67. {
  68. }
  69. TrueTypeFont::~TrueTypeFont()
  70. {
  71. if (NULL != m_font)
  72. {
  73. FT_Done_Face(m_font->face);
  74. FT_Done_FreeType(m_font->library);
  75. delete m_font;
  76. m_font = NULL;
  77. }
  78. }
  79. bool TrueTypeFont::init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight)
  80. {
  81. BX_CHECK(m_font == NULL, "TrueTypeFont already initialized");
  82. BX_CHECK( (_bufferSize > 256 && _bufferSize < 100000000), "TrueType buffer size is suspicious");
  83. BX_CHECK( (_pixelHeight > 4 && _pixelHeight < 128), "TrueType buffer size is suspicious");
  84. FTHolder* holder = new FTHolder;
  85. FT_Error error = FT_Init_FreeType(&holder->library);
  86. BX_WARN(!error, "FT_Init_FreeType failed.");
  87. if (error)
  88. {
  89. goto err0;
  90. }
  91. error = FT_New_Memory_Face(holder->library, _buffer, _bufferSize, _fontIndex, &holder->face);
  92. BX_WARN(!error, "FT_Init_FreeType failed.");
  93. if (error)
  94. {
  95. if (FT_Err_Unknown_File_Format == error)
  96. {
  97. goto err0;
  98. }
  99. goto err1;
  100. }
  101. error = FT_Select_Charmap(holder->face, FT_ENCODING_UNICODE);
  102. BX_WARN(!error, "FT_Init_FreeType failed.");
  103. if (error)
  104. {
  105. goto err2;
  106. }
  107. error = FT_Set_Pixel_Sizes(holder->face, 0, _pixelHeight);
  108. BX_WARN(!error, "FT_Init_FreeType failed.");
  109. if (error)
  110. {
  111. goto err2;
  112. }
  113. m_font = holder;
  114. return true;
  115. err2:
  116. FT_Done_Face(holder->face);
  117. err1:
  118. FT_Done_FreeType(holder->library);
  119. err0:
  120. delete holder;
  121. return false;
  122. }
  123. FontInfo TrueTypeFont::getFontInfo()
  124. {
  125. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
  126. BX_CHECK(FT_IS_SCALABLE(m_font->face), "Font is unscalable");
  127. FT_Size_Metrics metrics = m_font->face->size->metrics;
  128. FontInfo outFontInfo;
  129. outFontInfo.scale = 1.0f;
  130. outFontInfo.ascender = metrics.ascender / 64.0f;
  131. outFontInfo.descender = metrics.descender / 64.0f;
  132. outFontInfo.lineGap = (metrics.height - metrics.ascender + metrics.descender) / 64.0f;
  133. outFontInfo.maxAdvanceWidth = metrics.max_advance/ 64.0f;
  134. outFontInfo.underlinePosition = FT_MulFix(m_font->face->underline_position, metrics.y_scale) / 64.0f;
  135. outFontInfo.underlineThickness = FT_MulFix(m_font->face->underline_thickness, metrics.y_scale) / 64.0f;
  136. return outFontInfo;
  137. }
  138. static void glyphInfoInit(GlyphInfo& _glyphInfo, FT_BitmapGlyph _bitmap, FT_GlyphSlot _slot, uint8_t* _dst, uint32_t _bpp)
  139. {
  140. int32_t xx = _bitmap->left;
  141. int32_t yy = -_bitmap->top;
  142. int32_t ww = _bitmap->bitmap.width;
  143. int32_t hh = _bitmap->bitmap.rows;
  144. _glyphInfo.offset_x = (float)xx;
  145. _glyphInfo.offset_y = (float)yy;
  146. _glyphInfo.width = (float)ww;
  147. _glyphInfo.height = (float)hh;
  148. _glyphInfo.advance_x = (float)_slot->advance.x / 64.0f;
  149. _glyphInfo.advance_y = (float)_slot->advance.y / 64.0f;
  150. uint32_t dstPitch = ww * _bpp;
  151. uint8_t* src = _bitmap->bitmap.buffer;
  152. uint32_t srcPitch = _bitmap->bitmap.pitch;
  153. for (int32_t ii = 0; ii < hh; ++ii)
  154. {
  155. bx::memCopy(_dst, src, dstPitch);
  156. _dst += dstPitch;
  157. src += srcPitch;
  158. }
  159. }
  160. bool TrueTypeFont::bakeGlyphAlpha(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
  161. {
  162. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
  163. _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint);
  164. FT_GlyphSlot slot = m_font->face->glyph;
  165. FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, FT_LOAD_DEFAULT);
  166. if (error)
  167. {
  168. return false;
  169. }
  170. FT_Glyph glyph;
  171. error = FT_Get_Glyph(slot, &glyph);
  172. if (error)
  173. {
  174. return false;
  175. }
  176. error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
  177. if (error)
  178. {
  179. return false;
  180. }
  181. FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
  182. glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 1);
  183. FT_Done_Glyph(glyph);
  184. return true;
  185. }
  186. bool TrueTypeFont::bakeGlyphSubpixel(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
  187. {
  188. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
  189. _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint);
  190. FT_GlyphSlot slot = m_font->face->glyph;
  191. FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, FT_LOAD_DEFAULT);
  192. if (error)
  193. {
  194. return false;
  195. }
  196. FT_Glyph glyph;
  197. error = FT_Get_Glyph(slot, &glyph);
  198. if (error)
  199. {
  200. return false;
  201. }
  202. error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_LCD, 0, 1);
  203. if (error)
  204. {
  205. return false;
  206. }
  207. FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
  208. glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 3);
  209. FT_Done_Glyph(glyph);
  210. return true;
  211. }
  212. static void makeDistanceMap(const uint8_t* _img, uint8_t* _outImg, uint32_t _width, uint32_t _height)
  213. {
  214. #if USE_EDTAA3
  215. int16_t* xdist = (int16_t*)malloc(_width * _height * sizeof(int16_t) );
  216. int16_t* ydist = (int16_t*)malloc(_width * _height * sizeof(int16_t) );
  217. double* gx = (double*)calloc(_width * _height, sizeof(double) );
  218. double* gy = (double*)calloc(_width * _height, sizeof(double) );
  219. double* data = (double*)calloc(_width * _height, sizeof(double) );
  220. double* outside = (double*)calloc(_width * _height, sizeof(double) );
  221. double* inside = (double*)calloc(_width * _height, sizeof(double) );
  222. uint32_t ii;
  223. // Convert img into double (data)
  224. double img_min = 255, img_max = -255;
  225. for (ii = 0; ii < _width * _height; ++ii)
  226. {
  227. double v = _img[ii];
  228. data[ii] = v;
  229. if (v > img_max)
  230. {
  231. img_max = v;
  232. }
  233. if (v < img_min)
  234. {
  235. img_min = v;
  236. }
  237. }
  238. // Rescale image levels between 0 and 1
  239. for (ii = 0; ii < _width * _height; ++ii)
  240. {
  241. data[ii] = (_img[ii] - img_min) / (img_max - img_min);
  242. }
  243. // Compute outside = edtaa3(bitmap); % Transform background (0's)
  244. computegradient(data, _width, _height, gx, gy);
  245. edtaa3(data, gx, gy, _width, _height, xdist, ydist, outside);
  246. for (ii = 0; ii < _width * _height; ++ii)
  247. {
  248. if (outside[ii] < 0)
  249. {
  250. outside[ii] = 0.0;
  251. }
  252. }
  253. // Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
  254. bx::memSet(gx, 0, sizeof(double) * _width * _height);
  255. bx::memSet(gy, 0, sizeof(double) * _width * _height);
  256. for (ii = 0; ii < _width * _height; ++ii)
  257. {
  258. data[ii] = 1.0 - data[ii];
  259. }
  260. computegradient(data, _width, _height, gx, gy);
  261. edtaa3(data, gx, gy, _width, _height, xdist, ydist, inside);
  262. for (ii = 0; ii < _width * _height; ++ii)
  263. {
  264. if (inside[ii] < 0)
  265. {
  266. inside[ii] = 0.0;
  267. }
  268. }
  269. // distmap = outside - inside; % Bipolar distance field
  270. uint8_t* out = _outImg;
  271. for (ii = 0; ii < _width * _height; ++ii)
  272. {
  273. outside[ii] -= inside[ii];
  274. outside[ii] = 128 + outside[ii] * 16;
  275. if (outside[ii] < 0)
  276. {
  277. outside[ii] = 0;
  278. }
  279. if (outside[ii] > 255)
  280. {
  281. outside[ii] = 255;
  282. }
  283. out[ii] = 255 - (uint8_t) outside[ii];
  284. }
  285. free(xdist);
  286. free(ydist);
  287. free(gx);
  288. free(gy);
  289. free(data);
  290. free(outside);
  291. free(inside);
  292. #else
  293. sdfBuild(_outImg, _width, 8.0f, _img, _width, _height, _width);
  294. #endif // USE_EDTAA3
  295. }
  296. bool TrueTypeFont::bakeGlyphDistance(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
  297. {
  298. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
  299. _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint);
  300. FT_Int32 loadMode = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
  301. FT_Render_Mode renderMode = FT_RENDER_MODE_NORMAL;
  302. FT_GlyphSlot slot = m_font->face->glyph;
  303. FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, loadMode);
  304. if (error)
  305. {
  306. return false;
  307. }
  308. FT_Glyph glyph;
  309. error = FT_Get_Glyph(slot, &glyph);
  310. if (error)
  311. {
  312. return false;
  313. }
  314. error = FT_Glyph_To_Bitmap(&glyph, renderMode, 0, 1);
  315. if (error)
  316. {
  317. return false;
  318. }
  319. FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
  320. int32_t ww = bitmap->bitmap.width;
  321. int32_t hh = bitmap->bitmap.rows;
  322. glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 1);
  323. FT_Done_Glyph(glyph);
  324. if (ww * hh > 0)
  325. {
  326. uint32_t dw = 6;
  327. uint32_t dh = 6;
  328. uint32_t nw = ww + dw * 2;
  329. uint32_t nh = hh + dh * 2;
  330. BX_CHECK(nw * nh < 128 * 128, "Buffer overflow (size %d)", nw * nh);
  331. uint32_t buffSize = nw * nh * sizeof(uint8_t);
  332. uint8_t* alphaImg = (uint8_t*)malloc(buffSize);
  333. bx::memSet(alphaImg, 0, nw * nh * sizeof(uint8_t) );
  334. //copy the original buffer to the temp one
  335. for (uint32_t ii = dh; ii < nh - dh; ++ii)
  336. {
  337. bx::memCopy(alphaImg + ii * nw + dw, _outBuffer + (ii - dh) * ww, ww);
  338. }
  339. makeDistanceMap(alphaImg, _outBuffer, nw, nh);
  340. free(alphaImg);
  341. _glyphInfo.offset_x -= (float)dw;
  342. _glyphInfo.offset_y -= (float)dh;
  343. _glyphInfo.width = (float)nw;
  344. _glyphInfo.height = (float)nh;
  345. }
  346. return true;
  347. }
  348. typedef stl::unordered_map<CodePoint, GlyphInfo> GlyphHashMap;
  349. // cache font data
  350. struct FontManager::CachedFont
  351. {
  352. CachedFont()
  353. : trueTypeFont(NULL)
  354. {
  355. masterFontHandle.idx = bx::HandleAlloc::invalid;
  356. }
  357. FontInfo fontInfo;
  358. GlyphHashMap cachedGlyphs;
  359. TrueTypeFont* trueTypeFont;
  360. // an handle to a master font in case of sub distance field font
  361. FontHandle masterFontHandle;
  362. int16_t padding;
  363. };
  364. #define MAX_FONT_BUFFER_SIZE (512 * 512 * 4)
  365. FontManager::FontManager(Atlas* _atlas)
  366. : m_ownAtlas(false)
  367. , m_atlas(_atlas)
  368. {
  369. init();
  370. }
  371. FontManager::FontManager(uint16_t _textureSideWidth)
  372. : m_ownAtlas(true)
  373. , m_atlas(new Atlas(_textureSideWidth) )
  374. {
  375. init();
  376. }
  377. void FontManager::init()
  378. {
  379. m_cachedFiles = new CachedFile[MAX_OPENED_FILES];
  380. m_cachedFonts = new CachedFont[MAX_OPENED_FONT];
  381. m_buffer = new uint8_t[MAX_FONT_BUFFER_SIZE];
  382. const uint32_t W = 3;
  383. // Create filler rectangle
  384. uint8_t buffer[W * W * 4];
  385. bx::memSet(buffer, 255, W * W * 4);
  386. m_blackGlyph.width = W;
  387. m_blackGlyph.height = W;
  388. ///make sure the black glyph doesn't bleed by using a one pixel inner outline
  389. m_blackGlyph.regionIndex = m_atlas->addRegion(W, W, buffer, AtlasRegion::TYPE_GRAY, 1);
  390. }
  391. FontManager::~FontManager()
  392. {
  393. BX_CHECK(m_fontHandles.getNumHandles() == 0, "All the fonts must be destroyed before destroying the manager");
  394. delete [] m_cachedFonts;
  395. BX_CHECK(m_filesHandles.getNumHandles() == 0, "All the font files must be destroyed before destroying the manager");
  396. delete [] m_cachedFiles;
  397. delete [] m_buffer;
  398. if (m_ownAtlas)
  399. {
  400. delete m_atlas;
  401. }
  402. }
  403. TrueTypeHandle FontManager::createTtf(const uint8_t* _buffer, uint32_t _size)
  404. {
  405. uint16_t id = m_filesHandles.alloc();
  406. BX_CHECK(id != bx::HandleAlloc::invalid, "Invalid handle used");
  407. m_cachedFiles[id].buffer = new uint8_t[_size];
  408. m_cachedFiles[id].bufferSize = _size;
  409. bx::memCopy(m_cachedFiles[id].buffer, _buffer, _size);
  410. TrueTypeHandle ret = { id };
  411. return ret;
  412. }
  413. void FontManager::destroyTtf(TrueTypeHandle _handle)
  414. {
  415. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  416. delete m_cachedFiles[_handle.idx].buffer;
  417. m_cachedFiles[_handle.idx].bufferSize = 0;
  418. m_cachedFiles[_handle.idx].buffer = NULL;
  419. m_filesHandles.free(_handle.idx);
  420. }
  421. FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _ttfHandle, uint32_t _typefaceIndex, uint32_t _pixelSize, uint32_t _fontType)
  422. {
  423. BX_CHECK(bgfx::isValid(_ttfHandle), "Invalid handle used");
  424. TrueTypeFont* ttf = new TrueTypeFont();
  425. if (!ttf->init(m_cachedFiles[_ttfHandle.idx].buffer, m_cachedFiles[_ttfHandle.idx].bufferSize, _typefaceIndex, _pixelSize) )
  426. {
  427. delete ttf;
  428. FontHandle invalid = { bx::HandleAlloc::invalid };
  429. return invalid;
  430. }
  431. uint16_t fontIdx = m_fontHandles.alloc();
  432. BX_CHECK(fontIdx != bx::HandleAlloc::invalid, "Invalid handle used");
  433. CachedFont& font = m_cachedFonts[fontIdx];
  434. font.trueTypeFont = ttf;
  435. font.fontInfo = ttf->getFontInfo();
  436. font.fontInfo.fontType = int16_t(_fontType);
  437. font.fontInfo.pixelSize = uint16_t(_pixelSize);
  438. font.cachedGlyphs.clear();
  439. font.masterFontHandle.idx = bx::HandleAlloc::invalid;
  440. FontHandle handle = { fontIdx };
  441. return handle;
  442. }
  443. FontHandle FontManager::createScaledFontToPixelSize(FontHandle _baseFontHandle, uint32_t _pixelSize)
  444. {
  445. BX_CHECK(bgfx::isValid(_baseFontHandle), "Invalid handle used");
  446. CachedFont& baseFont = m_cachedFonts[_baseFontHandle.idx];
  447. FontInfo& fontInfo = baseFont.fontInfo;
  448. FontInfo newFontInfo = fontInfo;
  449. newFontInfo.pixelSize = uint16_t(_pixelSize);
  450. newFontInfo.scale = (float)_pixelSize / (float) fontInfo.pixelSize;
  451. newFontInfo.ascender = (newFontInfo.ascender * newFontInfo.scale);
  452. newFontInfo.descender = (newFontInfo.descender * newFontInfo.scale);
  453. newFontInfo.lineGap = (newFontInfo.lineGap * newFontInfo.scale);
  454. newFontInfo.maxAdvanceWidth = (newFontInfo.maxAdvanceWidth * newFontInfo.scale);
  455. newFontInfo.underlineThickness = (newFontInfo.underlineThickness * newFontInfo.scale);
  456. newFontInfo.underlinePosition = (newFontInfo.underlinePosition * newFontInfo.scale);
  457. uint16_t fontIdx = m_fontHandles.alloc();
  458. BX_CHECK(fontIdx != bx::HandleAlloc::invalid, "Invalid handle used");
  459. CachedFont& font = m_cachedFonts[fontIdx];
  460. font.cachedGlyphs.clear();
  461. font.fontInfo = newFontInfo;
  462. font.trueTypeFont = NULL;
  463. font.masterFontHandle = _baseFontHandle;
  464. FontHandle handle = { fontIdx };
  465. return handle;
  466. }
  467. void FontManager::destroyFont(FontHandle _handle)
  468. {
  469. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  470. CachedFont& font = m_cachedFonts[_handle.idx];
  471. if (font.trueTypeFont != NULL)
  472. {
  473. delete font.trueTypeFont;
  474. font.trueTypeFont = NULL;
  475. }
  476. font.cachedGlyphs.clear();
  477. m_fontHandles.free(_handle.idx);
  478. }
  479. bool FontManager::preloadGlyph(FontHandle _handle, const wchar_t* _string)
  480. {
  481. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  482. CachedFont& font = m_cachedFonts[_handle.idx];
  483. if (NULL == font.trueTypeFont)
  484. {
  485. return false;
  486. }
  487. for (uint32_t ii = 0, end = (uint32_t)wcslen(_string); ii < end; ++ii)
  488. {
  489. CodePoint codePoint = _string[ii];
  490. if (!preloadGlyph(_handle, codePoint) )
  491. {
  492. return false;
  493. }
  494. }
  495. return true;
  496. }
  497. bool FontManager::preloadGlyph(FontHandle _handle, CodePoint _codePoint)
  498. {
  499. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  500. CachedFont& font = m_cachedFonts[_handle.idx];
  501. FontInfo& fontInfo = font.fontInfo;
  502. GlyphHashMap::iterator iter = font.cachedGlyphs.find(_codePoint);
  503. if (iter != font.cachedGlyphs.end() )
  504. {
  505. return true;
  506. }
  507. if (NULL != font.trueTypeFont)
  508. {
  509. GlyphInfo glyphInfo;
  510. switch (font.fontInfo.fontType)
  511. {
  512. case FONT_TYPE_ALPHA:
  513. font.trueTypeFont->bakeGlyphAlpha(_codePoint, glyphInfo, m_buffer);
  514. break;
  515. case FONT_TYPE_DISTANCE:
  516. font.trueTypeFont->bakeGlyphDistance(_codePoint, glyphInfo, m_buffer);
  517. break;
  518. case FONT_TYPE_DISTANCE_SUBPIXEL:
  519. font.trueTypeFont->bakeGlyphDistance(_codePoint, glyphInfo, m_buffer);
  520. break;
  521. default:
  522. BX_CHECK(false, "TextureType not supported yet");
  523. }
  524. if (!addBitmap(glyphInfo, m_buffer) )
  525. {
  526. return false;
  527. }
  528. glyphInfo.advance_x = (glyphInfo.advance_x * fontInfo.scale);
  529. glyphInfo.advance_y = (glyphInfo.advance_y * fontInfo.scale);
  530. glyphInfo.offset_x = (glyphInfo.offset_x * fontInfo.scale);
  531. glyphInfo.offset_y = (glyphInfo.offset_y * fontInfo.scale);
  532. glyphInfo.height = (glyphInfo.height * fontInfo.scale);
  533. glyphInfo.width = (glyphInfo.width * fontInfo.scale);
  534. font.cachedGlyphs[_codePoint] = glyphInfo;
  535. return true;
  536. }
  537. if (isValid(font.masterFontHandle)
  538. && preloadGlyph(font.masterFontHandle, _codePoint) )
  539. {
  540. const GlyphInfo* glyph = getGlyphInfo(font.masterFontHandle, _codePoint);
  541. GlyphInfo glyphInfo = *glyph;
  542. glyphInfo.advance_x = (glyphInfo.advance_x * fontInfo.scale);
  543. glyphInfo.advance_y = (glyphInfo.advance_y * fontInfo.scale);
  544. glyphInfo.offset_x = (glyphInfo.offset_x * fontInfo.scale);
  545. glyphInfo.offset_y = (glyphInfo.offset_y * fontInfo.scale);
  546. glyphInfo.height = (glyphInfo.height * fontInfo.scale);
  547. glyphInfo.width = (glyphInfo.width * fontInfo.scale);
  548. font.cachedGlyphs[_codePoint] = glyphInfo;
  549. return true;
  550. }
  551. return false;
  552. }
  553. const FontInfo& FontManager::getFontInfo(FontHandle _handle) const
  554. {
  555. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  556. return m_cachedFonts[_handle.idx].fontInfo;
  557. }
  558. const GlyphInfo* FontManager::getGlyphInfo(FontHandle _handle, CodePoint _codePoint)
  559. {
  560. const GlyphHashMap& cachedGlyphs = m_cachedFonts[_handle.idx].cachedGlyphs;
  561. GlyphHashMap::const_iterator it = cachedGlyphs.find(_codePoint);
  562. if (it == cachedGlyphs.end() )
  563. {
  564. if (!preloadGlyph(_handle, _codePoint) )
  565. {
  566. return NULL;
  567. }
  568. it = cachedGlyphs.find(_codePoint);
  569. }
  570. BX_CHECK(it != cachedGlyphs.end(), "Failed to preload glyph.");
  571. return &it->second;
  572. }
  573. bool FontManager::addBitmap(GlyphInfo& _glyphInfo, const uint8_t* _data)
  574. {
  575. _glyphInfo.regionIndex = m_atlas->addRegion( (uint16_t) ceil(_glyphInfo.width), (uint16_t) ceil(_glyphInfo.height), _data, AtlasRegion::TYPE_GRAY);
  576. return true;
  577. }