font_manager.cpp 18 KB

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