mirror of https://github.com/Chlumsky/msdfgen.git
Fix for incorrect font coordinate scaling
This commit is contained in:
parent
6d252a7dc3
commit
bc9f02e156
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
namespace msdfgen {
|
namespace msdfgen {
|
||||||
|
|
||||||
#define F26DOT6_TO_DOUBLE(x) (1/64.*double(x))
|
|
||||||
#define F16DOT16_TO_DOUBLE(x) (1/65536.*double(x))
|
#define F16DOT16_TO_DOUBLE(x) (1/65536.*double(x))
|
||||||
#define DOUBLE_TO_F16DOT16(x) FT_Fixed(65536.*x)
|
#define DOUBLE_TO_F16DOT16(x) FT_Fixed(65536.*x)
|
||||||
|
|
||||||
|
|
@ -35,14 +34,14 @@ class FontHandle {
|
||||||
friend FontHandle *loadFont(FreetypeHandle *library, const char *filename);
|
friend FontHandle *loadFont(FreetypeHandle *library, const char *filename);
|
||||||
friend FontHandle *loadFontData(FreetypeHandle *library, const byte *data, int length);
|
friend FontHandle *loadFontData(FreetypeHandle *library, const byte *data, int length);
|
||||||
friend void destroyFont(FontHandle *font);
|
friend void destroyFont(FontHandle *font);
|
||||||
friend bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
|
friend bool getFontMetrics(FontMetrics &metrics, FontHandle *font, FontCoordinateScaling coordinateScaling);
|
||||||
friend bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font);
|
friend bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font, FontCoordinateScaling coordinateScaling);
|
||||||
friend bool getGlyphCount(unsigned &output, FontHandle *font);
|
friend bool getGlyphCount(unsigned &output, FontHandle *font);
|
||||||
friend bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode);
|
friend bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode);
|
||||||
friend bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *advance);
|
friend bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, FontCoordinateScaling coordinateScaling, double *outAdvance);
|
||||||
friend bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance);
|
friend bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, FontCoordinateScaling coordinateScaling, double *outAdvance);
|
||||||
friend bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex0, GlyphIndex glyphIndex1);
|
friend bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex0, GlyphIndex glyphIndex1, FontCoordinateScaling coordinateScaling);
|
||||||
friend bool getKerning(double &output, FontHandle *font, unicode_t unicode0, unicode_t unicode1);
|
friend bool getKerning(double &output, FontHandle *font, unicode_t unicode0, unicode_t unicode1, FontCoordinateScaling coordinateScaling);
|
||||||
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
||||||
friend bool setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, double coordinate);
|
friend bool setFontVariationAxis(FreetypeHandle *library, FontHandle *font, const char *name, double coordinate);
|
||||||
friend bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
|
friend bool listFontVariationAxes(std::vector<FontVariationAxis> &axes, FreetypeHandle *library, FontHandle *font);
|
||||||
|
|
@ -54,26 +53,27 @@ class FontHandle {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FtContext {
|
struct FtContext {
|
||||||
|
double scale;
|
||||||
Point2 position;
|
Point2 position;
|
||||||
Shape *shape;
|
Shape *shape;
|
||||||
Contour *contour;
|
Contour *contour;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Point2 ftPoint2(const FT_Vector &vector) {
|
static Point2 ftPoint2(const FT_Vector &vector, double scale) {
|
||||||
return Point2(F26DOT6_TO_DOUBLE(vector.x), F26DOT6_TO_DOUBLE(vector.y));
|
return Point2(scale*vector.x, scale*vector.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ftMoveTo(const FT_Vector *to, void *user) {
|
static int ftMoveTo(const FT_Vector *to, void *user) {
|
||||||
FtContext *context = reinterpret_cast<FtContext *>(user);
|
FtContext *context = reinterpret_cast<FtContext *>(user);
|
||||||
if (!(context->contour && context->contour->edges.empty()))
|
if (!(context->contour && context->contour->edges.empty()))
|
||||||
context->contour = &context->shape->addContour();
|
context->contour = &context->shape->addContour();
|
||||||
context->position = ftPoint2(*to);
|
context->position = ftPoint2(*to, context->scale);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ftLineTo(const FT_Vector *to, void *user) {
|
static int ftLineTo(const FT_Vector *to, void *user) {
|
||||||
FtContext *context = reinterpret_cast<FtContext *>(user);
|
FtContext *context = reinterpret_cast<FtContext *>(user);
|
||||||
Point2 endpoint = ftPoint2(*to);
|
Point2 endpoint = ftPoint2(*to, context->scale);
|
||||||
if (endpoint != context->position) {
|
if (endpoint != context->position) {
|
||||||
context->contour->addEdge(EdgeHolder(context->position, endpoint));
|
context->contour->addEdge(EdgeHolder(context->position, endpoint));
|
||||||
context->position = endpoint;
|
context->position = endpoint;
|
||||||
|
|
@ -83,9 +83,9 @@ static int ftLineTo(const FT_Vector *to, void *user) {
|
||||||
|
|
||||||
static int ftConicTo(const FT_Vector *control, const FT_Vector *to, void *user) {
|
static int ftConicTo(const FT_Vector *control, const FT_Vector *to, void *user) {
|
||||||
FtContext *context = reinterpret_cast<FtContext *>(user);
|
FtContext *context = reinterpret_cast<FtContext *>(user);
|
||||||
Point2 endpoint = ftPoint2(*to);
|
Point2 endpoint = ftPoint2(*to, context->scale);
|
||||||
if (endpoint != context->position) {
|
if (endpoint != context->position) {
|
||||||
context->contour->addEdge(EdgeHolder(context->position, ftPoint2(*control), endpoint));
|
context->contour->addEdge(EdgeHolder(context->position, ftPoint2(*control, context->scale), endpoint));
|
||||||
context->position = endpoint;
|
context->position = endpoint;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -93,14 +93,26 @@ static int ftConicTo(const FT_Vector *control, const FT_Vector *to, void *user)
|
||||||
|
|
||||||
static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, void *user) {
|
static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, void *user) {
|
||||||
FtContext *context = reinterpret_cast<FtContext *>(user);
|
FtContext *context = reinterpret_cast<FtContext *>(user);
|
||||||
Point2 endpoint = ftPoint2(*to);
|
Point2 endpoint = ftPoint2(*to, context->scale);
|
||||||
if (endpoint != context->position || crossProduct(ftPoint2(*control1)-endpoint, ftPoint2(*control2)-endpoint)) {
|
if (endpoint != context->position || crossProduct(ftPoint2(*control1, context->scale)-endpoint, ftPoint2(*control2, context->scale)-endpoint)) {
|
||||||
context->contour->addEdge(EdgeHolder(context->position, ftPoint2(*control1), ftPoint2(*control2), endpoint));
|
context->contour->addEdge(EdgeHolder(context->position, ftPoint2(*control1, context->scale), ftPoint2(*control2, context->scale), endpoint));
|
||||||
context->position = endpoint;
|
context->position = endpoint;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double getFontCoordinateScale(const FT_Face &face, FontCoordinateScaling coordinateScaling) {
|
||||||
|
switch (coordinateScaling) {
|
||||||
|
case FontCoordinateScaling::LEGACY:
|
||||||
|
return MSDFGEN_LEGACY_FONT_COORDINATE_SCALE;
|
||||||
|
case FontCoordinateScaling::KEEP_INTEGERS:
|
||||||
|
return 1;
|
||||||
|
case FontCoordinateScaling::EM_NORMALIZED:
|
||||||
|
return 1./(face->units_per_EM ? face->units_per_EM : 1);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
GlyphIndex::GlyphIndex(unsigned index) : index(index) { }
|
GlyphIndex::GlyphIndex(unsigned index) : index(index) { }
|
||||||
|
|
||||||
unsigned GlyphIndex::getIndex() const {
|
unsigned GlyphIndex::getIndex() const {
|
||||||
|
|
@ -129,10 +141,11 @@ FontHandle *adoptFreetypeFont(FT_Face ftFace) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Error readFreetypeOutline(Shape &output, FT_Outline *outline) {
|
FT_Error readFreetypeOutline(Shape &output, FT_Outline *outline, double scale) {
|
||||||
output.contours.clear();
|
output.contours.clear();
|
||||||
output.inverseYAxis = false;
|
output.inverseYAxis = false;
|
||||||
FtContext context = { };
|
FtContext context = { };
|
||||||
|
context.scale = scale;
|
||||||
context.shape = &output;
|
context.shape = &output;
|
||||||
FT_Outline_Funcs ftFunctions;
|
FT_Outline_Funcs ftFunctions;
|
||||||
ftFunctions.move_to = &ftMoveTo;
|
ftFunctions.move_to = &ftMoveTo;
|
||||||
|
|
@ -179,25 +192,27 @@ void destroyFont(FontHandle *font) {
|
||||||
delete font;
|
delete font;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getFontMetrics(FontMetrics &metrics, FontHandle *font) {
|
bool getFontMetrics(FontMetrics &metrics, FontHandle *font, FontCoordinateScaling coordinateScaling) {
|
||||||
metrics.emSize = F26DOT6_TO_DOUBLE(font->face->units_per_EM);
|
double scale = getFontCoordinateScale(font->face, coordinateScaling);
|
||||||
metrics.ascenderY = F26DOT6_TO_DOUBLE(font->face->ascender);
|
metrics.emSize = scale*font->face->units_per_EM;
|
||||||
metrics.descenderY = F26DOT6_TO_DOUBLE(font->face->descender);
|
metrics.ascenderY = scale*font->face->ascender;
|
||||||
metrics.lineHeight = F26DOT6_TO_DOUBLE(font->face->height);
|
metrics.descenderY = scale*font->face->descender;
|
||||||
metrics.underlineY = F26DOT6_TO_DOUBLE(font->face->underline_position);
|
metrics.lineHeight = scale*font->face->height;
|
||||||
metrics.underlineThickness = F26DOT6_TO_DOUBLE(font->face->underline_thickness);
|
metrics.underlineY = scale*font->face->underline_position;
|
||||||
|
metrics.underlineThickness = scale*font->face->underline_thickness;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font) {
|
bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font, FontCoordinateScaling coordinateScaling) {
|
||||||
|
double scale = getFontCoordinateScale(font->face, coordinateScaling);
|
||||||
FT_Error error = FT_Load_Char(font->face, ' ', FT_LOAD_NO_SCALE);
|
FT_Error error = FT_Load_Char(font->face, ' ', FT_LOAD_NO_SCALE);
|
||||||
if (error)
|
if (error)
|
||||||
return false;
|
return false;
|
||||||
spaceAdvance = F26DOT6_TO_DOUBLE(font->face->glyph->advance.x);
|
spaceAdvance = scale*font->face->glyph->advance.x;
|
||||||
error = FT_Load_Char(font->face, '\t', FT_LOAD_NO_SCALE);
|
error = FT_Load_Char(font->face, '\t', FT_LOAD_NO_SCALE);
|
||||||
if (error)
|
if (error)
|
||||||
return false;
|
return false;
|
||||||
tabAdvance = F26DOT6_TO_DOUBLE(font->face->glyph->advance.x);
|
tabAdvance = scale*font->face->glyph->advance.x;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,33 +226,42 @@ bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode)
|
||||||
return glyphIndex.getIndex() != 0;
|
return glyphIndex.getIndex() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *advance) {
|
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, FontCoordinateScaling coordinateScaling, double *outAdvance) {
|
||||||
if (!font)
|
if (!font)
|
||||||
return false;
|
return false;
|
||||||
FT_Error error = FT_Load_Glyph(font->face, glyphIndex.getIndex(), FT_LOAD_NO_SCALE);
|
FT_Error error = FT_Load_Glyph(font->face, glyphIndex.getIndex(), FT_LOAD_NO_SCALE);
|
||||||
if (error)
|
if (error)
|
||||||
return false;
|
return false;
|
||||||
if (advance)
|
double scale = getFontCoordinateScale(font->face, coordinateScaling);
|
||||||
*advance = F26DOT6_TO_DOUBLE(font->face->glyph->advance.x);
|
if (outAdvance)
|
||||||
return !readFreetypeOutline(output, &font->face->glyph->outline);
|
*outAdvance = scale*font->face->glyph->advance.x;
|
||||||
|
return !readFreetypeOutline(output, &font->face->glyph->outline, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance) {
|
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, FontCoordinateScaling coordinateScaling, double *outAdvance) {
|
||||||
return loadGlyph(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode)), advance);
|
return loadGlyph(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode)), coordinateScaling, outAdvance);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex0, GlyphIndex glyphIndex1) {
|
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *outAdvance) {
|
||||||
|
return loadGlyph(output, font, glyphIndex, FontCoordinateScaling::LEGACY, outAdvance);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *outAdvance) {
|
||||||
|
return loadGlyph(output, font, unicode, FontCoordinateScaling::LEGACY, outAdvance);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex0, GlyphIndex glyphIndex1, FontCoordinateScaling coordinateScaling) {
|
||||||
FT_Vector kerning;
|
FT_Vector kerning;
|
||||||
if (FT_Get_Kerning(font->face, glyphIndex0.getIndex(), glyphIndex1.getIndex(), FT_KERNING_UNSCALED, &kerning)) {
|
if (FT_Get_Kerning(font->face, glyphIndex0.getIndex(), glyphIndex1.getIndex(), FT_KERNING_UNSCALED, &kerning)) {
|
||||||
output = 0;
|
output = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
output = F26DOT6_TO_DOUBLE(kerning.x);
|
output = getFontCoordinateScale(font->face, coordinateScaling)*kerning.x;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getKerning(double &output, FontHandle *font, unicode_t unicode0, unicode_t unicode1) {
|
bool getKerning(double &output, FontHandle *font, unicode_t unicode0, unicode_t unicode1, FontCoordinateScaling coordinateScaling) {
|
||||||
return getKerning(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode0)), GlyphIndex(FT_Get_Char_Index(font->face, unicode1)));
|
return getKerning(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode0)), GlyphIndex(FT_Get_Char_Index(font->face, unicode1)), coordinateScaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
namespace msdfgen {
|
namespace msdfgen {
|
||||||
|
|
||||||
|
#define MSDFGEN_LEGACY_FONT_COORDINATE_SCALE (1/64.)
|
||||||
|
|
||||||
typedef unsigned unicode_t;
|
typedef unsigned unicode_t;
|
||||||
|
|
||||||
class FreetypeHandle;
|
class FreetypeHandle;
|
||||||
|
|
@ -45,6 +47,16 @@ struct FontVariationAxis {
|
||||||
double defaultValue;
|
double defaultValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The scaling applied to font glyph coordinates when loading a glyph
|
||||||
|
enum class FontCoordinateScaling {
|
||||||
|
/// The incorrect legacy version that was in effect before version 1.12, coordinate values are divided by 64
|
||||||
|
LEGACY,
|
||||||
|
/// The coordinates are kept as the integer values native to the font file
|
||||||
|
KEEP_INTEGERS,
|
||||||
|
/// The coordinates will be normalized to the em size, i.e. 1 = 1 em
|
||||||
|
EM_NORMALIZED
|
||||||
|
};
|
||||||
|
|
||||||
/// Initializes the FreeType library.
|
/// Initializes the FreeType library.
|
||||||
FreetypeHandle *initializeFreetype();
|
FreetypeHandle *initializeFreetype();
|
||||||
/// Deinitializes the FreeType library.
|
/// Deinitializes the FreeType library.
|
||||||
|
|
@ -54,7 +66,7 @@ void deinitializeFreetype(FreetypeHandle *library);
|
||||||
/// Creates a FontHandle from FT_Face that was loaded by the user. destroyFont must still be called but will not affect the FT_Face.
|
/// Creates a FontHandle from FT_Face that was loaded by the user. destroyFont must still be called but will not affect the FT_Face.
|
||||||
FontHandle *adoptFreetypeFont(FT_Face ftFace);
|
FontHandle *adoptFreetypeFont(FT_Face ftFace);
|
||||||
/// Converts the geometry of FreeType's FT_Outline to a Shape object.
|
/// Converts the geometry of FreeType's FT_Outline to a Shape object.
|
||||||
FT_Error readFreetypeOutline(Shape &output, FT_Outline *outline);
|
FT_Error readFreetypeOutline(Shape &output, FT_Outline *outline, double scale = MSDFGEN_LEGACY_FONT_COORDINATE_SCALE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Loads a font file and returns its handle.
|
/// Loads a font file and returns its handle.
|
||||||
|
|
@ -64,19 +76,22 @@ FontHandle *loadFontData(FreetypeHandle *library, const byte *data, int length);
|
||||||
/// Unloads a font.
|
/// Unloads a font.
|
||||||
void destroyFont(FontHandle *font);
|
void destroyFont(FontHandle *font);
|
||||||
/// Outputs the metrics of a font.
|
/// Outputs the metrics of a font.
|
||||||
bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
|
bool getFontMetrics(FontMetrics &metrics, FontHandle *font, FontCoordinateScaling coordinateScaling = FontCoordinateScaling::LEGACY);
|
||||||
/// Outputs the width of the space and tab characters.
|
/// Outputs the width of the space and tab characters.
|
||||||
bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font);
|
bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font, FontCoordinateScaling coordinateScaling = FontCoordinateScaling::LEGACY);
|
||||||
/// Outputs the total number of glyphs available in the font.
|
/// Outputs the total number of glyphs available in the font.
|
||||||
bool getGlyphCount(unsigned &output, FontHandle *font);
|
bool getGlyphCount(unsigned &output, FontHandle *font);
|
||||||
/// Outputs the glyph index corresponding to the specified Unicode character.
|
/// Outputs the glyph index corresponding to the specified Unicode character.
|
||||||
bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode);
|
bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode);
|
||||||
/// Loads the geometry of a glyph from a font.
|
/// Loads the geometry of a glyph from a font.
|
||||||
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *advance = NULL);
|
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, FontCoordinateScaling coordinateScaling, double *outAdvance = NULL);
|
||||||
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance = NULL);
|
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, FontCoordinateScaling coordinateScaling, double *outAdvance = NULL);
|
||||||
|
// Legacy API - FontCoordinateScaling is LEGACY
|
||||||
|
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *outAdvance = NULL);
|
||||||
|
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *outAdvance = NULL);
|
||||||
/// Outputs the kerning distance adjustment between two specific glyphs.
|
/// Outputs the kerning distance adjustment between two specific glyphs.
|
||||||
bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex0, GlyphIndex glyphIndex1);
|
bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex0, GlyphIndex glyphIndex1, FontCoordinateScaling coordinateScaling = FontCoordinateScaling::LEGACY);
|
||||||
bool getKerning(double &output, FontHandle *font, unicode_t unicode0, unicode_t unicode1);
|
bool getKerning(double &output, FontHandle *font, unicode_t unicode0, unicode_t unicode1, FontCoordinateScaling coordinateScaling = FontCoordinateScaling::LEGACY);
|
||||||
|
|
||||||
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
||||||
/// Sets a single variation axis of a variable font.
|
/// Sets a single variation axis of a variable font.
|
||||||
|
|
|
||||||
78
main.cpp
78
main.cpp
|
|
@ -402,6 +402,10 @@ static const char *const helpText =
|
||||||
"\tSets the dimensions of the output image.\n"
|
"\tSets the dimensions of the output image.\n"
|
||||||
" -edgecolors <sequence>\n"
|
" -edgecolors <sequence>\n"
|
||||||
"\tOverrides automatic edge coloring with the specified color sequence.\n"
|
"\tOverrides automatic edge coloring with the specified color sequence.\n"
|
||||||
|
#ifdef MSDFGEN_EXTENSIONS
|
||||||
|
" -emnormalize\n"
|
||||||
|
"\tBefore applying scale, normalizes font glyph coordinates so that 1 = 1 em.\n"
|
||||||
|
#endif
|
||||||
" -errorcorrection <mode>\n"
|
" -errorcorrection <mode>\n"
|
||||||
"\tChanges the MSDF/MTSDF error correction mode. Use -errorcorrection help for a list of valid modes.\n"
|
"\tChanges the MSDF/MTSDF error correction mode. Use -errorcorrection help for a list of valid modes.\n"
|
||||||
" -errordeviationratio <ratio>\n"
|
" -errordeviationratio <ratio>\n"
|
||||||
|
|
@ -426,6 +430,10 @@ static const char *const helpText =
|
||||||
"\tDisplays this help.\n"
|
"\tDisplays this help.\n"
|
||||||
" -legacy\n"
|
" -legacy\n"
|
||||||
"\tUses the original (legacy) distance field algorithms.\n"
|
"\tUses the original (legacy) distance field algorithms.\n"
|
||||||
|
#ifdef MSDFGEN_EXTENSIONS
|
||||||
|
" -noemnormalize\n"
|
||||||
|
"\tRaw integer font glyph coordinates will be used. Without this option, legacy scaling will be applied.\n"
|
||||||
|
#endif
|
||||||
#ifdef MSDFGEN_USE_SKIA
|
#ifdef MSDFGEN_USE_SKIA
|
||||||
" -nopreprocess\n"
|
" -nopreprocess\n"
|
||||||
"\tDisables path preprocessing which resolves self-intersections and overlapping contours.\n"
|
"\tDisables path preprocessing which resolves self-intersections and overlapping contours.\n"
|
||||||
|
|
@ -547,6 +555,8 @@ int main(int argc, const char *const *argv) {
|
||||||
bool glyphIndexSpecified = false;
|
bool glyphIndexSpecified = false;
|
||||||
GlyphIndex glyphIndex;
|
GlyphIndex glyphIndex;
|
||||||
unicode_t unicode = 0;
|
unicode_t unicode = 0;
|
||||||
|
FontCoordinateScaling fontCoordinateScaling = FontCoordinateScaling::LEGACY;
|
||||||
|
bool fontCoordinateScalingSpecified = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int width = 64, height = 64;
|
int width = 64, height = 64;
|
||||||
|
|
@ -631,6 +641,21 @@ int main(int argc, const char *const *argv) {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ARG_CASE("-noemnormalize", 0) {
|
||||||
|
fontCoordinateScaling = FontCoordinateScaling::KEEP_INTEGERS;
|
||||||
|
fontCoordinateScalingSpecified = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ARG_CASE("-emnormalize", 0) {
|
||||||
|
fontCoordinateScaling = FontCoordinateScaling::EM_NORMALIZED;
|
||||||
|
fontCoordinateScalingSpecified = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ARG_CASE("-legacyfontscaling", 0) {
|
||||||
|
fontCoordinateScaling = FontCoordinateScaling::LEGACY;
|
||||||
|
fontCoordinateScalingSpecified = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
ARG_CASE("-svg", 1) {
|
ARG_CASE("-svg", 1) {
|
||||||
ABORT("SVG input is not available in core-only version.");
|
ABORT("SVG input is not available in core-only version.");
|
||||||
|
|
@ -668,6 +693,10 @@ int main(int argc, const char *const *argv) {
|
||||||
}
|
}
|
||||||
ARG_CASE("-legacy", 0) {
|
ARG_CASE("-legacy", 0) {
|
||||||
legacyMode = true;
|
legacyMode = true;
|
||||||
|
#ifdef MSDFGEN_EXTENSIONS
|
||||||
|
fontCoordinateScaling = FontCoordinateScaling::LEGACY;
|
||||||
|
fontCoordinateScalingSpecified = true;
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ARG_CASE("-nopreprocess", 0) {
|
ARG_CASE("-nopreprocess", 0) {
|
||||||
|
|
@ -987,28 +1016,40 @@ int main(int argc, const char *const *argv) {
|
||||||
case FONT: case VAR_FONT: {
|
case FONT: case VAR_FONT: {
|
||||||
if (!glyphIndexSpecified && !unicode)
|
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).");
|
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();
|
struct FreetypeFontGuard {
|
||||||
if (!ft)
|
FreetypeHandle *ft;
|
||||||
return -1;
|
FontHandle *font;
|
||||||
FontHandle *font = (
|
FreetypeFontGuard() : ft(), font() { }
|
||||||
|
~FreetypeFontGuard() {
|
||||||
|
if (ft) {
|
||||||
|
if (font)
|
||||||
|
destroyFont(font);
|
||||||
|
deinitializeFreetype(ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} guard;
|
||||||
|
if (!(guard.ft = initializeFreetype()))
|
||||||
|
ABORT("Failed to initialize FreeType library.");
|
||||||
|
if (!(guard.font = (
|
||||||
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
||||||
inputType == VAR_FONT ? loadVarFont(ft, input) :
|
inputType == VAR_FONT ? loadVarFont(guard.ft, input) :
|
||||||
#endif
|
#endif
|
||||||
loadFont(ft, input)
|
loadFont(guard.ft, input)
|
||||||
);
|
)))
|
||||||
if (!font) {
|
|
||||||
deinitializeFreetype(ft);
|
|
||||||
ABORT("Failed to load font file.");
|
ABORT("Failed to load font file.");
|
||||||
}
|
|
||||||
if (unicode)
|
if (unicode)
|
||||||
getGlyphIndex(glyphIndex, font, unicode);
|
getGlyphIndex(glyphIndex, guard.font, unicode);
|
||||||
if (!loadGlyph(shape, font, glyphIndex, &glyphAdvance)) {
|
if (!loadGlyph(shape, guard.font, glyphIndex, fontCoordinateScaling, &glyphAdvance))
|
||||||
destroyFont(font);
|
|
||||||
deinitializeFreetype(ft);
|
|
||||||
ABORT("Failed to load glyph from font file.");
|
ABORT("Failed to load glyph from font file.");
|
||||||
|
if (!fontCoordinateScalingSpecified && (!autoFrame || scaleSpecified || rangeMode == RANGE_UNIT || mode == METRICS || printMetrics || shapeExport)) {
|
||||||
|
fputs(
|
||||||
|
"Warning: Using legacy font coordinate conversion for compatibility reasons.\n"
|
||||||
|
" The scaling behavior in this configuration will likely change in a future version resulting in different output.\n"
|
||||||
|
" To silence this warning, use one of the following options:\n"
|
||||||
|
" -noemnormalize to switch to the correct native font coordinates,\n"
|
||||||
|
" -emnormalize to switch to coordinates normalized to 1 em, or\n"
|
||||||
|
" -legacyfontscaling to keep current behavior and make sure it will not change.\n", stderr);
|
||||||
}
|
}
|
||||||
destroyFont(font);
|
|
||||||
deinitializeFreetype(ft);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1026,9 +1067,10 @@ int main(int argc, const char *const *argv) {
|
||||||
FILE *file = fopen(input, "r");
|
FILE *file = fopen(input, "r");
|
||||||
if (!file)
|
if (!file)
|
||||||
ABORT("Failed to load shape description file.");
|
ABORT("Failed to load shape description file.");
|
||||||
if (!readShapeDescription(file, shape, &skipColoring))
|
bool readSuccessful = readShapeDescription(file, shape, &skipColoring);
|
||||||
ABORT("Parse error in shape description.");
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
if (!readSuccessful)
|
||||||
|
ABORT("Parse error in shape description.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:;
|
default:;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue