2
0

import-font.cpp 12 KB

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