summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoazin Khatti <moazinkhatri@gmail.com>2019-08-10 14:49:59 +0500
committerMoazin Khatti <moazinkhatri@gmail.com>2019-08-10 16:11:07 +0500
commitce64d9cbf11045895118b732a9c8d4ee83cfae83 (patch)
tree2ad9d12c4eeb060d503be8b712b2c2fad894b0dc
parent92eeba75c408cb655001648889b93f80379b969e (diff)
downloadfreetype2-ce64d9cbf11045895118b732a9c8d4ee83cfae83.tar.gz
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.
-rw-r--r--include/freetype/config/ftheader.h13
-rw-r--r--include/freetype/ftimage.h7
-rw-r--r--include/freetype/internal/ftobjs.h3
-rw-r--r--include/freetype/internal/sfnt.h32
-rw-r--r--include/freetype/otsvg.h91
-rw-r--r--src/base/ftobjs.c42
-rw-r--r--src/cff/cffgload.c47
-rw-r--r--src/sfnt/sfdriver.c16
-rw-r--r--src/sfnt/ttsvg.c207
-rw-r--r--src/sfnt/ttsvg.h4
-rw-r--r--src/truetype/ttgload.c39
11 files changed, 490 insertions, 11 deletions
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index 696d6ba90..55716c2e5 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 face34fe4..86fb04065 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 0c1d3e5bf..2f2050921 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 fbc29d3a2..d09b190aa 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 000000000..5569ce4d6
--- /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 e301f8f11..31fc23936 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 36aa7d1b9..33733896a 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 dec953c4b..8e9a8a005 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 546446b6f..211a63960 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 493d72aa0..c54e04832 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 093eed839..a6ec379ed 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 );