freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] ot-svg-clean ce64d9c 1/2: Adds the functionality to load SVG


From: Moazin Khatti
Subject: [freetype2] ot-svg-clean ce64d9c 1/2: Adds the functionality to load SVG documents.
Date: Sat, 10 Aug 2019 13:34:08 -0400 (EDT)

branch: ot-svg-clean
commit ce64d9cbf11045895118b732a9c8d4ee83cfae83
Author: Moazin Khatti <address@hidden>
Commit: Moazin Khatti <address@hidden>

    Adds the functionality to load SVG documents.
    
    SVG document corresponding to a glyphID is fetched and stored
    in an `FT_SVG_Document' structure which is referenced in the
    glyphslot.
    
    * include/freetype/config/ftheader.h: Adds `FT_OTSVG_H'.
    
    * include/freetype/ftimage.h: Adds `FT_GLYPH_FORMAT_SVG'.
    
    * include/freetype/internal/ftobjs.h: Adds `FT_GLYPH_OWN_GZIP_SVG'.
    
    * include/freetype/internal/sfnt.h: Adds `load_svg_doc' and its
    function type `TT_Load_Svg_Doc_Func'.
    
    * include/freetype/otsvg.h: Adds `FT_SVG_Document' and its struct.
    
    * src/base/ftobjs.c: Adds code to allocate and free memory for
    `FT_SVG_Document' in `slot->other'.
    
    * src/cff/cffgload.c: Adds code to load SVG glyph if it's present.
    
    * src/truetype/ttgload.c: Ditto.
    
    * src/sfnt/sfdriver.c: Adds `tt_face_load_svg_doc'.
    
    * src/sfnt/ttsvg.h: Ditto.
    
    * src/sfnt/ttsvg.c: Adds implementation of `tt_face_load_svg_doc'
    and its helper functions.
---
 include/freetype/config/ftheader.h |  13 +++
 include/freetype/ftimage.h         |   7 +-
 include/freetype/internal/ftobjs.h |   3 +-
 include/freetype/internal/sfnt.h   |  32 +++++-
 include/freetype/otsvg.h           |  91 ++++++++++++++++
 src/base/ftobjs.c                  |  42 ++++++++
 src/cff/cffgload.c                 |  47 +++++++++
 src/sfnt/sfdriver.c                |  16 +--
 src/sfnt/ttsvg.c                   | 207 +++++++++++++++++++++++++++++++++++++
 src/sfnt/ttsvg.h                   |   4 +
 src/truetype/ttgload.c             |  39 +++++++
 11 files changed, 490 insertions(+), 11 deletions(-)

diff --git a/include/freetype/config/ftheader.h 
b/include/freetype/config/ftheader.h
index 696d6ba..55716c2 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -550,6 +550,19 @@
   /**************************************************************************
    *
    * @macro:
+   *   FT_OTSVG_H
+   *
+   * @description:
+   *   A macro used in `#include` statements to name the file containing the
+   *   API of OT-SVG support related things.
+   *
+   */
+#define FT_OTSVG_H  <freetype/otsvg.h>
+
+
+  /**************************************************************************
+   *
+   * @macro:
    *   FT_BBOX_H
    *
    * @description:
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index face34f..86fb040 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -732,6 +732,9 @@ FT_BEGIN_HEADER
    *     contours.  Some Type~1 fonts, like those in the Hershey family,
    *     contain glyphs in this format.  These are described as @FT_Outline,
    *     but FreeType isn't currently capable of rendering them correctly.
+   *
+   *   FT_GLYPH_FORMAT_SVG ::
+   *     The glyph is represented by an SVG document in the SVG table.
    */
   typedef enum  FT_Glyph_Format_
   {
@@ -740,7 +743,8 @@ FT_BEGIN_HEADER
     FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),
     FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP,    'b', 'i', 't', 's' ),
     FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE,   'o', 'u', 't', 'l' ),
-    FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER,   'p', 'l', 'o', 't' )
+    FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER,   'p', 'l', 'o', 't' ),
+    FT_IMAGE_TAG( FT_GLYPH_FORMAT_SVG,       's', 'v', 'g', ' ' )
 
   } FT_Glyph_Format;
 
@@ -752,6 +756,7 @@ FT_BEGIN_HEADER
 #define ft_glyph_format_bitmap     FT_GLYPH_FORMAT_BITMAP
 #define ft_glyph_format_outline    FT_GLYPH_FORMAT_OUTLINE
 #define ft_glyph_format_plotter    FT_GLYPH_FORMAT_PLOTTER
+#define ft_glyph_format_svg        FT_GLYPH_FORMAT_SVG
 
 
   /*************************************************************************/
diff --git a/include/freetype/internal/ftobjs.h 
b/include/freetype/internal/ftobjs.h
index 0c1d3e5..2f20509 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -418,7 +418,8 @@ FT_BEGIN_HEADER
    *     initializing the glyph slot.
    */
 
-#define FT_GLYPH_OWN_BITMAP  0x1U
+#define FT_GLYPH_OWN_BITMAP    0x1U
+#define FT_GLYPH_OWN_GZIP_SVG  0x2U
 
   typedef struct  FT_Slot_InternalRec_
   {
diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h
index fbc29d3..d09b190 100644
--- a/include/freetype/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -315,6 +315,31 @@ FT_BEGIN_HEADER
   /**************************************************************************
    *
    * @functype:
+   *   TT_Load_Svg_Doc_Func
+   *
+   * @description:
+   *   Scans the SVG documents list to find the document containing the glyph
+   *   that has the id "glyph<glyph_index>".
+   *
+   * @input:
+   *   glyph ::
+   *     The glyph slot from which pointers to SVG documents list will be
+   *     grabbed.  The results will be stored back in the slot too.
+   *
+   *   glyph_index ::
+   *     The index of the glyph that is to be looked up.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   */
+  typedef FT_Error
+  (*TT_Load_Svg_Doc_Func)( FT_GlyphSlot  glyph,
+                           FT_UInt       glyph_index );
+
+
+  /**************************************************************************
+   *
+   * @functype:
    *   TT_Set_SBit_Strike_Func
    *
    * @description:
@@ -781,6 +806,7 @@ FT_BEGIN_HEADER
     /* OpenType SVG support */
     TT_Load_Table_Func           load_svg;
     TT_Free_Table_Func           free_svg;
+    TT_Load_Svg_Doc_Func         load_svg_doc;
 
   } SFNT_Interface;
 
@@ -830,7 +856,8 @@ FT_BEGIN_HEADER
           get_name_,                     \
           get_name_id_,                  \
           load_svg_,                     \
-          free_svg_ )                    \
+          free_svg_,                     \
+          load_svg_doc_ )                \
   static const SFNT_Interface  class_ =  \
   {                                      \
     goto_table_,                         \
@@ -872,7 +899,8 @@ FT_BEGIN_HEADER
     get_name_,                           \
     get_name_id_,                        \
     load_svg_,                           \
-    free_svg_                            \
+    free_svg_,                           \
+    load_svg_doc_                        \
   };
 
 
