mirror of https://github.com/Chlumsky/msdfgen.git
Variable fonts (#164)
Co-authored-by: themancalledjakob <github@jrkb.land>
This commit is contained in:
parent
3300ab6869
commit
99559ac1db
|
|
@ -1,22 +1,26 @@
|
|||
|
||||
#include "import-font.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <queue>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <ft2build.h>
|
||||
#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 F16DOT16_TO_DOUBLE(x) (1/65536.*double(x))
|
||||
#define DOUBLE_TO_F16DOT16(x) FT_Fixed(65536.*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 setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, double coordinate);
|
||||
friend bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
|
||||
|
||||
FT_Library library;
|
||||
|
||||
|
|
@ -34,6 +38,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 setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, double coordinate);
|
||||
friend bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
|
||||
|
||||
FT_Face face;
|
||||
bool ownership;
|
||||
|
|
@ -215,4 +221,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 setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, double coordinate) {
|
||||
bool success = false;
|
||||
if (font->face->face_flags&FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
FT_MM_Var *master = NULL;
|
||||
if (FT_Get_MM_Var(font->face, &master))
|
||||
return false;
|
||||
if (master && master->num_axis) {
|
||||
std::vector<FT_Fixed> coords(master->num_axis);
|
||||
if (!FT_Get_Var_Design_Coordinates(font->face, FT_UInt(coords.size()), &coords[0])) {
|
||||
for (FT_UInt i = 0; i < master->num_axis; ++i) {
|
||||
if (!strcmp(name, master->axis[i].name)) {
|
||||
coords[i] = DOUBLE_TO_F16DOT16(coordinate);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FT_Set_Var_Design_Coordinates(font->face, FT_UInt(coords.size()), &coords[0]))
|
||||
success = false;
|
||||
}
|
||||
FT_Done_MM_Var(library->library, master);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font) {
|
||||
if (font->face->face_flags&FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
FT_MM_Var *master = NULL;
|
||||
if (FT_Get_MM_Var(font->face, &master))
|
||||
return false;
|
||||
axes.resize(master->num_axis);
|
||||
for (FT_UInt i = 0; i < master->num_axis; i++) {
|
||||
FontVariationAxis &axis = axes[i];
|
||||
axis.name = master->axis[i].name;
|
||||
axis.minValue = master->axis[i].minimum;
|
||||
axis.maxValue = master->axis[i].maximum;
|
||||
axis.defaultValue = master->axis[i].def;
|
||||
}
|
||||
FT_Done_MM_Var(library->library, master);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,18 @@ struct FontMetrics {
|
|||
double underlineY, underlineThickness;
|
||||
};
|
||||
|
||||
/// A structure to model a given axis of a variable font.
|
||||
struct FontVariationAxis {
|
||||
/// The name of the variation axis.
|
||||
const char *name;
|
||||
/// The axis's minimum coordinate value.
|
||||
double minValue;
|
||||
/// The axis's maximum coordinate value.
|
||||
double maxValue;
|
||||
/// The axis's default coordinate value. FreeType computes meaningful default values for Adobe MM fonts.
|
||||
double defaultValue;
|
||||
};
|
||||
|
||||
/// Initializes the FreeType library.
|
||||
FreetypeHandle * initializeFreetype();
|
||||
/// Deinitializes the FreeType library.
|
||||
|
|
@ -62,5 +74,9 @@ 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 a single variation axis of a variable font.
|
||||
bool setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, double coordinate);
|
||||
/// Lists names and ranges of variation axes of a variable font.
|
||||
bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
|
||||
|
||||
}
|
||||
|
|
|
|||
38
main.cpp
38
main.cpp
|
|
@ -13,6 +13,7 @@
|
|||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "msdfgen.h"
|
||||
#include "msdfgen-ext.h"
|
||||
|
|
@ -135,6 +136,29 @@ static void parseColoring(Shape &shape, const char *edgeAssignment) {
|
|||
}
|
||||
}
|
||||
|
||||
static FontHandle * loadVarFont(FreetypeHandle *library, const char *filename) {
|
||||
std::string buffer;
|
||||
while (*filename && *filename != '?')
|
||||
buffer.push_back(*filename++);
|
||||
FontHandle *font = loadFont(library, buffer.c_str());
|
||||
if (*filename++ == '?') {
|
||||
do {
|
||||
buffer.clear();
|
||||
while (*filename && *filename != '=')
|
||||
buffer.push_back(*filename++);
|
||||
if (*filename == '=') {
|
||||
double value = 0;
|
||||
int skip = 0;
|
||||
if (sscanf(++filename, "%lf%n", &value, &skip) == 1) {
|
||||
setFontVariationAxis(library, font, buffer.c_str(), value);
|
||||
filename += skip;
|
||||
}
|
||||
}
|
||||
} while (*filename++ == '&');
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
template <int N>
|
||||
static void invertColor(const BitmapRef<float, N> &bitmap) {
|
||||
const float *end = bitmap.pixels+N*bitmap.width*bitmap.height;
|
||||
|
|
@ -295,6 +319,8 @@ static const char *helpText =
|
|||
"\tReads text shape description from the standard input.\n"
|
||||
" -svg <filename.svg>\n"
|
||||
"\tLoads the last vector path found in the specified SVG file.\n"
|
||||
" -varfont <filename and variables> <character code>\n"
|
||||
"\tLoads a single glyph from a variable font. Specify variable values as x.ttf?var1=0.5&var2=1\n"
|
||||
"\n"
|
||||
// Keep alphabetical order!
|
||||
"OPTIONS\n"
|
||||
|
|
@ -408,6 +434,7 @@ int main(int argc, const char * const *argv) {
|
|||
NONE,
|
||||
SVG,
|
||||
FONT,
|
||||
VAR_FONT,
|
||||
DESCRIPTION_ARG,
|
||||
DESCRIPTION_STDIN,
|
||||
DESCRIPTION_FILE
|
||||
|
|
@ -496,8 +523,8 @@ int main(int argc, const char * const *argv) {
|
|||
argPos += 2;
|
||||
continue;
|
||||
}
|
||||
ARG_CASE("-font", 2) {
|
||||
inputType = FONT;
|
||||
//ARG_CASE -font, -varfont
|
||||
if (argPos+2 < argc && ((!strcmp(arg, "-font") && (inputType = FONT)) || (!strcmp(arg, "-varfont") && (inputType = VAR_FONT)))) {
|
||||
input = argv[argPos+1];
|
||||
const char *charArg = argv[argPos+2];
|
||||
unsigned gi;
|
||||
|
|
@ -840,12 +867,13 @@ int main(int argc, const char * const *argv) {
|
|||
ABORT("Failed to load shape from SVG file.");
|
||||
break;
|
||||
}
|
||||
case FONT: {
|
||||
case FONT: case VAR_FONT: {
|
||||
if (!glyphIndexSpecified && !unicode)
|
||||
ABORT("No character specified! Use -font <file.ttf/otf> <character code>. Character code can be a Unicode index (65, 0x41), a character in apostrophes ('A'), or a glyph index prefixed by g (g36, g0x24).");
|
||||
FreetypeHandle *ft = initializeFreetype();
|
||||
if (!ft) return -1;
|
||||
FontHandle *font = loadFont(ft, input);
|
||||
if (!ft)
|
||||
return -1;
|
||||
FontHandle *font = inputType == VAR_FONT ? loadVarFont(ft, input) : loadFont(ft, input);
|
||||
if (!font) {
|
||||
deinitializeFreetype(ft);
|
||||
ABORT("Failed to load font file.");
|
||||
|
|
|
|||
Loading…
Reference in New Issue