font_manager.cpp 23 KB

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