diff --git a/include/freetype/otsvg.h b/include/freetype/otsvg.h
new file mode 100644
index 0000000..5569ce4
--- /dev/null
+++ b/include/freetype/otsvg.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+ *
+ * otsvg.h
+ *
+ *   Interface for OT-SVG support related things (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, Werner Lemberg and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSVG_RENDERER_H_
+#define FTSVG_RENDERER_H_
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+FT_BEGIN_HEADER
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_SVG_DocumentRec_
+   *
+   * @description:
+   *   A structure that models one SVG document.
+   *
+   * @fields:
+   *   svg_document ::
+   *     A pointer to the SVG document string.
+   *
+   *   svg_document_length ::
+   *     The length of the SVG document string.
+   *
+   *   metrics ::
+   *     A metrics object storing the size information.
+   *
+   *   units_per_EM ::
+   *     The size of the EM square.
+   *
+   *   start_glyph_id ::
+   *     The starting glyph ID for the glyph range that this document has.
+   *
+   *   end_glyph_id ::
+   *     The ending glyph ID for the glyph range that this document has.
+   *
+   * @note:
+   *   `metrics` and `units_per_EM` might look like repetitions since both
+   *   fields are stored in face object, but they are not; When the slot is
+   *   passed down to a renderer, the renderer can only access the `metrics`
+   *   and `units_per_EM` by `slot->face`. However, when `FT_Glyph_To_Bitmap`
+   *   sets up a dummy object, it has no way to set a `face` object. Thus,
+   *   metrics information and units_per_EM (which is necessary for OT-SVG)
+   *   has to be stored separately.
+   */
+
+  typedef struct FT_SVG_DocumentRec_
+  {
+    FT_Byte*         svg_document;
+    FT_ULong         svg_document_length;
+    FT_Size_Metrics  metrics;
+    FT_UShort        units_per_EM;
+    FT_UShort        start_glyph_id;
+    FT_UShort        end_glyph_id;
+  } FT_SVG_DocumentRec;
+
+  /**************************************************************************
+   *
+   * @type:
+   *   FT_SVG_Document
+   *
+   * @description:
+   *   A handle to a FT_SVG_DocumentRec object.
+   */
+  typedef struct FT_SVG_DocumentRec_*  FT_SVG_Document;
+
+FT_END_HEADER
+#endif
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index e301f8f..31fc239 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -40,6 +40,7 @@
 #include FT_SERVICE_TT_CMAP_H
 #include FT_SERVICE_KERNING_H
 #include FT_SERVICE_TRUETYPE_ENGINE_H
+#include FT_OTSVG_H
 
 #include FT_DRIVER_H
 
@@ -317,6 +318,17 @@
     if ( !error && clazz->init_slot )
       error = clazz->init_slot( slot );
 
+#ifdef FT_CONFIG_OPTION_SVG
+    /* check if SVG table exists allocate the space in slot->other */
+    if ( slot->face->face_flags & FT_FACE_FLAG_SVG )
+    {
+      FT_SVG_Document  document;
+      if ( FT_NEW( document ) )
+        goto Exit;
+      slot->other = document;
+    }
+#endif
+
   Exit:
     return error;
   }
@@ -551,7 +563,23 @@
     slot->subglyphs     = NULL;
     slot->control_data  = NULL;
     slot->control_len   = 0;
+#ifndef FT_CONFIG_OPTION_SVG
     slot->other         = NULL;
+#else
+    if ( !( slot->face->face_flags & FT_FACE_FLAG_SVG ) )
+      slot->other         = NULL;
+    else
+    {
+      if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG )
+      {
+        FT_Memory        memory = slot->face->memory;
+        FT_SVG_Document  doc    = (FT_SVG_Document)slot->other;
+        FT_FREE( doc->svg_document );
+        slot->internal->load_flags &= ~FT_GLYPH_OWN_GZIP_SVG;
+      }
+    }
+#endif
+
     slot->format        = FT_GLYPH_FORMAT_NONE;
 
     slot->linearHoriAdvance = 0;
@@ -569,6 +597,20 @@
     FT_Memory        memory = driver->root.memory;
 
 
+#ifdef FT_CONFIG_OPTION_SVG
+    if ( slot->face->face_flags & FT_FACE_FLAG_SVG )
+    {
+      /* free memory in case svg was there */
+      if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG )
+      {
+        FT_SVG_Document  doc    = (FT_SVG_Document)slot->other;
+        FT_FREE( doc->svg_document );
+        slot->internal->flags &= ~FT_GLYPH_OWN_GZIP_SVG;
+      }
+      FT_FREE( slot->other );
+    }
+#endif
+
     if ( clazz->done_slot )
       clazz->done_slot( slot );
 
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 36aa7d1..3373389 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -347,6 +347,53 @@
     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 ) )
