Ver Fonte

Added glyph loading by glyph index, passing own FT_Face handle

Viktor Chlumský há 4 anos atrás
pai
commit
38ef289f25
5 ficheiros alterados com 98 adições e 27 exclusões
  1. 1 1
      core/save-bmp.cpp
  2. 1 1
      core/shape-description.cpp
  3. 42 5
      ext/import-font.cpp
  4. 21 0
      ext/import-font.h
  5. 33 20
      main.cpp

+ 1 - 1
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;

+ 1 - 1
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;

+ 42 - 5
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)));
+}
+
 }

+ 21 - 0
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);
 
 }

+ 33 - 20
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 parseUnsignedLL(unsigned long long &value, const char *arg) {
-    static char c;
-    return sscanf(arg, "%llu%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 parseUnsignedHex(unsigned &value, const char *arg) {
-    static char c;
-    return sscanf(arg, "%x%c", &value, &c) == 1;
+static bool parseUnsignedLL(unsigned long long &value, const char *arg) {
+    char c;
+    return sscanf(arg, "%llu%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 <definition>\n"
         "\tDefines input shape using the ad-hoc text definition.\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"
         "\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 <file.ttf/otf> <character code>. Character code can be a number (65, 0x41), or a character in apostrophes ('A').");
+            if (!glyphIndex && !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);
@@ -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.");