font_manager.cpp 18 KB

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