+    {
+      SFNT_Service  sfnt;
+      FT_Short      leftBearing;
+      FT_Short      topBearing;
+      FT_UShort     advanceX;
+      FT_UShort     advanceY;
+
+      if ( ( size->root.metrics.x_ppem < 1 ||
+             size->root.metrics.y_ppem < 1 ) )
+      {
+        error = FT_THROW( Invalid_Size_Handle );
+        return error;
+      }
+
+      FT_TRACE3(( "Attemping 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_Err_Ok )
+      {
+        FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
+        glyph->root.format = FT_GLYPH_FORMAT_SVG;
+        sfnt->get_metrics( face,
+                           FALSE,
+                           glyph_index,
+                           &leftBearing,
+                           &advanceX );
+        sfnt->get_metrics( face,
+                           TRUE,
+                           glyph_index,
+                           &topBearing,
+                           &advanceY );
+        advanceX *= ((float)glyph->root.face->size->metrics.x_ppem)/
+                    ((float)glyph->root.face->units_per_EM) * 64.0;
+        advanceY *= ((float)glyph->root.face->size->metrics.y_ppem)/
+                    ((float)glyph->root.face->units_per_EM) * 64.0;
+        glyph->root.metrics.horiAdvance = advanceX;
+        glyph->root.metrics.vertAdvance = advanceY;
+        return error;
+      }
+      FT_TRACE3(( "Failed to load SVG glyph\n" ));
+    }
+#endif
+
     /* if we have a CID subfont, use its matrix (which has already */
     /* been multiplied with the root matrix)                       */
 
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index dec953c..8e9a8a0 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -1212,18 +1212,18 @@
 #define PUT_EMBEDDED_BITMAPS( a )  NULL
 #endif
 
-#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
-#define PUT_COLOR_LAYERS( a )  a
-#else
-#define PUT_COLOR_LAYERS( a )  NULL
-#endif
-
 #ifdef FT_CONFIG_OPTION_SVG
 #define PUT_SVG_SUPPORT( a )  a
 #else
 #define PUT_SVG_SUPPORT( a )  NULL
 #endif
 
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+#define PUT_COLOR_LAYERS( a )  a
+#else
+#define PUT_COLOR_LAYERS( a )  NULL
+#endif
+
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
 #define PUT_PS_NAMES( a )  a
 #else
@@ -1308,8 +1308,10 @@
 
     PUT_SVG_SUPPORT( tt_face_load_svg ),
                             /* TT_Load_Table_Func      load_svg        */
-    PUT_SVG_SUPPORT( tt_face_free_svg )
+    PUT_SVG_SUPPORT( tt_face_free_svg ),
                             /* TT_Free_Table_Func      free_svg        */
+    PUT_SVG_SUPPORT( tt_face_load_svg_doc )
+                            /* TT_Load_Svg_Doc_Func    load_svg_doc    */
   )
 
 
diff --git a/src/sfnt/ttsvg.c b/src/sfnt/ttsvg.c
index 546446b..211a639 100644
--- a/src/sfnt/ttsvg.c
+++ b/src/sfnt/ttsvg.c
@@ -28,6 +28,8 @@
 #include FT_INTERNAL_STREAM_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_TRUETYPE_TAGS_H
+#include FT_GZIP_H
+#include FT_OTSVG_H
 
 #ifdef FT_CONFIG_OPTION_SVG
 
@@ -121,6 +123,211 @@
     }
   }
 
