From 4aba809e947fca4f043ded976f55178d28d9cf06 Mon Sep 17 00:00:00 2001 From: themancalledjakob Date: Fri, 9 Sep 2022 09:05:02 +0200 Subject: [PATCH] Adding setVariationAxis for variable fonts (#158) --- ext/import-font.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++ ext/import-font.h | 15 +++++++++++++ 2 files changed, 66 insertions(+) diff --git a/ext/import-font.cpp b/ext/import-font.cpp index 5995261..ff85df8 100644 --- a/ext/import-font.cpp +++ b/ext/import-font.cpp @@ -6,17 +6,22 @@ #include #include FT_FREETYPE_H #include FT_OUTLINE_H +#include FT_MULTIPLE_MASTERS_H namespace msdfgen { #define REQUIRE(cond) { if (!(cond)) return false; } #define F26DOT6_TO_DOUBLE(x) (1/64.*double(x)) +#define DOUBLE_TO_F16DOT16(x) (FT_Fixed(x*65536.)) +#define F16DOT16_TO_DOUBLE(x) (1/65536.*double(x)) class FreetypeHandle { friend FreetypeHandle * initializeFreetype(); friend void deinitializeFreetype(FreetypeHandle *library); friend FontHandle * loadFont(FreetypeHandle *library, const char *filename); friend FontHandle * loadFontData(FreetypeHandle *library, const byte *data, int length); + friend bool setVariationAxis(FontHandle *font, FreetypeHandle *library, const char *axisname, double coordinate); + friend bool getVariationAxes(std::vector &axes, FontHandle *font, FreetypeHandle *library); FT_Library library; @@ -34,6 +39,8 @@ class FontHandle { friend bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance); friend bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex1, GlyphIndex glyphIndex2); friend bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2); + friend bool setVariationAxis(FontHandle *font, FreetypeHandle *library, const char *axisname, double coordinate); + friend bool getVariationAxes(std::vector &axes, FontHandle *font, FreetypeHandle *library); FT_Face face; bool ownership; @@ -215,4 +222,48 @@ bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t return getKerning(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode1)), GlyphIndex(FT_Get_Char_Index(font->face, unicode2))); } +bool setVariationAxis(FontHandle *font, FreetypeHandle *library, const char *name, double coordinate) { + bool success = false; + if (font->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { + FT_MM_Var *amaster; + FT_Get_MM_Var(font->face, &amaster); + + std::vector coords; + coords.resize(amaster->num_axis); + + FT_Get_Var_Design_Coordinates(font->face, coords.size(), coords.data()); + for (FT_UInt i = 0; i < amaster->num_axis; i++) { + int strdiff = strcmp(name,amaster->axis[i].name); + if (strdiff == 0) { + coords[i] = DOUBLE_TO_F16DOT16(coordinate); + success = true; + break; + } + } + FT_Set_Var_Design_Coordinates(font->face, coords.size(), coords.data()); + FT_Done_MM_Var(library->library, amaster); + } + return success; +} + +bool getVariationAxes(std::vector &axes, FontHandle *font, FreetypeHandle *library) { + if (font->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { + FT_MM_Var *amaster; + FT_Get_MM_Var(font->face, &amaster); + + for (FT_UInt i = 0; i < amaster->num_axis; i++) { + FontVariationAxis axis{ + amaster->axis[i].name, + F16DOT16_TO_DOUBLE(amaster->axis[i].minimum), + F16DOT16_TO_DOUBLE(amaster->axis[i].def), + F16DOT16_TO_DOUBLE(amaster->axis[i].maximum) + }; + axes.push_back(axis); + } + FT_Done_MM_Var(library->library, amaster); + return true; + } + return false; +} + } diff --git a/ext/import-font.h b/ext/import-font.h index 82859a6..9b7635b 100644 --- a/ext/import-font.h +++ b/ext/import-font.h @@ -35,6 +35,18 @@ struct FontMetrics { double underlineY, underlineThickness; }; +/// A structure to model a given axis for variation fonts. +struct FontVariationAxis { + /// The name of the variation axis. + const char * name; + /// The axis's minimum design coordinate. + double minimum; + /// The axis's default design coordinate. FreeType computes meaningful default values for Adobe MM fonts. + double def; + /// The axis's maximum design coordinate. + double maximum; +}; + /// Initializes the FreeType library. FreetypeHandle * initializeFreetype(); /// Deinitializes the FreeType library. @@ -62,5 +74,8 @@ bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advan /// Outputs the kerning distance adjustment between two specific glyphs. bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex1, GlyphIndex glyphIndex2); bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2); +/// Sets variation axis of variable font. +bool setVariationAxis(FontHandle *font, FreetypeHandle *library, const char *name, double coordinate); +bool getVariationAxes(std::vector &axes, FontHandle *font, FreetypeHandle *library); }