font_manager.cpp 22 KB

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