+  typedef struct Svg_doc_
+  {
+    FT_UShort  start_glyph_id;
+    FT_UShort  end_glyph_id;
+    FT_ULong   offset;
+    FT_ULong   length;
+  } Svg_doc;
+
+  static Svg_doc
+  extract_svg_doc( FT_Byte*  stream )
+  {
+    Svg_doc  doc;
+    doc.start_glyph_id = FT_NEXT_USHORT( stream );
+    doc.end_glyph_id   = FT_NEXT_USHORT( stream );
+    doc.offset = FT_NEXT_ULONG( stream );
+    doc.length = FT_NEXT_ULONG( stream );
+    return doc;
+  }
+
+  static FT_Int
+  compare_svg_doc( Svg_doc  doc,
+                   FT_UInt  glyph_index )
+  {
+    if ( glyph_index < doc.start_glyph_id )
+      return -1;
+    else if ( glyph_index > doc.end_glyph_id )
+      return 1;
+    else
+      return 0;
+  }
+
+  static FT_Error
+  find_doc( FT_Byte*   stream,
+            FT_UShort  num_entries,
+            FT_UInt    glyph_index,
+            FT_ULong   *doc_offset,
+            FT_ULong   *doc_length,
+            FT_UShort  *start_glyph,
+            FT_UShort  *end_glyph )
+  {
+    FT_Error   error;
+    Svg_doc    start_doc;
+    Svg_doc    mid_doc;
+    Svg_doc    end_doc;
+
+    FT_Bool  found       = FALSE;
+    FT_UInt  i           = 0;
+    FT_UInt  start_index = 0;
+    FT_UInt  end_index   = num_entries - 1;
+    FT_Int   comp_res;
+
+
+    /* search algo */
+    if ( num_entries == 0 )
+    {
+      error = FT_THROW( Invalid_Table );
+      return error;
+    }
+
+    FT_TRACE6(( "--- binary search glyph id: %d ---\n", glyph_index ));
+
+    start_doc = extract_svg_doc( stream + start_index * 12 );
+    end_doc   = extract_svg_doc( stream + end_index * 12 );
+
+    FT_TRACE6(( "--- start glyph ---\n" ));
+    FT_TRACE6(( "start_id: %d\n", start_doc.start_glyph_id ));
+    FT_TRACE6(( "end_id: %d\n", start_doc.end_glyph_id ));
+    FT_TRACE6(( "--- end glyph ---\n" ));
+    FT_TRACE6(( "start_id: %d\n", end_doc.start_glyph_id ));
+    FT_TRACE6(( "end_id: %d\n", end_doc.end_glyph_id ));
+    if ( ( compare_svg_doc( start_doc, glyph_index ) == -1 ) ||
+         ( compare_svg_doc( end_doc, glyph_index ) == 1 ) )
+    {
+      error = FT_THROW( Invalid_Glyph_Index );
+      return error;
+    }
+
+    while ( start_index <= end_index )
+    {
+      i = ( start_index + end_index ) / 2;
+      mid_doc = extract_svg_doc( stream + i * 12 );
+      FT_TRACE6(( "--- current glyph ---\n" ));
+      FT_TRACE6(( "start_id: %d\n", mid_doc.start_glyph_id ));
+      FT_TRACE6(( "end_id: %d\n", mid_doc.end_glyph_id ));
+      comp_res = compare_svg_doc( mid_doc, glyph_index );
+      if ( comp_res == 1 )
+      {
+        start_index = i + 1;
+        start_doc = extract_svg_doc( stream + start_index * 4 );
+        FT_TRACE6(( "RIGHT\n" ));
+      }
+      else if ( comp_res == -1 )
+      {
+        end_index = i - 1;
+        end_doc = extract_svg_doc( stream + end_index * 4 );
+        FT_TRACE6(( "LEFT\n" ));
+      }
+      else
+      {
+        found = TRUE;
+        FT_TRACE5(( "FOUND\n" ));
+        break;
+      }
+    }
+
+    FT_TRACE5(( "--- binary search end ---\n" ));
+    /* search algo end */
+    if ( found != TRUE )
+    {
+      FT_TRACE5(( "NOT FOUND\n" ));
+      error = FT_THROW( Invalid_Glyph_Index );
+    }
+    else
+    {
+      *doc_offset = mid_doc.offset;
+      *doc_length = mid_doc.length;
+      *start_glyph = mid_doc.start_glyph_id;
+      *end_glyph   = mid_doc.end_glyph_id;
+      error = FT_Err_Ok;
+    }
+    return error;
+  }
+
+  FT_LOCAL_DEF( FT_Error )
+  tt_face_load_svg_doc( FT_GlyphSlot  glyph,
+                        FT_UInt       glyph_index )
+  {
+    FT_Byte*   doc_list;             /* Pointer to the Svg Document List */
+    FT_UShort  num_entries;          /* Total no of entires in doc list  */
+
+    FT_ULong   doc_offset;
+    FT_ULong   doc_length;
+    FT_UShort  start_glyph_id;
+    FT_UShort  end_glyph_id;
+
+    FT_ULong   uncomp_size;
+    FT_Byte*   uncomp_buffer;
+
+    FT_Error   error  = FT_Err_Ok;
+    TT_Face    face   = (TT_Face)glyph->face;
+    FT_Memory  memory = face->root.memory;
+    Svg*       svg    = face->svg;
+
+    FT_SVG_Document  svg_document = glyph->other;
+
+    FT_ASSERT( !( svg == NULL ) );
+
+    doc_list     = svg->svg_doc_list;
+    num_entries  = FT_NEXT_USHORT( doc_list );
+
+    error = find_doc( doc_list, num_entries, glyph_index,
+                                &doc_offset, &doc_length,
+                                &start_glyph_id, &end_glyph_id );
+    if ( error != FT_Err_Ok )
+      goto Exit;
+
+    doc_list = svg->svg_doc_list;   /* Reset to so we can use it again */
+    doc_list = (FT_Byte*)( doc_list + doc_offset );
+
+    if( ( doc_list[0] == 0x1F ) && ( doc_list[1] == 0x8B )
+                                && ( doc_list[2] == 0x08 ) )
+    {
+      /* get the size of the orignal document. This helps in alotting the
+       * buffer to accomodate the uncompressed version. The last 4 bytes
+       * of the compressed document are equal to orignal_size modulo 2^32.
+       * Since SVG docs will be lesser in size then 2^32, we can use this
+       * accurately. The four bytes are stored in little-endian format.
+       */
+      FT_TRACE4(( "SVG document found is GZIP compressed\n" ));
+      uncomp_size = (FT_ULong)doc_list[doc_length - 1] << 24 |
+                    (FT_ULong)doc_list[doc_length - 2] << 16 |
+                    (FT_ULong)doc_list[doc_length - 3] << 8  |
+                    (FT_ULong)doc_list[doc_length - 4];
+
+      uncomp_buffer = (FT_Byte*) memory->alloc( memory, uncomp_size );
+      error = FT_Gzip_Uncompress( memory, uncomp_buffer, &uncomp_size,
+                                          doc_list,      doc_length  );
+      if ( error != FT_Err_Ok )
+      {
+        memory->free( memory, uncomp_buffer );
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+      glyph->internal->flags |= FT_GLYPH_OWN_GZIP_SVG;
+      doc_list   = uncomp_buffer;
+      doc_length = uncomp_size;
+    }
+
+    svg_document->svg_document        = doc_list;
+    svg_document->svg_document_length = doc_length;
+    svg_document->metrics             = glyph->face->size->metrics;
+    svg_document->units_per_EM        = glyph->face->units_per_EM;
+    svg_document->start_glyph_id      = start_glyph_id;
+    svg_document->end_glyph_id        = end_glyph_id;
+
+    FT_TRACE5(( "start_glyph_id: %d\n", start_glyph_id ));
+    FT_TRACE5(( "end_glyph_id:   %d\n", end_glyph_id ));
+    FT_TRACE5(( "svg_document:\n%.*s\n", doc_length, doc_list ));
+
+    glyph->other = svg_document;
+
+Exit:
+    return error;
+  }
+
 #else /* !FT_CONFIG_OPTION_SVG */
 
   /* ANSI C doesn't like empty source files */
diff --git a/src/sfnt/ttsvg.h b/src/sfnt/ttsvg.h
index 493d72a..c54e048 100644
--- a/src/sfnt/ttsvg.h
+++ b/src/sfnt/ttsvg.h
@@ -29,6 +29,10 @@ FT_BEGIN_HEADER
   FT_LOCAL( void )
   tt_face_free_svg( TT_Face    face );
 
+  FT_LOCAL( FT_Error )
+  tt_face_load_svg_doc( FT_GlyphSlot  glyph,
+                        FT_UInt       glyph_index );
+
 FT_END_HEADER
 
 #endif /* __TTSVG_H__ */
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 093eed8..a6ec379 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -2907,6 +2907,45 @@
       goto Exit;
     }
 
