mirror of https://github.com/Chlumsky/msdfgen.git
Added glyph loading by glyph index, passing own FT_Face handle
This commit is contained in:
parent
9d5c7c54e8
commit
38ef289f25
|
|
@ -34,7 +34,7 @@ static bool writeValue(FILE *file, T value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool writeBmpHeader(FILE *file, int width, int height, int &paddedWidth) {
|
static bool writeBmpHeader(FILE *file, int width, int height, int &paddedWidth) {
|
||||||
paddedWidth = 3*width+3&~3;
|
paddedWidth = (3*width+3)&~3;
|
||||||
const uint32_t bitmapStart = 54;
|
const uint32_t bitmapStart = 54;
|
||||||
const uint32_t bitmapSize = paddedWidth*height;
|
const uint32_t bitmapSize = paddedWidth*height;
|
||||||
const uint32_t fileSize = bitmapStart+bitmapSize;
|
const uint32_t fileSize = bitmapStart+bitmapSize;
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ bool readShapeDescription(const char *input, Shape &output, bool *colorsSpecifie
|
||||||
else {
|
else {
|
||||||
int c = readCharS(&input);
|
int c = readCharS(&input);
|
||||||
if (c == '@') {
|
if (c == '@') {
|
||||||
for (int i = 0; i < sizeof("invert-y")-1; ++i)
|
for (int i = 0; i < (int) sizeof("invert-y")-1; ++i)
|
||||||
if (input[i] != "invert-y"[i])
|
if (input[i] != "invert-y"[i])
|
||||||
return false;
|
return false;
|
||||||
output.inverseYAxis = true;
|
output.inverseYAxis = true;
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,19 @@ class FreetypeHandle {
|
||||||
};
|
};
|
||||||
|
|
||||||
class FontHandle {
|
class FontHandle {
|
||||||
|
friend FontHandle * adoptFreetypeFont(FT_Face ftFace);
|
||||||
friend FontHandle * loadFont(FreetypeHandle *library, const char *filename);
|
friend FontHandle * loadFont(FreetypeHandle *library, const char *filename);
|
||||||
friend void destroyFont(FontHandle *font);
|
friend void destroyFont(FontHandle *font);
|
||||||
friend bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
|
friend bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
|
||||||
friend bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font);
|
friend bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle *font);
|
||||||
|
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, unicode_t unicode, double *advance);
|
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 getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2);
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
|
bool ownership;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -79,6 +84,16 @@ static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GlyphIndex::GlyphIndex(unsigned index) : index(index) { }
|
||||||
|
|
||||||
|
unsigned GlyphIndex::getIndex() const {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlyphIndex::operator!() const {
|
||||||
|
return index == 0;
|
||||||
|
}
|
||||||
|
|
||||||
FreetypeHandle * initializeFreetype() {
|
FreetypeHandle * initializeFreetype() {
|
||||||
FreetypeHandle *handle = new FreetypeHandle;
|
FreetypeHandle *handle = new FreetypeHandle;
|
||||||
FT_Error error = FT_Init_FreeType(&handle->library);
|
FT_Error error = FT_Init_FreeType(&handle->library);
|
||||||
|
|
@ -94,6 +109,13 @@ void deinitializeFreetype(FreetypeHandle *library) {
|
||||||
delete library;
|
delete library;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FontHandle * adoptFreetypeFont(FT_Face ftFace) {
|
||||||
|
FontHandle *handle = new FontHandle;
|
||||||
|
handle->face = ftFace;
|
||||||
|
handle->ownership = false;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
FontHandle * loadFont(FreetypeHandle *library, const char *filename) {
|
FontHandle * loadFont(FreetypeHandle *library, const char *filename) {
|
||||||
if (!library)
|
if (!library)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -103,11 +125,13 @@ FontHandle * loadFont(FreetypeHandle *library, const char *filename) {
|
||||||
delete handle;
|
delete handle;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
handle->ownership = true;
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyFont(FontHandle *font) {
|
void destroyFont(FontHandle *font) {
|
||||||
FT_Done_Face(font->face);
|
if (font->ownership)
|
||||||
|
FT_Done_Face(font->face);
|
||||||
delete font;
|
delete font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,10 +157,15 @@ bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance) {
|
bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode) {
|
||||||
|
glyphIndex = GlyphIndex(FT_Get_Char_Index(font->face, unicode));
|
||||||
|
return glyphIndex.getIndex() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *advance) {
|
||||||
if (!font)
|
if (!font)
|
||||||
return false;
|
return false;
|
||||||
FT_Error error = FT_Load_Char(font->face, unicode, 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;
|
||||||
output.contours.clear();
|
output.contours.clear();
|
||||||
|
|
@ -161,9 +190,13 @@ bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advan
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2) {
|
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance) {
|
||||||
|
return loadGlyph(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode)), advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex1, GlyphIndex glyphIndex2) {
|
||||||
FT_Vector kerning;
|
FT_Vector kerning;
|
||||||
if (FT_Get_Kerning(font->face, FT_Get_Char_Index(font->face, unicode1), FT_Get_Char_Index(font->face, unicode2), FT_KERNING_UNSCALED, &kerning)) {
|
if (FT_Get_Kerning(font->face, glyphIndex1.getIndex(), glyphIndex2.getIndex(), FT_KERNING_UNSCALED, &kerning)) {
|
||||||
output = 0;
|
output = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -171,4 +204,8 @@ bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2) {
|
||||||
|
return getKerning(output, font, GlyphIndex(FT_Get_Char_Index(font->face, unicode1)), GlyphIndex(FT_Get_Char_Index(font->face, unicode2)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,18 @@ typedef unsigned unicode_t;
|
||||||
class FreetypeHandle;
|
class FreetypeHandle;
|
||||||
class FontHandle;
|
class FontHandle;
|
||||||
|
|
||||||
|
class GlyphIndex {
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GlyphIndex(unsigned index = 0);
|
||||||
|
unsigned getIndex() const;
|
||||||
|
bool operator!() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/// Global metrics of a typeface (in font units).
|
/// Global metrics of a typeface (in font units).
|
||||||
struct FontMetrics {
|
struct FontMetrics {
|
||||||
/// The size of one EM.
|
/// The size of one EM.
|
||||||
|
|
@ -27,6 +39,11 @@ struct FontMetrics {
|
||||||
FreetypeHandle * initializeFreetype();
|
FreetypeHandle * initializeFreetype();
|
||||||
/// Deinitializes the FreeType library.
|
/// Deinitializes the FreeType library.
|
||||||
void deinitializeFreetype(FreetypeHandle *library);
|
void deinitializeFreetype(FreetypeHandle *library);
|
||||||
|
|
||||||
|
#ifdef FT_FREETYPE_H
|
||||||
|
/// 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);
|
||||||
|
#endif
|
||||||
/// Loads a font file and returns its handle.
|
/// Loads a font file and returns its handle.
|
||||||
FontHandle * loadFont(FreetypeHandle *library, const char *filename);
|
FontHandle * loadFont(FreetypeHandle *library, const char *filename);
|
||||||
/// Unloads a font file.
|
/// Unloads a font file.
|
||||||
|
|
@ -35,9 +52,13 @@ void destroyFont(FontHandle *font);
|
||||||
bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
|
bool getFontMetrics(FontMetrics &metrics, FontHandle *font);
|
||||||
/// 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);
|
||||||
|
/// Outputs the glyph index corresponding to the specified Unicode character.
|
||||||
|
bool getGlyphIndex(GlyphIndex &glyphIndex, FontHandle *font, unicode_t unicode);
|
||||||
/// Loads the geometry of a glyph from a font file.
|
/// Loads the geometry of a glyph from a font file.
|
||||||
|
bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *advance = NULL);
|
||||||
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance = NULL);
|
bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance = 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 glyphIndex1, GlyphIndex glyphIndex2);
|
||||||
bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2);
|
bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
53
main.cpp
53
main.cpp
|
|
@ -45,37 +45,36 @@ static char toupper(char c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseUnsigned(unsigned &value, const char *arg) {
|
static bool parseUnsigned(unsigned &value, const char *arg) {
|
||||||
static char c;
|
char c;
|
||||||
return sscanf(arg, "%u%c", &value, &c) == 1;
|
return sscanf(arg, "%u%c", &value, &c) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parseUnsignedDecOrHex(unsigned &value, const char *arg) {
|
||||||
|
if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) {
|
||||||
|
char c;
|
||||||
|
return sscanf(arg+2, "%x%c", &value, &c) == 1;
|
||||||
|
}
|
||||||
|
return parseUnsigned(value, arg);
|
||||||
|
}
|
||||||
|
|
||||||
static bool parseUnsignedLL(unsigned long long &value, const char *arg) {
|
static bool parseUnsignedLL(unsigned long long &value, const char *arg) {
|
||||||
static char c;
|
char c;
|
||||||
return sscanf(arg, "%llu%c", &value, &c) == 1;
|
return sscanf(arg, "%llu%c", &value, &c) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseUnsignedHex(unsigned &value, const char *arg) {
|
|
||||||
static char c;
|
|
||||||
return sscanf(arg, "%x%c", &value, &c) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parseDouble(double &value, const char *arg) {
|
static bool parseDouble(double &value, const char *arg) {
|
||||||
static char c;
|
char c;
|
||||||
return sscanf(arg, "%lf%c", &value, &c) == 1;
|
return sscanf(arg, "%lf%c", &value, &c) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseUnicode(unicode_t &unicode, const char *arg) {
|
static bool parseUnicode(unicode_t &unicode, const char *arg) {
|
||||||
unsigned uuc;
|
unsigned uuc;
|
||||||
if (parseUnsigned(uuc, arg)) {
|
if (parseUnsignedDecOrHex(uuc, arg)) {
|
||||||
unicode = uuc;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X') && parseUnsignedHex(uuc, arg+2)) {
|
|
||||||
unicode = uuc;
|
unicode = uuc;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (arg[0] == '\'' && arg[1] && arg[2] == '\'' && !arg[3]) {
|
if (arg[0] == '\'' && arg[1] && arg[2] == '\'' && !arg[3]) {
|
||||||
unicode = arg[1];
|
unicode = (unicode_t) (unsigned char) arg[1];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -178,7 +177,7 @@ static bool writeBinBitmapFloatBE(FILE *file, const float *values, int count)
|
||||||
static bool writeBinBitmapFloat(FILE *file, const float *values, int count)
|
static bool writeBinBitmapFloat(FILE *file, const float *values, int count)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return fwrite(values, sizeof(float), count, file) == count;
|
return (int) fwrite(values, sizeof(float), count, file) == count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
#ifdef __BIG_ENDIAN__
|
||||||
|
|
@ -274,7 +273,7 @@ static const char *helpText =
|
||||||
" -defineshape <definition>\n"
|
" -defineshape <definition>\n"
|
||||||
"\tDefines input shape using the ad-hoc text definition.\n"
|
"\tDefines input shape using the ad-hoc text definition.\n"
|
||||||
" -font <filename.ttf> <character code>\n"
|
" -font <filename.ttf> <character code>\n"
|
||||||
"\tLoads a single glyph from the specified font file. Format of character code is '?', 63 or 0x3F.\n"
|
"\tLoads a single glyph from the specified font file. Format of character code is '?', 63, 0x3F (Unicode value), or g34 (glyph index).\n"
|
||||||
" -shapedesc <filename.txt>\n"
|
" -shapedesc <filename.txt>\n"
|
||||||
"\tLoads text shape description from a file.\n"
|
"\tLoads text shape description from a file.\n"
|
||||||
" -stdin\n"
|
" -stdin\n"
|
||||||
|
|
@ -373,6 +372,7 @@ int main(int argc, const char * const *argv) {
|
||||||
const char *testRender = NULL;
|
const char *testRender = NULL;
|
||||||
const char *testRenderMulti = NULL;
|
const char *testRenderMulti = NULL;
|
||||||
bool outputSpecified = false;
|
bool outputSpecified = false;
|
||||||
|
GlyphIndex glyphIndex;
|
||||||
unicode_t unicode = 0;
|
unicode_t unicode = 0;
|
||||||
int svgPathIndex = 0;
|
int svgPathIndex = 0;
|
||||||
|
|
||||||
|
|
@ -428,7 +428,18 @@ int main(int argc, const char * const *argv) {
|
||||||
ARG_CASE("-font", 2) {
|
ARG_CASE("-font", 2) {
|
||||||
inputType = FONT;
|
inputType = FONT;
|
||||||
input = argv[argPos+1];
|
input = argv[argPos+1];
|
||||||
parseUnicode(unicode, argv[argPos+2]);
|
const char *charArg = argv[argPos+2];
|
||||||
|
unsigned gi;
|
||||||
|
switch (charArg[0]) {
|
||||||
|
case 'G': case 'g':
|
||||||
|
if (parseUnsignedDecOrHex(gi, charArg+1))
|
||||||
|
glyphIndex = GlyphIndex(gi);
|
||||||
|
break;
|
||||||
|
case 'U': case 'u':
|
||||||
|
++charArg;
|
||||||
|
default:
|
||||||
|
parseUnicode(unicode, charArg);
|
||||||
|
}
|
||||||
argPos += 3;
|
argPos += 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -693,8 +704,8 @@ int main(int argc, const char * const *argv) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FONT: {
|
case FONT: {
|
||||||
if (!unicode)
|
if (!glyphIndex && !unicode)
|
||||||
ABORT("No character specified! Use -font <file.ttf/otf> <character code>. Character code can be a number (65, 0x41), or a character in apostrophes ('A').");
|
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();
|
FreetypeHandle *ft = initializeFreetype();
|
||||||
if (!ft) return -1;
|
if (!ft) return -1;
|
||||||
FontHandle *font = loadFont(ft, input);
|
FontHandle *font = loadFont(ft, input);
|
||||||
|
|
@ -702,7 +713,9 @@ int main(int argc, const char * const *argv) {
|
||||||
deinitializeFreetype(ft);
|
deinitializeFreetype(ft);
|
||||||
ABORT("Failed to load font file.");
|
ABORT("Failed to load font file.");
|
||||||
}
|
}
|
||||||
if (!loadGlyph(shape, font, unicode, &glyphAdvance)) {
|
if (unicode)
|
||||||
|
getGlyphIndex(glyphIndex, font, unicode);
|
||||||
|
if (!loadGlyph(shape, font, glyphIndex, &glyphAdvance)) {
|
||||||
destroyFont(font);
|
destroyFont(font);
|
||||||
deinitializeFreetype(ft);
|
deinitializeFreetype(ft);
|
||||||
ABORT("Failed to load glyph from font file.");
|
ABORT("Failed to load glyph from font file.");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue