font_manager.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /* Copyright 2013 Jeremie Roy. All rights reserved.
  2. * License: http://www.opensource.org/licenses/BSD-2-Clause
  3. */
  4. #include "font_manager.h"
  5. #include "../cube_atlas.h"
  6. #if BX_COMPILER_MSVC
  7. # pragma warning(push)
  8. # pragma warning(disable: 4100) // DISABLE warning C4100: '' : unreferenced formal parameter
  9. # pragma warning(disable: 4146) // DISABLE warning C4146: unary minus operator applied to unsigned type, result still unsigned
  10. # pragma warning(disable: 4700) // DISABLE warning C4700: uninitialized local variable 'temp' used
  11. # pragma warning(disable: 4701) // DISABLE warning C4701: potentially uninitialized local variable '' used
  12. # include "../../../3rdparty/freetype/freetype.h"
  13. # pragma warning(pop)
  14. #else
  15. # include "../../../3rdparty/freetype/freetype.h"
  16. #endif // BX_COMPILER_MSVC
  17. #include "../../../3rdparty/edtaa3/edtaa3func.h"
  18. #include "../../../3rdparty/edtaa3/edtaa3func.cpp"
  19. #include <math.h>
  20. #include <bx/bx.h>
  21. #if BGFX_CONFIG_USE_TINYSTL
  22. namespace tinystl
  23. {
  24. //struct bgfx_allocator
  25. //{
  26. //static void* static_allocate(size_t _bytes);
  27. //static void static_deallocate(void* _ptr, size_t /*_bytes*/);
  28. //};
  29. } // namespace tinystl
  30. //# define TINYSTL_ALLOCATOR tinystl::bgfx_allocator
  31. # include <TINYSTL/unordered_map.h>
  32. //# include <TINYSTL/unordered_set.h>
  33. namespace stl = tinystl;
  34. #else
  35. # include <unordered_map>
  36. namespace std { namespace tr1 {} }
  37. namespace stl {
  38. using namespace std;
  39. using namespace std::tr1;
  40. }
  41. #endif // BGFX_CONFIG_USE_TINYSTL
  42. class FontManager::TrueTypeFont
  43. {
  44. public:
  45. TrueTypeFont();
  46. ~TrueTypeFont();
  47. /// Initialize from an external buffer
  48. /// @remark The ownership of the buffer is external, and you must ensure it stays valid up to this object lifetime
  49. /// @return true if the initialization succeed
  50. bool init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight );
  51. /// return the font descriptor of the current font
  52. FontInfo getFontInfo();
  53. /// raster a glyph as 8bit alpha to a memory buffer
  54. /// update the GlyphInfo according to the raster strategy
  55. /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(char)
  56. bool bakeGlyphAlpha(CodePoint_t _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
  57. /// raster a glyph as 32bit subpixel rgba to a memory buffer
  58. /// update the GlyphInfo according to the raster strategy
  59. /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(uint32_t)
  60. bool bakeGlyphSubpixel(CodePoint_t _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
  61. /// raster a glyph as 8bit signed distance to a memory buffer
  62. /// update the GlyphInfo according to the raster strategy
  63. /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(char)
  64. bool bakeGlyphDistance(CodePoint_t _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
  65. private:
  66. void* m_font;
  67. };
  68. struct FTHolder
  69. {
  70. FT_Library m_library;
  71. FT_Face m_face;
  72. };
  73. FontManager::TrueTypeFont::TrueTypeFont(): m_font(NULL)
  74. {
  75. }
  76. FontManager::TrueTypeFont::~TrueTypeFont()
  77. {
  78. if(m_font!=NULL)
  79. {
  80. FTHolder* holder = (FTHolder*) m_font;
  81. FT_Done_Face( holder->m_face );
  82. FT_Done_FreeType( holder->m_library );
  83. delete m_font;
  84. m_font = NULL;
  85. }
  86. }
  87. bool FontManager::TrueTypeFont::init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight)
  88. {
  89. BX_CHECK((_bufferSize > 256 && _bufferSize < 100000000), "TrueType buffer size is suspicious");
  90. BX_CHECK((_pixelHeight > 4 && _pixelHeight < 128), "TrueType buffer size is suspicious");
  91. BX_CHECK(m_font == NULL, "TrueTypeFont already initialized" );
  92. FTHolder* holder = new FTHolder();
  93. // Initialize Freetype library
  94. FT_Error error = FT_Init_FreeType( &holder->m_library );
  95. if( error)
  96. {
  97. delete holder;
  98. return false;
  99. }
  100. error = FT_New_Memory_Face( holder->m_library, _buffer, _bufferSize, _fontIndex, &holder->m_face );
  101. if ( error == FT_Err_Unknown_File_Format )
  102. {
  103. // the font file could be opened and read, but it appears
  104. //that its font format is unsupported
  105. FT_Done_FreeType( holder->m_library );
  106. delete holder;
  107. return false;
  108. }
  109. else if ( error )
  110. {
  111. // another error code means that the font file could not
  112. // be opened or read, or simply that it is broken...
  113. FT_Done_FreeType( holder->m_library );
  114. delete holder;
  115. return false;
  116. }
  117. // Select unicode charmap
  118. error = FT_Select_Charmap( holder->m_face, FT_ENCODING_UNICODE );
  119. if( error )
  120. {
  121. FT_Done_Face( holder->m_face );
  122. FT_Done_FreeType( holder->m_library );
  123. return false;
  124. }
  125. //set size in pixels
  126. error = FT_Set_Pixel_Sizes( holder->m_face, 0, _pixelHeight );
  127. if( error )
  128. {
  129. FT_Done_Face( holder->m_face );
  130. FT_Done_FreeType( holder->m_library );
  131. return false;
  132. }
  133. m_font = holder;
  134. return true;
  135. }
  136. FontInfo FontManager::TrueTypeFont::getFontInfo()
  137. {
  138. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized" );
  139. FTHolder* holder = (FTHolder*) m_font;
  140. //todo manage unscalable font
  141. BX_CHECK(FT_IS_SCALABLE (holder->m_face), "Font is unscalable");
  142. FT_Size_Metrics metrics = holder->m_face->size->metrics;
  143. FontInfo outFontInfo;
  144. outFontInfo.m_scale = 1.0f;
  145. outFontInfo.m_ascender = metrics.ascender /64.0f;
  146. outFontInfo.m_descender = metrics.descender /64.0f;
  147. outFontInfo.m_lineGap = (metrics.height - metrics.ascender + metrics.descender) /64.0f;
  148. outFontInfo.m_underline_position = FT_MulFix(holder->m_face->underline_position, metrics.y_scale) /64.0f;
  149. outFontInfo.m_underline_thickness= FT_MulFix(holder->m_face->underline_thickness,metrics.y_scale) /64.0f;
  150. return outFontInfo;
  151. }
  152. bool FontManager::TrueTypeFont::bakeGlyphAlpha(CodePoint_t _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
  153. {
  154. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized" );
  155. FTHolder* holder = (FTHolder*) m_font;
  156. _glyphInfo.m_glyphIndex = FT_Get_Char_Index( holder->m_face, _codePoint );
  157. FT_GlyphSlot slot = holder->m_face->glyph;
  158. FT_Error error = FT_Load_Glyph( holder->m_face, _glyphInfo.m_glyphIndex, FT_LOAD_DEFAULT );
  159. if(error) { return false; }
  160. FT_Glyph glyph;
  161. error = FT_Get_Glyph( slot, &glyph );
  162. if ( error ) { return false; }
  163. error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
  164. if(error){ return false; }
  165. FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
  166. int32_t x = bitmap->left;
  167. int32_t y = -bitmap->top;
  168. int32_t w = bitmap->bitmap.width;
  169. int32_t h = bitmap->bitmap.rows;
  170. _glyphInfo.m_offset_x = (float) x;
  171. _glyphInfo.m_offset_y = (float) y;
  172. _glyphInfo.m_width = (float) w;
  173. _glyphInfo.m_height = (float) h;
  174. _glyphInfo.m_advance_x = (float)slot->advance.x /64.0f;
  175. _glyphInfo.m_advance_y = (float)slot->advance.y /64.0f;
  176. int32_t charsize = 1;
  177. int32_t depth=1;
  178. int32_t stride = bitmap->bitmap.pitch;
  179. for( int32_t ii=0; ii<h; ++ii )
  180. {
  181. memcpy(_outBuffer+(ii*w) * charsize * depth,
  182. bitmap->bitmap.buffer + (ii*stride) * charsize, w * charsize * depth );
  183. }
  184. FT_Done_Glyph(glyph);
  185. return true;
  186. }
  187. bool FontManager::TrueTypeFont::bakeGlyphSubpixel(CodePoint_t _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
  188. {
  189. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized" );
  190. FTHolder* holder = (FTHolder*) m_font;
  191. _glyphInfo.m_glyphIndex = FT_Get_Char_Index( holder->m_face, _codePoint );
  192. FT_GlyphSlot slot = holder->m_face->glyph;
  193. FT_Error error = FT_Load_Glyph( holder->m_face, _glyphInfo.m_glyphIndex, FT_LOAD_DEFAULT );
  194. if(error) { return false; }
  195. FT_Glyph glyph;
  196. error = FT_Get_Glyph( slot, &glyph );
  197. if ( error ) { return false; }
  198. error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_LCD, 0, 1 );
  199. if(error){ return false; }
  200. FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
  201. int32_t x = bitmap->left;
  202. int32_t y = -bitmap->top;
  203. int32_t w = bitmap->bitmap.width;
  204. int32_t h = bitmap->bitmap.rows;
  205. _glyphInfo.m_offset_x = (float) x;
  206. _glyphInfo.m_offset_y = (float) y;
  207. _glyphInfo.m_width = (float) w;
  208. _glyphInfo.m_height = (float) h;
  209. _glyphInfo.m_advance_x = (float)slot->advance.x /64.0f;
  210. _glyphInfo.m_advance_y = (float)slot->advance.y /64.0f;
  211. int32_t charsize = 1;
  212. int32_t depth=3;
  213. int32_t stride = bitmap->bitmap.pitch;
  214. for( int32_t ii=0; ii<h; ++ii )
  215. {
  216. memcpy(_outBuffer+(ii*w) * charsize * depth,
  217. bitmap->bitmap.buffer + (ii*stride) * charsize, w * charsize * depth );
  218. }
  219. FT_Done_Glyph(glyph);
  220. return true;
  221. }
  222. //TODO optimize: remove dynamic allocation and convert double to float
  223. void make_distance_map( unsigned char *img, unsigned char *outImg, unsigned int width, unsigned int height )
  224. {
  225. short * xdist = (short *) malloc( width * height * sizeof(short) );
  226. short * ydist = (short *) malloc( width * height * sizeof(short) );
  227. double * gx = (double *) calloc( width * height, sizeof(double) );
  228. double * gy = (double *) calloc( width * height, sizeof(double) );
  229. double * data = (double *) calloc( width * height, sizeof(double) );
  230. double * outside = (double *) calloc( width * height, sizeof(double) );
  231. double * inside = (double *) calloc( width * height, sizeof(double) );
  232. uint32_t ii;
  233. // Convert img into double (data)
  234. double img_min = 255, img_max = -255;
  235. for( ii=0; ii<width*height; ++ii)
  236. {
  237. double v = img[ii];
  238. data[ii] = v;
  239. if (v > img_max) img_max = v;
  240. if (v < img_min) img_min = v;
  241. }
  242. // Rescale image levels between 0 and 1
  243. for( ii=0; ii<width*height; ++ii)
  244. {
  245. data[ii] = (img[ii]-img_min)/(img_max-img_min);
  246. }
  247. // Compute outside = edtaa3(bitmap); % Transform background (0's)
  248. computegradient( data, width, height, gx, gy);
  249. edtaa3(data, gx, gy, width, height, xdist, ydist, outside);
  250. for( ii=0; ii<width*height; ++ii)
  251. if( outside[ii] < 0 )
  252. outside[ii] = 0.0;
  253. // Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
  254. memset(gx, 0, sizeof(double)*width*height );
  255. memset(gy, 0, sizeof(double)*width*height );
  256. for( ii=0; ii<width*height; ++ii)
  257. data[ii] = 1.0 - data[ii];
  258. computegradient( data, width, height, gx, gy);
  259. edtaa3(data, gx, gy, width, height, xdist, ydist, inside);
  260. for( ii=0; ii<width*height; ++ii)
  261. if( inside[ii] < 0 )
  262. inside[ii] = 0.0;
  263. // distmap = outside - inside; % Bipolar distance field
  264. unsigned char *out = outImg;//(unsigned char *) malloc( width * height * sizeof(unsigned char) );
  265. for( ii=0; ii<width*height; ++ii)
  266. {
  267. //out[i] = 127 - outside[i]*8;
  268. //if(out[i]<0) out[i] = 0;
  269. //out[i] += inside[i]*16;
  270. //if(out[i]>255) out[i] = 255;
  271. outside[ii] -= inside[ii];
  272. outside[ii] = 128 + outside[ii]*16;
  273. //if(outside[i] > 8) outside[i] = 8;
  274. //if(inside[i] > 8) outside[i] = 8;
  275. //outside[i] = 128 - inside[i]*8 + outside[i]*8;
  276. if( outside[ii] < 0 ) outside[ii] = 0;
  277. if( outside[ii] > 255 ) outside[ii] = 255;
  278. out[ii] = 255 - (unsigned char) outside[ii];
  279. //out[i] = (unsigned char) outside[i];
  280. }
  281. free( xdist );
  282. free( ydist );
  283. free( gx );
  284. free( gy );
  285. free( data );
  286. free( outside );
  287. free( inside );
  288. }
  289. bool FontManager::TrueTypeFont::bakeGlyphDistance(CodePoint_t _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
  290. {
  291. BX_CHECK(m_font != NULL, "TrueTypeFont not initialized" );
  292. FTHolder* holder = (FTHolder*) m_font;
  293. _glyphInfo.m_glyphIndex = FT_Get_Char_Index( holder->m_face, _codePoint );
  294. FT_Int32 loadMode = FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING;
  295. FT_Render_Mode renderMode = FT_RENDER_MODE_NORMAL;
  296. FT_GlyphSlot slot = holder->m_face->glyph;
  297. FT_Error error = FT_Load_Glyph( holder->m_face, _glyphInfo.m_glyphIndex, loadMode );
  298. if(error) { return false; }
  299. FT_Glyph glyph;
  300. error = FT_Get_Glyph( slot, &glyph );
  301. if ( error ) { return false; }
  302. error = FT_Glyph_To_Bitmap( &glyph, renderMode, 0, 1 );
  303. if(error){ return false; }
  304. FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
  305. int32_t x = bitmap->left;
  306. int32_t y = -bitmap->top;
  307. int32_t w = bitmap->bitmap.width;
  308. int32_t h = bitmap->bitmap.rows;
  309. _glyphInfo.m_offset_x = (float) x;
  310. _glyphInfo.m_offset_y = (float) y;
  311. _glyphInfo.m_width = (float) w;
  312. _glyphInfo.m_height = (float) h;
  313. _glyphInfo.m_advance_x = (float)slot->advance.x /64.0f;
  314. _glyphInfo.m_advance_y = (float)slot->advance.y /64.0f;
  315. int32_t charsize = 1;
  316. int32_t depth=1;
  317. int32_t stride = bitmap->bitmap.pitch;
  318. for(int32_t ii=0; ii<h; ++ii )
  319. {
  320. memcpy(_outBuffer+(ii*w) * charsize * depth,
  321. bitmap->bitmap.buffer + (ii*stride) * charsize, w * charsize * depth );
  322. }
  323. FT_Done_Glyph(glyph);
  324. if(w*h >0)
  325. {
  326. uint32_t dw = 6;
  327. uint32_t dh = 6;
  328. if(dw<2) dw = 2;
  329. if(dh<2) dh = 2;
  330. uint32_t nw = w + dw*2;
  331. uint32_t nh = h + dh*2;
  332. BX_CHECK(nw*nh < 128*128, "buffer overflow");
  333. uint32_t buffSize = nw*nh*sizeof(uint8_t);
  334. uint8_t * alphaImg = (uint8_t *) malloc( buffSize );
  335. memset(alphaImg, 0, nw*nh*sizeof(uint8_t));
  336. //copy the original buffer to the temp one
  337. for(uint32_t ii= dh; ii< nh-dh; ++ii)
  338. {
  339. memcpy(alphaImg+ii*nw+dw, _outBuffer+(ii-dh)*w, w);
  340. }
  341. make_distance_map(alphaImg, _outBuffer, nw, nh);
  342. free(alphaImg);
  343. _glyphInfo.m_offset_x -= (float) dw;
  344. _glyphInfo.m_offset_y -= (float) dh;
  345. _glyphInfo.m_width = (float) nw ;
  346. _glyphInfo.m_height = (float) nh;
  347. }
  348. return true;
  349. }
  350. //*************************************************************
  351. typedef stl::unordered_map<CodePoint_t, GlyphInfo> GlyphHash_t;
  352. // cache font data
  353. struct FontManager::CachedFont
  354. {
  355. CachedFont(){ m_trueTypeFont = NULL; m_masterFontHandle.idx = -1; }
  356. FontInfo m_fontInfo;
  357. GlyphHash_t m_cachedGlyphs;
  358. FontManager::TrueTypeFont* m_trueTypeFont;
  359. // an handle to a master font in case of sub distance field font
  360. FontHandle m_masterFontHandle;
  361. int16_t m_padding;
  362. };
  363. const uint16_t MAX_OPENED_FILES = 64;
  364. const uint16_t MAX_OPENED_FONT = 64;
  365. const uint32_t MAX_FONT_BUFFER_SIZE = 512*512*4;
  366. FontManager::FontManager(Atlas* _atlas):m_filesHandles(MAX_OPENED_FILES), m_fontHandles(MAX_OPENED_FONT)
  367. {
  368. m_atlas = _atlas;
  369. m_ownAtlas = false;
  370. init();
  371. }
  372. FontManager::FontManager(uint32_t _textureSideWidth):m_filesHandles(MAX_OPENED_FILES), m_fontHandles(MAX_OPENED_FONT)
  373. {
  374. m_atlas = new Atlas(_textureSideWidth);
  375. m_ownAtlas = true;
  376. init();
  377. }
  378. void FontManager::init()
  379. {
  380. m_cachedFiles = new CachedFile[MAX_OPENED_FILES];
  381. m_cachedFonts = new CachedFont[MAX_OPENED_FONT];
  382. m_buffer = new uint8_t[MAX_FONT_BUFFER_SIZE];
  383. // Create filler rectangle
  384. uint8_t buffer[4*4*4];
  385. memset( buffer, 255, 4 * 4 * 4);
  386. m_blackGlyph.m_width=3;
  387. m_blackGlyph.m_height=3;
  388. bool addResult = addBitmap(m_blackGlyph, buffer);
  389. BX_UNUSED(addResult);
  390. BX_CHECK( addResult , "unable to add white glyph" );
  391. //make sure the black glyph doesn't bleed
  392. /*int16_t texUnit = 65535 / m_textureWidth;
  393. m_blackGlyph.texture_x0 += texUnit;
  394. m_blackGlyph.texture_y0 += texUnit;
  395. m_blackGlyph.texture_x1 -= texUnit;
  396. m_blackGlyph.texture_y1 -= texUnit;*/
  397. }
  398. FontManager::~FontManager()
  399. {
  400. BX_CHECK(m_fontHandles.getNumHandles() == 0, "All the fonts must be destroyed before destroying the manager");
  401. delete [] m_cachedFonts;
  402. BX_CHECK(m_filesHandles.getNumHandles() == 0, "All the font files must be destroyed before destroying the manager");
  403. delete [] m_cachedFiles;
  404. delete [] m_buffer;
  405. if(m_ownAtlas)
  406. {
  407. delete m_atlas;
  408. }
  409. }
  410. TrueTypeHandle FontManager::loadTrueTypeFromFile(const char* _fontPath)
  411. {
  412. FILE * pFile;
  413. pFile = fopen (_fontPath, "rb");
  414. if (pFile==NULL)
  415. {
  416. TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
  417. return invalid;
  418. }
  419. // Go to the end of the file.
  420. if (fseek(pFile, 0L, SEEK_END) == 0)
  421. {
  422. // Get the size of the file.
  423. long bufsize = ftell(pFile);
  424. if (bufsize == -1)
  425. {
  426. fclose(pFile);
  427. TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
  428. return invalid;
  429. }
  430. uint8_t* buffer = new uint8_t[bufsize];
  431. // Go back to the start of the file.
  432. fseek(pFile, 0L, SEEK_SET);
  433. // Read the entire file into memory.
  434. uint32_t newLen = fread((void*)buffer, sizeof(char), bufsize, pFile);
  435. if (newLen == 0)
  436. {
  437. fclose(pFile);
  438. delete [] buffer;
  439. TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
  440. return invalid;
  441. }
  442. fclose(pFile);
  443. uint16_t id = m_filesHandles.alloc();
  444. BX_CHECK(id != bx::HandleAlloc::invalid, "No more room for files");
  445. m_cachedFiles[id].buffer = buffer;
  446. m_cachedFiles[id].bufferSize = bufsize;
  447. TrueTypeHandle ret = {id};
  448. return ret;
  449. }
  450. //TODO validate font
  451. TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
  452. return invalid;
  453. }
  454. TrueTypeHandle FontManager::loadTrueTypeFromMemory(const uint8_t* _buffer, uint32_t _size)
  455. {
  456. uint16_t id = m_filesHandles.alloc();
  457. BX_CHECK(id != bx::HandleAlloc::invalid, "Invalid handle used");
  458. m_cachedFiles[id].buffer = new uint8_t[_size];
  459. m_cachedFiles[id].bufferSize = _size;
  460. memcpy(m_cachedFiles[id].buffer, _buffer, _size);
  461. //TODO validate font
  462. TrueTypeHandle ret = {id};
  463. return ret;
  464. }
  465. void FontManager::unloadTrueType(TrueTypeHandle _handle)
  466. {
  467. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  468. delete m_cachedFiles[_handle.idx].buffer;
  469. m_cachedFiles[_handle.idx].bufferSize = 0;
  470. m_cachedFiles[_handle.idx].buffer = NULL;
  471. m_filesHandles.free(_handle.idx);
  472. }
  473. FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _tt_handle, uint32_t _typefaceIndex, uint32_t _pixelSize, FontType _fontType)
  474. {
  475. BX_CHECK(bgfx::invalidHandle != _tt_handle.idx, "Invalid handle used");
  476. TrueTypeFont* ttf = new TrueTypeFont();
  477. if(!ttf->init( m_cachedFiles[_tt_handle.idx].buffer, m_cachedFiles[_tt_handle.idx].bufferSize, _typefaceIndex, _pixelSize))
  478. {
  479. delete ttf;
  480. FontHandle invalid = BGFX_INVALID_HANDLE;
  481. return invalid;
  482. }
  483. uint16_t fontIdx = m_fontHandles.alloc();
  484. BX_CHECK(fontIdx != bx::HandleAlloc::invalid, "Invalid handle used");
  485. m_cachedFonts[fontIdx].m_trueTypeFont = ttf;
  486. m_cachedFonts[fontIdx].m_fontInfo = ttf->getFontInfo();
  487. m_cachedFonts[fontIdx].m_fontInfo.m_fontType = _fontType;
  488. m_cachedFonts[fontIdx].m_fontInfo.m_pixelSize = _pixelSize;
  489. m_cachedFonts[fontIdx].m_cachedGlyphs.clear();
  490. m_cachedFonts[fontIdx].m_masterFontHandle.idx = -1;
  491. FontHandle ret = {fontIdx};
  492. return ret;
  493. }
  494. FontHandle FontManager::createScaledFontToPixelSize(FontHandle _baseFontHandle, uint32_t _pixelSize)
  495. {
  496. BX_CHECK(bgfx::invalidHandle != _baseFontHandle.idx, "Invalid handle used");
  497. CachedFont& font = m_cachedFonts[_baseFontHandle.idx];
  498. FontInfo& fontInfo = font.m_fontInfo;
  499. FontInfo newFontInfo = fontInfo;
  500. newFontInfo.m_pixelSize = _pixelSize;
  501. newFontInfo.m_scale = (float)_pixelSize / (float) fontInfo.m_pixelSize;
  502. newFontInfo.m_ascender = (newFontInfo.m_ascender * newFontInfo.m_scale);
  503. newFontInfo.m_descender = (newFontInfo.m_descender * newFontInfo.m_scale);
  504. newFontInfo.m_lineGap = (newFontInfo.m_lineGap * newFontInfo.m_scale);
  505. newFontInfo.m_underline_thickness = (newFontInfo.m_underline_thickness * newFontInfo.m_scale);
  506. newFontInfo.m_underline_position = (newFontInfo.m_underline_position * newFontInfo.m_scale);
  507. uint16_t fontIdx = m_fontHandles.alloc();
  508. BX_CHECK(fontIdx != bx::HandleAlloc::invalid, "Invalid handle used");
  509. m_cachedFonts[fontIdx].m_cachedGlyphs.clear();
  510. m_cachedFonts[fontIdx].m_fontInfo = newFontInfo;
  511. m_cachedFonts[fontIdx].m_trueTypeFont = NULL;
  512. m_cachedFonts[fontIdx].m_masterFontHandle = _baseFontHandle;
  513. FontHandle ret = {fontIdx};
  514. return ret;
  515. }
  516. FontHandle FontManager::loadBakedFontFromFile(const char* /*fontPath*/, const char* /*descriptorPath*/)
  517. {
  518. //assert(false); //TODO implement
  519. FontHandle invalid = BGFX_INVALID_HANDLE;
  520. return invalid;
  521. }
  522. FontHandle FontManager::loadBakedFontFromMemory(const uint8_t* /*imageBuffer*/, uint32_t /*imageSize*/, const uint8_t* /*descriptorBuffer*/, uint32_t /*descriptorSize*/)
  523. {
  524. //assert(false); //TODO implement
  525. FontHandle invalid = BGFX_INVALID_HANDLE;
  526. return invalid;
  527. }
  528. void FontManager::destroyFont(FontHandle _handle)
  529. {
  530. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  531. if(m_cachedFonts[_handle.idx].m_trueTypeFont != NULL)
  532. {
  533. delete m_cachedFonts[_handle.idx].m_trueTypeFont;
  534. m_cachedFonts[_handle.idx].m_trueTypeFont = NULL;
  535. }
  536. m_cachedFonts[_handle.idx].m_cachedGlyphs.clear();
  537. m_fontHandles.free(_handle.idx);
  538. }
  539. bool FontManager::preloadGlyph(FontHandle _handle, const wchar_t* _string)
  540. {
  541. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  542. CachedFont& font = m_cachedFonts[_handle.idx];
  543. //if truetype present
  544. if(font.m_trueTypeFont != NULL)
  545. {
  546. //parse string
  547. for( uint32_t ii=0, end = wcslen(_string) ; ii < end; ++ii )
  548. {
  549. //if glyph cached, continue
  550. CodePoint_t codePoint = _string[ii];
  551. if(!preloadGlyph(_handle, codePoint))
  552. {
  553. return false;
  554. }
  555. }
  556. return true;
  557. }
  558. return false;
  559. }
  560. bool FontManager::preloadGlyph(FontHandle _handle, CodePoint_t _codePoint)
  561. {
  562. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  563. CachedFont& font = m_cachedFonts[_handle.idx];
  564. FontInfo& fontInfo = font.m_fontInfo;
  565. //check if glyph not already present
  566. GlyphHash_t::iterator iter = font.m_cachedGlyphs.find(_codePoint);
  567. if(iter != font.m_cachedGlyphs.end())
  568. {
  569. return true;
  570. }
  571. //if truetype present
  572. if(font.m_trueTypeFont != NULL)
  573. {
  574. GlyphInfo glyphInfo;
  575. //bake glyph as bitmap to buffer
  576. switch(font.m_fontInfo.m_fontType)
  577. {
  578. case FONT_TYPE_ALPHA:
  579. font.m_trueTypeFont->bakeGlyphAlpha(_codePoint, glyphInfo, m_buffer);
  580. break;
  581. //case FONT_TYPE_LCD:
  582. //font.m_trueTypeFont->bakeGlyphSubpixel(codePoint, glyphInfo, m_buffer);
  583. //break;
  584. case FONT_TYPE_DISTANCE:
  585. font.m_trueTypeFont->bakeGlyphDistance(_codePoint, glyphInfo, m_buffer);
  586. break;
  587. case FONT_TYPE_DISTANCE_SUBPIXEL:
  588. font.m_trueTypeFont->bakeGlyphDistance(_codePoint, glyphInfo, m_buffer);
  589. break;
  590. default:
  591. BX_CHECK(false, "TextureType not supported yet");
  592. };
  593. //copy bitmap to texture
  594. if(!addBitmap(glyphInfo, m_buffer) )
  595. {
  596. return false;
  597. }
  598. glyphInfo.m_advance_x = (glyphInfo.m_advance_x * fontInfo.m_scale);
  599. glyphInfo.m_advance_y = (glyphInfo.m_advance_y * fontInfo.m_scale);
  600. glyphInfo.m_offset_x = (glyphInfo.m_offset_x * fontInfo.m_scale);
  601. glyphInfo.m_offset_y = (glyphInfo.m_offset_y * fontInfo.m_scale);
  602. glyphInfo.m_height = (glyphInfo.m_height * fontInfo.m_scale);
  603. glyphInfo.m_width = (glyphInfo.m_width * fontInfo.m_scale);
  604. // store cached glyph
  605. font.m_cachedGlyphs[_codePoint] = glyphInfo;
  606. return true;
  607. }else
  608. {
  609. //retrieve glyph from parent font if any
  610. if(font.m_masterFontHandle.idx != bgfx::invalidHandle)
  611. {
  612. if(preloadGlyph(font.m_masterFontHandle, _codePoint))
  613. {
  614. GlyphInfo glyphInfo;
  615. getGlyphInfo(font.m_masterFontHandle, _codePoint, glyphInfo);
  616. glyphInfo.m_advance_x = (glyphInfo.m_advance_x * fontInfo.m_scale);
  617. glyphInfo.m_advance_y = (glyphInfo.m_advance_y * fontInfo.m_scale);
  618. glyphInfo.m_offset_x = (glyphInfo.m_offset_x * fontInfo.m_scale);
  619. glyphInfo.m_offset_y = (glyphInfo.m_offset_y * fontInfo.m_scale);
  620. glyphInfo.m_height = (glyphInfo.m_height * fontInfo.m_scale);
  621. glyphInfo.m_width = (glyphInfo.m_width * fontInfo.m_scale);
  622. // store cached glyph
  623. font.m_cachedGlyphs[_codePoint] = glyphInfo;
  624. return true;
  625. }
  626. }
  627. }
  628. return false;
  629. }
  630. const FontInfo& FontManager::getFontInfo(FontHandle _handle)
  631. {
  632. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  633. return m_cachedFonts[_handle.idx].m_fontInfo;
  634. }
  635. bool FontManager::getGlyphInfo(FontHandle _handle, CodePoint_t _codePoint, GlyphInfo& _outInfo)
  636. {
  637. GlyphHash_t::iterator iter = m_cachedFonts[_handle.idx].m_cachedGlyphs.find(_codePoint);
  638. if(iter == m_cachedFonts[_handle.idx].m_cachedGlyphs.end())
  639. {
  640. if(preloadGlyph(_handle, _codePoint))
  641. {
  642. iter = m_cachedFonts[_handle.idx].m_cachedGlyphs.find(_codePoint);
  643. }else
  644. {
  645. return false;
  646. }
  647. }
  648. _outInfo = iter->second;
  649. return true;
  650. }
  651. // ****************************************************************************
  652. bool FontManager::addBitmap(GlyphInfo& _glyphInfo, const uint8_t* _data)
  653. {
  654. _glyphInfo.m_regionIndex = m_atlas->addRegion((uint16_t) ceil(_glyphInfo.m_width),(uint16_t) ceil(_glyphInfo.m_height), _data, AtlasRegion::TYPE_GRAY);
  655. return true;
  656. }