diff --git a/core/save-bmp.cpp b/core/save-bmp.cpp index 3ca3674..f761ee4 100644 --- a/core/save-bmp.cpp +++ b/core/save-bmp.cpp @@ -34,7 +34,7 @@ static bool writeValue(FILE *file, T value) { } 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 bitmapSize = paddedWidth*height; const uint32_t fileSize = bitmapStart+bitmapSize; diff --git a/core/shape-description.cpp b/core/shape-description.cpp index 8aea533..9dd30a8 100644 --- a/core/shape-description.cpp +++ b/core/shape-description.cpp @@ -200,7 +200,7 @@ bool readShapeDescription(const char *input, Shape &output, bool *colorsSpecifie else { int c = readCharS(&input); 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]) return false; output.inverseYAxis = true; diff --git a/ext/import-font.cpp b/ext/import-font.cpp index f4afb11..8f23620 100644 --- a/ext/import-font.cpp +++ b/ext/import-font.cpp @@ -26,14 +26,19 @@ class FreetypeHandle { }; class FontHandle { + friend FontHandle * adoptFreetypeFont(FT_Face ftFace); friend FontHandle * loadFont(FreetypeHandle *library, const char *filename); friend void destroyFont(FontHandle *font); friend bool getFontMetrics(FontMetrics &metrics, 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 getKerning(double &output, FontHandle *font, GlyphIndex glyphIndex1, GlyphIndex glyphIndex2); friend bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t unicode2); FT_Face face; + bool ownership; }; @@ -79,6 +84,16 @@ static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const return 0; } +GlyphIndex::GlyphIndex(unsigned index) : index(index) { } + +unsigned GlyphIndex::getIndex() const { + return index; +} + +bool GlyphIndex::operator!() const { + return index == 0; +} + FreetypeHandle * initializeFreetype() { FreetypeHandle *handle = new FreetypeHandle; FT_Error error = FT_Init_FreeType(&handle->library); @@ -94,6 +109,13 @@ void deinitializeFreetype(FreetypeHandle *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) { if (!library) return NULL; @@ -103,11 +125,13 @@ FontHandle * loadFont(FreetypeHandle *library, const char *filename) { delete handle; return NULL; } + handle->ownership = true; return handle; } void destroyFont(FontHandle *font) { - FT_Done_Face(font->face); + if (font->ownership) + FT_Done_Face(font->face); delete font; } @@ -133,10 +157,15 @@ bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle 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) 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) return false; output.contours.clear(); @@ -161,9 +190,13 @@ bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advan 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; - 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; return false; } @@ -171,4 +204,8 @@ bool getKerning(double &output, FontHandle *font, unicode_t unicode1, unicode_t 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))); +} + } diff --git a/ext/import-font.h b/ext/import-font.h index 4edf4f0..e27df99 100644 --- a/ext/import-font.h +++ b/ext/import-font.h @@ -11,6 +11,18 @@ typedef unsigned unicode_t; class FreetypeHandle; 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). struct FontMetrics { /// The size of one EM. @@ -27,6 +39,11 @@ struct FontMetrics { FreetypeHandle * initializeFreetype(); /// Deinitializes the FreeType 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. FontHandle * loadFont(FreetypeHandle *library, const char *filename); /// Unloads a font file. @@ -35,9 +52,13 @@ void destroyFont(FontHandle *font); bool getFontMetrics(FontMetrics &metrics, FontHandle *font); /// Outputs the width of the space and tab characters. 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. +bool loadGlyph(Shape &output, FontHandle *font, GlyphIndex glyphIndex, double *advance = NULL); bool loadGlyph(Shape &output, FontHandle *font, unicode_t unicode, double *advance = NULL); /// 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); } diff --git a/main.cpp b/main.cpp index 7d03b83..49c4bd0 100644 --- a/main.cpp +++ b/main.cpp @@ -45,37 +45,36 @@ static char toupper(char c) { } static bool parseUnsigned(unsigned &value, const char *arg) { - static char c; + char c; 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 char c; + char c; 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 char c; + char c; return sscanf(arg, "%lf%c", &value, &c) == 1; } static bool parseUnicode(unicode_t &unicode, const char *arg) { unsigned uuc; - if (parseUnsigned(uuc, arg)) { - unicode = uuc; - return true; - } - if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X') && parseUnsignedHex(uuc, arg+2)) { + if (parseUnsignedDecOrHex(uuc, arg)) { unicode = uuc; return true; } if (arg[0] == '\'' && arg[1] && arg[2] == '\'' && !arg[3]) { - unicode = arg[1]; + unicode = (unicode_t) (unsigned char) arg[1]; return true; } 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) #endif { - return fwrite(values, sizeof(float), count, file) == count; + return (int) fwrite(values, sizeof(float), count, file) == count; } #ifdef __BIG_ENDIAN__ @@ -274,7 +273,7 @@ static const char *helpText = " -defineshape \n" "\tDefines input shape using the ad-hoc text definition.\n" " -font \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 \n" "\tLoads text shape description from a file.\n" " -stdin\n" @@ -373,6 +372,7 @@ int main(int argc, const char * const *argv) { const char *testRender = NULL; const char *testRenderMulti = NULL; bool outputSpecified = false; + GlyphIndex glyphIndex; unicode_t unicode = 0; int svgPathIndex = 0; @@ -428,7 +428,18 @@ int main(int argc, const char * const *argv) { ARG_CASE("-font", 2) { inputType = FONT; 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; continue; } @@ -693,8 +704,8 @@ int main(int argc, const char * const *argv) { break; } case FONT: { - if (!unicode) - ABORT("No character specified! Use -font . Character code can be a number (65, 0x41), or a character in apostrophes ('A')."); + if (!glyphIndex && !unicode) + ABORT("No character specified! Use -font . 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); @@ -702,7 +713,9 @@ int main(int argc, const char * const *argv) { deinitializeFreetype(ft); 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); deinitializeFreetype(ft); ABORT("Failed to load glyph from font file.");