FTFont.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "FTFont.h"
  2. #include "gfx/Texture.h"
  3. #include "gfx/RenderDevice.h"
  4. #include "img/ImageData.h"
  5. #include "BFApp.h"
  6. #include "freetype/ftsizes.h"
  7. #include "util/AllocDebug.h"
  8. USING_NS_BF;
  9. const int FT_PAGE_WIDTH = 1024;
  10. const int FT_PAGE_HEIGHT = 1024;
  11. //const int FT_PAGE_WIDTH = 128;
  12. //const int FT_PAGE_HEIGHT = 128;
  13. static FT_Library gFTLibrary = NULL;
  14. static FTFontManager gFTFontManager;
  15. FTFont::FTFont()
  16. {
  17. mFace = NULL;
  18. mFaceSize = NULL;
  19. mHeight = 0;
  20. mAscent = 0;
  21. mDescent = 0;
  22. mMaxAdvance = 0;
  23. }
  24. FTFont::~FTFont()
  25. {
  26. Dispose(false);
  27. }
  28. void FTFont::Dispose(bool cacheRetain)
  29. {
  30. if (mFaceSize != NULL)
  31. {
  32. BF_ASSERT((mFaceSize->mRefCount > 0) && (mFaceSize->mRefCount < 1000000));
  33. mFaceSize->mRefCount--;
  34. if (mFaceSize->mRefCount == 0)
  35. {
  36. mFace->mFaceSizes.Remove(mFaceSize->mPointSize);
  37. delete mFaceSize;
  38. if (!cacheRetain)
  39. {
  40. if (mFace->mFaceSizes.IsEmpty())
  41. {
  42. bool removed = gFTFontManager.mFaces.Remove(mFace->mFileName);
  43. BF_ASSERT(removed);
  44. delete mFace;
  45. }
  46. }
  47. }
  48. mFaceSize = NULL;
  49. }
  50. }
  51. FTFontManager::FaceSize::~FaceSize()
  52. {
  53. if (mFTSize != 0)
  54. FT_Done_Size(mFTSize);
  55. }
  56. FTFontManager::Face::~Face()
  57. {
  58. if (mFTFace != 0)
  59. FT_Done_Face(mFTFace);
  60. }
  61. FTFontManager::FTFontManager()
  62. {
  63. for (int i = 0; i < 256; i++)
  64. {
  65. uint8 whiteVal = (uint8)(pow(i / 255.0f, 0.75) * 255.0f);
  66. uint8 blackVal = (uint8)(pow(i / 255.0f, 0.9) * 255.0f);
  67. mWhiteTab[i] = whiteVal;
  68. mBlackTab[i] = blackVal;
  69. }
  70. }
  71. FTFontManager::~FTFontManager()
  72. {
  73. for (auto page : mPages)
  74. delete page;
  75. mPages.Clear();
  76. for (auto faceKV : mFaces)
  77. delete faceKV.mValue;
  78. mFaces.Clear();
  79. }
  80. void FTFontManager::DoClearCache()
  81. {
  82. for (auto page : mPages)
  83. delete page;
  84. mPages.Clear();
  85. for (auto itr = mFaces.begin(); itr != mFaces.end(); )
  86. {
  87. auto face = itr->mValue;
  88. if (face->mFaceSizes.IsEmpty())
  89. {
  90. delete face;
  91. itr = mFaces.Remove(itr);
  92. }
  93. else
  94. ++itr;
  95. }
  96. }
  97. void FTFontManager::ClearCache()
  98. {
  99. gFTFontManager.DoClearCache();
  100. }
  101. FTFontManager::Page::~Page()
  102. {
  103. mTexture->Release();
  104. //delete mTexture;
  105. }
  106. /*FTFontManager::Glyph::~Glyph()
  107. {
  108. //delete mTextureSegment;
  109. }*/
  110. bool FTFont::Load(const StringImpl& fileName, float pointSize)
  111. {
  112. if (gFTLibrary == NULL)
  113. FT_Init_FreeType(&gFTLibrary);
  114. FTFontManager::Face* face = NULL;
  115. String key = fileName;
  116. void* memPtr = NULL;
  117. int memLen = 0;
  118. bool isMemory = ParseMemorySpan(fileName, memPtr, memLen, &key);
  119. FTFontManager::Face** facePtr = NULL;
  120. if (gFTFontManager.mFaces.TryAdd(key, NULL, &facePtr))
  121. {
  122. face = new FTFontManager::Face();
  123. *facePtr = face;
  124. face->mFileName = key;
  125. FT_Face ftFace = NULL;
  126. String useFileName = fileName;
  127. int faceIdx = 0;
  128. int atPos = (int)useFileName.IndexOf('@', 1);
  129. if (atPos != -1)
  130. {
  131. faceIdx = atoi(useFileName.c_str() + atPos + 1);
  132. useFileName.RemoveToEnd(atPos);
  133. }
  134. if (isMemory)
  135. {
  136. FT_New_Memory_Face(gFTLibrary, (FT_Byte*)memPtr, memLen, faceIdx, &ftFace);
  137. }
  138. else
  139. {
  140. FT_New_Face(gFTLibrary, useFileName.c_str(), faceIdx, &ftFace);
  141. }
  142. face->mFTFace = ftFace;
  143. }
  144. else
  145. {
  146. face = *facePtr;
  147. }
  148. if (face->mFTFace == NULL)
  149. return false;
  150. mFace = face;
  151. FTFontManager::FaceSize** faceSizePtr = NULL;
  152. if (face->mFaceSizes.TryAdd(pointSize, NULL, &faceSizePtr))
  153. {
  154. //OutputDebugStrF("Created face %s %f\n", fileName.c_str(), pointSize);
  155. mFaceSize = new FTFontManager::FaceSize();
  156. *faceSizePtr = mFaceSize;
  157. FT_Size ftSize = NULL;
  158. FT_New_Size(mFace->mFTFace, &ftSize);
  159. FT_Activate_Size(ftSize);
  160. auto error = FT_Set_Char_Size(mFace->mFTFace, 0, (int)(pointSize * 64), 72, 72);
  161. mFaceSize->mFace = mFace;
  162. mFaceSize->mFTSize = ftSize;
  163. mFaceSize->mPointSize = pointSize;
  164. }
  165. else
  166. {
  167. mFaceSize = *faceSizePtr;
  168. }
  169. mFaceSize->mRefCount++;
  170. mHeight = mFaceSize->mFTSize->metrics.height / 64;
  171. mAscent = mFaceSize->mFTSize->metrics.ascender / 64;
  172. mDescent = mFaceSize->mFTSize->metrics.descender / 64;
  173. mMaxAdvance = mFaceSize->mFTSize->metrics.max_advance / 64;
  174. return true;
  175. }
  176. TextureSegment* BF_CALLTYPE Gfx_CreateTextureSegment(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight);
  177. FTFontManager::Glyph* FTFont::AllocGlyph(int charCode, bool allowDefault)
  178. {
  179. FT_Activate_Size(mFaceSize->mFTSize);
  180. int glyph_index = FT_Get_Char_Index(mFace->mFTFace, charCode);
  181. if ((glyph_index == 0) && (!allowDefault))
  182. return NULL;
  183. auto error = FT_Load_Glyph(mFace->mFTFace, glyph_index, FT_LOAD_NO_BITMAP);
  184. if (error != FT_Err_Ok)
  185. return NULL;
  186. error = FT_Render_Glyph(mFace->mFTFace->glyph, FT_RENDER_MODE_NORMAL);
  187. if (error != FT_Err_Ok)
  188. return NULL;
  189. auto& bitmap = mFace->mFTFace->glyph->bitmap;
  190. if ((bitmap.rows > FT_PAGE_HEIGHT) || (bitmap.width > FT_PAGE_WIDTH))
  191. {
  192. return NULL;
  193. }
  194. FTFontManager::Page* page = NULL;
  195. if (!gFTFontManager.mPages.empty())
  196. {
  197. page = gFTFontManager.mPages.back();
  198. if (page->mCurX + (int)bitmap.width > page->mTexture->mWidth)
  199. {
  200. // Move down to next row
  201. page->mCurX = 0;
  202. page->mCurY += page->mMaxRowHeight;
  203. page->mMaxRowHeight = 0;
  204. }
  205. if (page->mCurY + (int)bitmap.rows > page->mTexture->mHeight)
  206. {
  207. // Doesn't fit
  208. page = NULL;
  209. }
  210. }
  211. if (page == NULL)
  212. {
  213. page = new FTFontManager::Page();
  214. gFTFontManager.mPages.push_back(page);
  215. }
  216. //auto glyph = new FTFontManager::Glyph();
  217. static FTFontManager::Glyph staticGlyph;
  218. auto glyph = &staticGlyph;
  219. auto ftFace = mFace->mFTFace;
  220. glyph->mXAdvance = ftFace->glyph->advance.x / 64;
  221. glyph->mXOffset = ftFace->glyph->bitmap_left;
  222. glyph->mYOffset = ftFace->size->metrics.ascender / 64 - ftFace->glyph->bitmap_top;
  223. glyph->mPage = page;
  224. glyph->mX = page->mCurX;
  225. glyph->mY = page->mCurY;
  226. glyph->mWidth = bitmap.width;
  227. glyph->mHeight = bitmap.rows;
  228. if (page->mTexture == NULL)
  229. {
  230. ImageData* img = new ImageData();
  231. img->CreateNew(FT_PAGE_WIDTH, FT_PAGE_HEIGHT);
  232. auto* bits = img->mBits;
  233. for (int i = 0; i < FT_PAGE_HEIGHT * FT_PAGE_WIDTH; i++)
  234. {
  235. if (i % 3 == 0)
  236. bits[i] = 0xFFFF0000;
  237. else if (i % 3 == 1)
  238. bits[i] = 0xFF00FF00;
  239. else
  240. bits[i] = 0xFF0000FF;
  241. }
  242. page->mTexture = gBFApp->mRenderDevice->LoadTexture(img, TextureFlag_NoPremult);
  243. img->Deref();
  244. }
  245. if (bitmap.width > 0)
  246. {
  247. ImageData* img = new ImageData();
  248. img->CreateNew(bitmap.width, bitmap.rows);
  249. auto* bits = img->mBits;
  250. int width = img->mWidth;
  251. for (int y = 0; y < (int)bitmap.rows; y++)
  252. {
  253. for (int x = 0; x < (int)bitmap.width; x++)
  254. {
  255. uint8 val = bitmap.buffer[y * bitmap.pitch + x];
  256. uint8 whiteVal = gFTFontManager.mWhiteTab[val];
  257. uint8 blackVal = gFTFontManager.mBlackTab[val];
  258. bits[y * width + x] = ((int32)whiteVal << 24) |
  259. ((int32)blackVal) | ((int32)0xFF << 8) | ((int32)0xFF << 16);
  260. }
  261. }
  262. page->mTexture->Blt(img, page->mCurX, page->mCurY);
  263. img->Deref();
  264. }
  265. page->mCurX += bitmap.width;
  266. page->mMaxRowHeight = std::max(page->mMaxRowHeight, (int)bitmap.rows);
  267. auto texture = page->mTexture;
  268. texture->AddRef();
  269. TextureSegment* textureSegment = new TextureSegment();
  270. textureSegment->mTexture = texture;
  271. textureSegment->mU1 = (glyph->mX / (float)texture->mWidth);
  272. textureSegment->mV1 = (glyph->mY / (float)texture->mHeight);
  273. textureSegment->mU2 = ((glyph->mX + glyph->mWidth) / (float)texture->mWidth);
  274. textureSegment->mV2 = ((glyph->mY + glyph->mHeight) / (float)texture->mHeight);
  275. textureSegment->mScaleX = (float)abs(glyph->mWidth);
  276. textureSegment->mScaleY = (float)abs(glyph->mHeight);
  277. glyph->mTextureSegment = textureSegment;
  278. return glyph;
  279. }
  280. int FTFont::GetKerning(int charA, int charB)
  281. {
  282. FT_Activate_Size(mFaceSize->mFTSize);
  283. FT_Vector kerning;
  284. int glyph_indexA = FT_Get_Char_Index(mFace->mFTFace, charA);
  285. int glyph_indexB = FT_Get_Char_Index(mFace->mFTFace, charB);
  286. FT_Get_Kerning(mFace->mFTFace, glyph_indexA, glyph_indexB, FT_KERNING_DEFAULT, &kerning);
  287. return kerning.x / 64;
  288. }
  289. void FTFont::Release(bool cacheRetain)
  290. {
  291. Dispose(cacheRetain);
  292. delete this;
  293. }
  294. //////////////////////////////////////////////////////////////////////////
  295. BF_EXPORT FTFont* BF_CALLTYPE FTFont_Load(const char* fileName, float pointSize)
  296. {
  297. auto ftFont = new FTFont();
  298. if (!ftFont->Load(fileName, pointSize))
  299. {
  300. delete ftFont;
  301. return NULL;
  302. }
  303. return ftFont;
  304. }
  305. BF_EXPORT void BF_CALLTYPE FTFont_ClearCache()
  306. {
  307. FTFontManager::ClearCache();
  308. }
  309. BF_EXPORT void BF_CALLTYPE FTFont_Delete(FTFont* ftFont, bool cacheRetain)
  310. {
  311. ftFont->Release(cacheRetain);
  312. }
  313. BF_EXPORT FTFontManager::Glyph* BF_CALLTYPE FTFont_AllocGlyph(FTFont* ftFont, int charCode, bool allowDefault)
  314. {
  315. return ftFont->AllocGlyph(charCode, allowDefault);
  316. }
  317. BF_EXPORT int BF_CALLTYPE FTFont_GetKerning(FTFont* ftFont, int charCodeA, int charCodeB)
  318. {
  319. auto kerning = ftFont->GetKerning(charCodeA, charCodeB);
  320. return kerning;
  321. }