import-font.cpp 9.6 KB

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