Commit 5cf01aa2b26727abd97ef202a3687cd7a43819c3

Moazin Khatti 2021-12-25T19:46:46

[truetype, cff] Add code to load SVG document. * src/cff/cffgload.c (cff_slot_load): Add code to load SVG doc. * src/truetype/ttgload.c (TT_Load_Glyph): Add code to load SVG doc.

diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 86b8ea5..2ef9c76 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -346,6 +346,76 @@
     if ( load_flags & FT_LOAD_SBITS_ONLY )
       return FT_THROW( Invalid_Argument );
 
+#ifdef FT_CONFIG_OPTION_SVG
+    /* check for OT-SVG */
+    if ( ( load_flags & FT_LOAD_COLOR )     &&
+         ( (TT_Face)glyph->root.face )->svg )
+    {
+      /*
+       * We load the SVG document and try to grab the advances from the
+       * table.  For the bearings we rely on the presetting hook to do that.
+       */
+
+      FT_Short      dummy;
+      FT_UShort     advanceX;
+      FT_UShort     advanceY;
+      SFNT_Service  sfnt;
+
+
+      if ( size->root.metrics.x_ppem < 1 ||
+           size->root.metrics.y_ppem < 1 )
+      {
+        error = FT_THROW( Invalid_Size_Handle );
+        return error;
+      }
+
+      FT_TRACE3(( "Trying to load SVG glyph\n" ));
+
+      sfnt  = (SFNT_Service)((TT_Face)glyph->root.face)->sfnt;
+      error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index );
+      if ( !error )
+      {
+        FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
+
+        glyph->root.format = FT_GLYPH_FORMAT_SVG;
+
+        /*
+         * If horizontal or vertical advances are not present in the table,
+         * this is a problem with the font since the standard requires them.
+         * However, we are graceful and calculate the values by ourselves
+         * for the vertical case.
+         */
+        sfnt->get_metrics( face,
+                           FALSE,
+                           glyph_index,
+                           &dummy,
+                           &advanceX );
+        sfnt->get_metrics( face,
+                           TRUE,
+                           glyph_index,
+                           &dummy,
+                           &advanceY );
+
+        advanceX =
+          (FT_UShort)FT_MulDiv( advanceX,
+                                glyph->root.face->size->metrics.x_ppem,
+                                glyph->root.face->units_per_EM );
+        advanceY =
+          (FT_UShort)FT_MulDiv( advanceY,
+                                glyph->root.face->size->metrics.y_ppem,
+                                glyph->root.face->units_per_EM );
+
+        glyph->root.metrics.horiAdvance = advanceX << 6;
+        glyph->root.metrics.vertAdvance = advanceY << 6;
+
+        return error;
+      }
+
+      FT_TRACE3(( "Failed to load SVG glyph\n" ));
+    }
+
+#endif /* FT_CONFIG_OPTION_SVG */
+
     /* if we have a CID subfont, use its matrix (which has already */
     /* been multiplied with the root matrix)                       */
 
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index e773059..33d743b 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -2919,6 +2919,12 @@
       }
     }
 
+    if ( load_flags & FT_LOAD_SBITS_ONLY )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
@@ -2928,12 +2934,68 @@
       goto Exit;
     }
 
-    if ( load_flags & FT_LOAD_SBITS_ONLY )
+#ifdef FT_CONFIG_OPTION_SVG
+
+    /* check for OT-SVG */
+    if ( ( load_flags & FT_LOAD_COLOR ) && ( (TT_Face)glyph->face )->svg )
+    {
+      SFNT_Service  sfnt;
+
+      FT_Short   leftBearing;
+      FT_Short   topBearing;
+      FT_UShort  advanceX;
+      FT_UShort  advanceY;
+
+
+      FT_TRACE3(( "Trying to load SVG glyph\n" ));
+      sfnt = (SFNT_Service)( (TT_Face)glyph->face )->sfnt;
+
+      error = sfnt->load_svg_doc( glyph, glyph_index );
+      if ( !error )
+      {
+        TT_Face  face = (TT_Face)glyph->face;
+
+
+        FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
+
+        glyph->format = FT_GLYPH_FORMAT_SVG;
+
+        sfnt->get_metrics( face,
+                           FALSE,
+                           glyph_index,
+                           &leftBearing,
+                           &advanceX );
+        sfnt->get_metrics( face,
+                           TRUE,
+                           glyph_index,
+                           &topBearing,
+                           &advanceY );
+
+        advanceX = (FT_UShort)FT_MulDiv( advanceX,
+                                         glyph->face->size->metrics.x_ppem,
+                                         glyph->face->units_per_EM );
+        advanceY = (FT_UShort)FT_MulDiv( advanceY,
+                                         glyph->face->size->metrics.y_ppem,
+                                         glyph->face->units_per_EM );
+
+        glyph->metrics.horiAdvance = advanceX << 6;
+        glyph->metrics.vertAdvance = advanceY << 6;
+
+        return error;
+      }
+
+      FT_TRACE3(( "Failed to load SVG glyph\n" ));
+    }
+
+    /* return immediately if we only want SVG glyphs */
+    if ( load_flags & FT_LOAD_SVG_ONLY )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
+#endif /* FT_CONFIG_OPTION_SVG */
+
     error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
     if ( error )
       goto Exit;