import-font.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "import-font.h"
  2. #include <cstdlib>
  3. #include <queue>
  4. #include <ft2build.h>
  5. #include FT_FREETYPE_H
  6. #include FT_OUTLINE_H
  7. #ifdef _WIN32
  8. #pragma comment(lib, "freetype.lib")
  9. #endif
  10. namespace msdfgen {
  11. #define REQUIRE(cond) { if (!(cond)) return false; }
  12. class FreetypeHandle {
  13. friend FreetypeHandle * initializeFreetype();
  14. friend void deinitializeFreetype(FreetypeHandle *library);
  15. friend FontHandle * loadFont(FreetypeHandle *library, const char *filename);
  16. FT_Library library;
  17. };
  18. class FontHandle {
  19. friend FontHandle * loadFont(FreetypeHandle *library, const char *filename);
  20. friend void destroyFont(FontHandle *font);
  21. friend bool getFontScale(double &output, FontHandle *font);
  22. friend bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font);
  23. friend bool loadGlyph(Shape &output, FontHandle *font, int unicode, double *advance);
  24. friend bool getKerning(double &output, FontHandle *font, int unicode1, int unicode2);
  25. FT_Face face;
  26. };
  27. struct FtContext {
  28. Point2 position;
  29. Shape *shape;
  30. Contour *contour;
  31. };
  32. static Point2 ftPoint2(const FT_Vector &vector) {
  33. return Point2(vector.x/64., vector.y/64.);
  34. }
  35. static int ftMoveTo(const FT_Vector *to, void *user) {
  36. FtContext *context = reinterpret_cast<FtContext *>(user);
  37. context->contour = &context->shape->addContour();
  38. context->position = ftPoint2(*to);
  39. return 0;
  40. }
  41. static int ftLineTo(const FT_Vector *to, void *user) {
  42. FtContext *context = reinterpret_cast<FtContext *>(user);
  43. context->contour->addEdge(new LinearSegment(context->position, ftPoint2(*to)));
  44. context->position = ftPoint2(*to);
  45. return 0;
  46. }
  47. static int ftConicTo(const FT_Vector *control, const FT_Vector *to, void *user) {
  48. FtContext *context = reinterpret_cast<FtContext *>(user);
  49. context->contour->addEdge(new QuadraticSegment(context->position, ftPoint2(*control), ftPoint2(*to)));
  50. context->position = ftPoint2(*to);
  51. return 0;
  52. }
  53. static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, void *user) {
  54. FtContext *context = reinterpret_cast<FtContext *>(user);
  55. context->contour->addEdge(new CubicSegment(context->position, ftPoint2(*control1), ftPoint2(*control2), ftPoint2(*to)));
  56. context->position = ftPoint2(*to);
  57. return 0;
  58. }
  59. FreetypeHandle * initializeFreetype() {
  60. FreetypeHandle *handle = new FreetypeHandle;
  61. FT_Error error = FT_Init_FreeType(&handle->library);
  62. if (error) {
  63. delete handle;
  64. return NULL;
  65. }
  66. return handle;
  67. }
  68. void deinitializeFreetype(FreetypeHandle *library) {
  69. FT_Done_FreeType(library->library);
  70. delete library;
  71. }
  72. FontHandle * loadFont(FreetypeHandle *library, const char *filename) {
  73. if (!library)
  74. return NULL;
  75. FontHandle *handle = new FontHandle;
  76. FT_Error error = FT_New_Face(library->library, filename, 0, &handle->face);
  77. if (error) {
  78. delete handle;
  79. return NULL;
  80. }
  81. return handle;
  82. }
  83. void destroyFont(FontHandle *font) {
  84. FT_Done_Face(font->face);
  85. delete font;
  86. }
  87. bool getFontScale(double &output, FontHandle *font) {
  88. output = font->face->units_per_EM/64.;
  89. return true;
  90. }
  91. bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font) {
  92. FT_Error error = FT_Load_Char(font->face, ' ', FT_LOAD_NO_SCALE);
  93. if (error)
  94. return false;
  95. spaceAdvance = font->face->glyph->advance.x/64.;
  96. error = FT_Load_Char(font->face, '\t', FT_LOAD_NO_SCALE);
  97. if (error)
  98. return false;
  99. tabAdvance = font->face->glyph->advance.x/64.;
  100. return true;
  101. }
  102. bool loadGlyph(Shape &output, FontHandle *font, int unicode, double *advance) {
  103. if (!font)
  104. return false;
  105. FT_Error error = FT_Load_Char(font->face, unicode, FT_LOAD_NO_SCALE);
  106. if (error)
  107. return false;
  108. output.contours.clear();
  109. output.inverseYAxis = false;
  110. if (advance)
  111. *advance = font->face->glyph->advance.x/64.;
  112. FtContext context = { };
  113. context.shape = &output;
  114. FT_Outline_Funcs ftFunctions;
  115. ftFunctions.move_to = &ftMoveTo;
  116. ftFunctions.line_to = &ftLineTo;
  117. ftFunctions.conic_to = &ftConicTo;
  118. ftFunctions.cubic_to = &ftCubicTo;
  119. ftFunctions.shift = 0;
  120. ftFunctions.delta = 0;
  121. error = FT_Outline_Decompose(&font->face->glyph->outline, &ftFunctions, &context);
  122. if (error)
  123. return false;
  124. return true;
  125. }
  126. bool getKerning(double &output, FontHandle *font, int unicode1, int unicode2) {
  127. FT_Vector kerning;
  128. if (FT_Get_Kerning(font->face, FT_Get_Char_Index(font->face, unicode1), FT_Get_Char_Index(font->face, unicode2), FT_KERNING_UNSCALED, &kerning)) {
  129. output = 0;
  130. return false;
  131. }
  132. output = kerning.x/64.;
  133. return true;
  134. }
  135. }