import-font.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "import-font.h"
  2. #include <cstring>
  3. #include <vector>
  4. #include <ft2build.h>
  5. #include FT_FREETYPE_H
  6. #include FT_OUTLINE_H
  7. #ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
  8. #include FT_MULTIPLE_MASTERS_H
  9. #endif
  10. namespace msdfgen {
  11. #define F26DOT6_TO_REAL(x) (::msdfgen::real(1)/::msdfgen::real(64)*::msdfgen::real(x))
  12. #define F16DOT16_TO_REAL(x) (::msdfgen::real(1)/::msdfgen::real(65536)*::msdfgen::real(x))
  13. #define REAL_TO_F16DOT16(x) FT_Fixed(::msdfgen::real(65536)*::msdfgen::real(x))
  14. class FreetypeHandle {
  15. friend FreetypeHandle *initializeFreetype();
  16. friend void deinitializeFreetype(FreetypeHandle *library);
  17. friend FontHandle *loadFont(FreetypeHandle *library, const char *filename);
  18. friend FontHandle *loadFontData(FreetypeHandle *library, const byte *data, int length);
  19. #ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
  20. friend bool setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, real coordinate);
  21. friend bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
  22. #endif
  23. FT_Library library;
  24. };
  25. class FontHandle {
  26. friend FontHandle *adoptFreetypeFont(FT_Face ftFace);
  27. friend FontHandle *loadFont(FreetypeHandle *library, const char *filename);
  28. friend FontHandle *loadFontData(FreetypeHandle *library, const byte *data, int length);
  29. friend void destroyFont(FontHandle *font);
  30. friend bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
  31. friend bool getFontWhitespaceWidth(real &spaceAdvance, real &tabAdvance, FontHandle *font);
  32. friend bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode);
  33. friend bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, real *advance);
  34. friend bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, real *advance);
  35. friend bool getKerning(real &output, FontHandle *font, GlyphIndex glyphIndex1, GlyphIndex glyphIndex2);
  36. friend bool getKerning(real &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2);
  37. #ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
  38. friend bool setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, real coordinate);
  39. friend bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
  40. #endif
  41. FT_Face face;
  42. bool ownership;
  43. };
  44. struct FtContext {
  45. Point2 position;
  46. Shape *shape;
  47. Contour *contour;
  48. };
  49. static Point2 ftPoint2(const FT_Vector &vector) {
  50. return Point2(F26DOT6_TO_REAL(vector.x), F26DOT6_TO_REAL(vector.y));
  51. }
  52. static int ftMoveTo(const FT_Vector *to, void *user) {
  53. FtContext *context = reinterpret_cast<FtContext *>(user);
  54. if (!(context->contour && context->contour->edges.empty()))
  55. context->contour = &context->shape->addContour();
  56. context->position = ftPoint2(*to);
  57. return 0;
  58. }
  59. static int ftLineTo(const FT_Vector *to, void *user) {
  60. FtContext *context = reinterpret_cast<FtContext *>(user);
  61. Point2 endpoint = ftPoint2(*to);
  62. if (endpoint != context->position) {
  63. context->contour->addEdge(new LinearSegment(context->position, endpoint));
  64. context->position = endpoint;
  65. }
  66. return 0;
  67. }
  68. static int ftConicTo(const FT_Vector *control, const FT_Vector *to, void *user) {
  69. FtContext *context = reinterpret_cast<FtContext *>(user);
  70. context->contour->addEdge(new QuadraticSegment(context->position, ftPoint2(*control), ftPoint2(*to)));
  71. context->position = ftPoint2(*to);
  72. return 0;
  73. }
  74. static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, void *user) {
  75. FtContext *context = reinterpret_cast<FtContext *>(user);
  76. context->contour->addEdge(new CubicSegment(context->position, ftPoint2(*control1), ftPoint2(*control2), ftPoint2(*to)));
  77. context->position = ftPoint2(*to);
  78. return 0;
  79. }
  80. GlyphIndex::GlyphIndex(unsigned index) : index(index) { }
  81. unsigned GlyphIndex::getIndex() const {
  82. return index;
  83. }
  84. FreetypeHandle *initializeFreetype() {
  85. FreetypeHandle *handle = new FreetypeHandle;
  86. FT_Error error = FT_Init_FreeType(&handle->library);
  87. if (error) {
  88. delete handle;
  89. return NULL;
  90. }
  91. return handle;
  92. }
  93. void deinitializeFreetype(FreetypeHandle *library) {
  94. FT_Done_FreeType(library->library);
  95. delete library;
  96. }
  97. FontHandle *adoptFreetypeFont(FT_Face ftFace) {
  98. FontHandle *handle = new FontHandle;
  99. handle->face = ftFace;
  100. handle->ownership = false;
  101. return handle;
  102. }
  103. FT_Error readFreetypeOutline(Shape &output, FT_Outline *outline) {
  104. output.contours.clear();
  105. output.inverseYAxis = false;
  106. FtContext context = { };
  107. context.shape = &output;
  108. FT_Outline_Funcs ftFunctions;
  109. ftFunctions.move_to = &ftMoveTo;
  110. ftFunctions.line_to = &ftLineTo;
  111. ftFunctions.conic_to = &ftConicTo;
  112. ftFunctions.cubic_to = &ftCubicTo;
  113. ftFunctions.shift = 0;
  114. ftFunctions.delta = 0;
  115. FT_Error error = FT_Outline_Decompose(outline, &ftFunctions, &context);
  116. if (!output.contours.empty() && output.contours.back().edges.empty())
  117. output.contours.pop_back();
  118. return error;
  119. }
  120. FontHandle *loadFont(FreetypeHandle *library, const char *filename) {
  121. if (!library)
  122. return NULL;
  123. FontHandle *handle = new FontHandle;
  124. FT_Error error = FT_New_Face(library->library, filename, 0, &handle->face);
  125. if (error) {
  126. delete handle;
  127. return NULL;
  128. }
  129. handle->ownership = true;
  130. return handle;
  131. }
  132. FontHandle *loadFontData(FreetypeHandle *library, const byte *data, int length) {
  133. if (!library)
  134. return NULL;
  135. FontHandle *handle = new FontHandle;
  136. FT_Error error = FT_New_Memory_Face(library->library, data, length, 0, &handle->face);
  137. if (error) {
  138. delete handle;
  139. return NULL;
  140. }
  141. handle->ownership = true;
  142. return handle;
  143. }
  144. void destroyFont(FontHandle *font) {
  145. if (font->ownership)
  146. FT_Done_Face(font->face);
  147. delete font;
  148. }
  149. bool getFontMetrics(FontMetrics &metrics, FontHandle *font) {
  150. metrics.emSize = F26DOT6_TO_REAL(font->face->units_per_EM);
  151. metrics.ascenderY = F26DOT6_TO_REAL(font->face->ascender);
  152. metrics.descenderY = F26DOT6_TO_REAL(font->face->descender);
  153. metrics.lineHeight = F26DOT6_TO_REAL(font->face->height);
  154. metrics.underlineY = F26DOT6_TO_REAL(font->face->underline_position);
  155. metrics.underlineThickness = F26DOT6_TO_REAL(font->face->underline_thickness);
  156. return true;
  157. }
  158. bool getFontWhitespaceWidth(real &spaceAdvance, real &tabAdvance, FontHandle *font) {
  159. FT_Error error = FT_Load_Char(font->face, ' ', FT_LOAD_NO_SCALE);
  160. if (error)
  161. return false;
  162. spaceAdvance = F26DOT6_TO_REAL(font->face->glyph->advance.x);
  163. error = FT_Load_Char(font->face, '\t', FT_LOAD_NO_SCALE);
  164. if (error)
  165. return false;
  166. tabAdvance = F26DOT6_TO_REAL(font->face->glyph->advance.x);
  167. return true;
  168. }
  169. bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode) {
  170. glyphIndex = GlyphIndex(FT_Get_Char_Index(font->face, unicode));
  171. return glyphIndex.getIndex() != 0;
  172. }
  173. bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, real *advance) {
  174. if (!font)
  175. return false;
  176. FT_Error error = FT_Load_Glyph(font->face, glyphIndex.getIndex(), FT_LOAD_NO_SCALE);
  177. if (error)
  178. return false;
  179. if (advance)
  180. *advance = F26DOT6_TO_REAL(font->face->glyph->advance.x);
  181. return !readFreetypeOutline(output, &font->face->glyph->outline);
  182. }
  183. bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, real *advance) {
  184. return loadGlyph(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode)), advance);
  185. }
  186. bool getKerning(real &output, FontHandle *font, GlyphIndex glyphIndex1, GlyphIndex glyphIndex2) {
  187. FT_Vector kerning;
  188. if (FT_Get_Kerning(font->face, glyphIndex1.getIndex(), glyphIndex2.getIndex(), FT_KERNING_UNSCALED, &kerning)) {
  189. output = 0;
  190. return false;
  191. }
  192. output = F26DOT6_TO_REAL(kerning.x);
  193. return true;
  194. }
  195. bool getKerning(real &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2) {
  196. return getKerning(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode1)), GlyphIndex(FT_Get_Char_Index(font->face, unicode2)));
  197. }
  198. #ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
  199. bool setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, real coordinate) {
  200. bool success = false;
  201. if (font->face->face_flags&FT_FACE_FLAG_MULTIPLE_MASTERS) {
  202. FT_MM_Var *master = NULL;
  203. if (FT_Get_MM_Var(font->face, &master))
  204. return false;
  205. if (master && master->num_axis) {
  206. std::vector<FT_Fixed> coords(master->num_axis);
  207. if (!FT_Get_Var_Design_Coordinates(font->face, FT_UInt(coords.size()), &coords[0])) {
  208. for (FT_UInt i = 0; i < master->num_axis; ++i) {
  209. if (!strcmp(name, master->axis[i].name)) {
  210. coords[i] = REAL_TO_F16DOT16(coordinate);
  211. success = true;
  212. break;
  213. }
  214. }
  215. }
  216. if (FT_Set_Var_Design_Coordinates(font->face, FT_UInt(coords.size()), &coords[0]))
  217. success = false;
  218. }
  219. FT_Done_MM_Var(library->library, master);
  220. }
  221. return success;
  222. }
  223. bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font) {
  224. if (font->face->face_flags&FT_FACE_FLAG_MULTIPLE_MASTERS) {
  225. FT_MM_Var *master = NULL;
  226. if (FT_Get_MM_Var(font->face, &master))
  227. return false;
  228. axes.resize(master->num_axis);
  229. for (FT_UInt i = 0; i < master->num_axis; ++i) {
  230. FontVariationAxis &axis = axes[i];
  231. axis.name = master->axis[i].name;
  232. axis.minValue = F16DOT16_TO_REAL(master->axis[i].minimum);
  233. axis.maxValue = F16DOT16_TO_REAL(master->axis[i].maximum);
  234. axis.defaultValue = F16DOT16_TO_REAL(master->axis[i].def);
  235. }
  236. FT_Done_MM_Var(library->library, master);
  237. return true;
  238. }
  239. return false;
  240. }
  241. #endif
  242. }