+#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(( "Attemping to load SVG glyph\n" ));
+      sfnt = (SFNT_Service)((TT_Face)glyph->face)->sfnt;
+      error = sfnt->load_svg_doc( glyph, glyph_index );
+      if( error == FT_Err_Ok )
+      {
+        FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
+        glyph->format = FT_GLYPH_FORMAT_SVG;
+        sfnt->get_metrics( (TT_Face)glyph->face,
+                           FALSE,
+                           glyph_index,
+                           &leftBearing,
+                           &advanceX );
+        sfnt->get_metrics( (TT_Face)glyph->face,
+                           TRUE,
+                           glyph_index,
+                           &topBearing,
+                           &advanceY );
+        advanceX *= ((float)glyph->face->size->metrics.x_ppem)/
+                    ((float)glyph->face->units_per_EM) * 64.0;
+        advanceY *= ((float)glyph->face->size->metrics.y_ppem)/
+                    ((float)glyph->face->units_per_EM) * 64.0;
+        glyph->metrics.horiAdvance = advanceX;
+        glyph->metrics.vertAdvance = advanceY;
+        return error;
+      }
+      FT_TRACE3(( "Failed to load SVG glyph\n" ));
+    }
+#endif
+
     if ( load_flags & FT_LOAD_SBITS_ONLY )
     {
       error = FT_THROW( Invalid_Argument );



reply via email to

[Prev in Thread] Current Thread [Next in Thread]