forked from minhngoc25a/freetype2
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.
This commit is contained in:
parent
92eeba75c4
commit
ce64d9cbf1
|
@ -547,6 +547,19 @@
|
||||||
#define FT_BITMAP_H <freetype/ftbitmap.h>
|
#define FT_BITMAP_H <freetype/ftbitmap.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* @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:
|
* @macro:
|
||||||
|
|
|
@ -732,6 +732,9 @@ FT_BEGIN_HEADER
|
||||||
* contours. Some Type~1 fonts, like those in the Hershey family,
|
* contours. Some Type~1 fonts, like those in the Hershey family,
|
||||||
* contain glyphs in this format. These are described as @FT_Outline,
|
* contain glyphs in this format. These are described as @FT_Outline,
|
||||||
* but FreeType isn't currently capable of rendering them correctly.
|
* 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_
|
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_COMPOSITE, 'c', 'o', 'm', 'p' ),
|
||||||
FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ),
|
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_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;
|
} FT_Glyph_Format;
|
||||||
|
|
||||||
|
@ -752,6 +756,7 @@ FT_BEGIN_HEADER
|
||||||
#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
|
#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
|
||||||
#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE
|
#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE
|
||||||
#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER
|
#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER
|
||||||
|
#define ft_glyph_format_svg FT_GLYPH_FORMAT_SVG
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
|
@ -418,7 +418,8 @@ FT_BEGIN_HEADER
|
||||||
* initializing the glyph slot.
|
* 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_
|
typedef struct FT_Slot_InternalRec_
|
||||||
{
|
{
|
||||||
|
|
|
@ -312,6 +312,31 @@ FT_BEGIN_HEADER
|
||||||
TT_SBit_MetricsRec *ametrics );
|
TT_SBit_MetricsRec *ametrics );
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* @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:
|
* @functype:
|
||||||
|
@ -781,6 +806,7 @@ FT_BEGIN_HEADER
|
||||||
/* OpenType SVG support */
|
/* OpenType SVG support */
|
||||||
TT_Load_Table_Func load_svg;
|
TT_Load_Table_Func load_svg;
|
||||||
TT_Free_Table_Func free_svg;
|
TT_Free_Table_Func free_svg;
|
||||||
|
TT_Load_Svg_Doc_Func load_svg_doc;
|
||||||
|
|
||||||
} SFNT_Interface;
|
} SFNT_Interface;
|
||||||
|
|
||||||
|
@ -830,7 +856,8 @@ FT_BEGIN_HEADER
|
||||||
get_name_, \
|
get_name_, \
|
||||||
get_name_id_, \
|
get_name_id_, \
|
||||||
load_svg_, \
|
load_svg_, \
|
||||||
free_svg_ ) \
|
free_svg_, \
|
||||||
|
load_svg_doc_ ) \
|
||||||
static const SFNT_Interface class_ = \
|
static const SFNT_Interface class_ = \
|
||||||
{ \
|
{ \
|
||||||
goto_table_, \
|
goto_table_, \
|
||||||
|
@ -872,7 +899,8 @@ FT_BEGIN_HEADER
|
||||||
get_name_, \
|
get_name_, \
|
||||||
get_name_id_, \
|
get_name_id_, \
|
||||||
load_svg_, \
|
load_svg_, \
|
||||||
free_svg_ \
|
free_svg_, \
|
||||||
|
load_svg_doc_ \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -40,6 +40,7 @@
|
||||||
#include FT_SERVICE_TT_CMAP_H
|
#include FT_SERVICE_TT_CMAP_H
|
||||||
#include FT_SERVICE_KERNING_H
|
#include FT_SERVICE_KERNING_H
|
||||||
#include FT_SERVICE_TRUETYPE_ENGINE_H
|
#include FT_SERVICE_TRUETYPE_ENGINE_H
|
||||||
|
#include FT_OTSVG_H
|
||||||
|
|
||||||
#include FT_DRIVER_H
|
#include FT_DRIVER_H
|
||||||
|
|
||||||
|
@ -317,6 +318,17 @@
|
||||||
if ( !error && clazz->init_slot )
|
if ( !error && clazz->init_slot )
|
||||||
error = clazz->init_slot( 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:
|
Exit:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -551,7 +563,23 @@
|
||||||
slot->subglyphs = NULL;
|
slot->subglyphs = NULL;
|
||||||
slot->control_data = NULL;
|
slot->control_data = NULL;
|
||||||
slot->control_len = 0;
|
slot->control_len = 0;
|
||||||
|
#ifndef FT_CONFIG_OPTION_SVG
|
||||||
slot->other = NULL;
|
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->format = FT_GLYPH_FORMAT_NONE;
|
||||||
|
|
||||||
slot->linearHoriAdvance = 0;
|
slot->linearHoriAdvance = 0;
|
||||||
|
@ -569,6 +597,20 @@
|
||||||
FT_Memory memory = driver->root.memory;
|
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 )
|
if ( clazz->done_slot )
|
||||||
clazz->done_slot( slot );
|
clazz->done_slot( slot );
|
||||||
|
|
||||||
|
|
|
@ -347,6 +347,53 @@
|
||||||
if ( load_flags & FT_LOAD_SBITS_ONLY )
|
if ( load_flags & FT_LOAD_SBITS_ONLY )
|
||||||
return FT_THROW( Invalid_Argument );
|
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 */
|
/* if we have a CID subfont, use its matrix (which has already */
|
||||||
/* been multiplied with the root matrix) */
|
/* been multiplied with the root matrix) */
|
||||||
|
|
||||||
|
|
|
@ -1212,18 +1212,18 @@
|
||||||
#define PUT_EMBEDDED_BITMAPS( a ) NULL
|
#define PUT_EMBEDDED_BITMAPS( a ) NULL
|
||||||
#endif
|
#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
|
#ifdef FT_CONFIG_OPTION_SVG
|
||||||
#define PUT_SVG_SUPPORT( a ) a
|
#define PUT_SVG_SUPPORT( a ) a
|
||||||
#else
|
#else
|
||||||
#define PUT_SVG_SUPPORT( a ) NULL
|
#define PUT_SVG_SUPPORT( a ) NULL
|
||||||
#endif
|
#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
|
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
|
||||||
#define PUT_PS_NAMES( a ) a
|
#define PUT_PS_NAMES( a ) a
|
||||||
#else
|
#else
|
||||||
|
@ -1308,8 +1308,10 @@
|
||||||
|
|
||||||
PUT_SVG_SUPPORT( tt_face_load_svg ),
|
PUT_SVG_SUPPORT( tt_face_load_svg ),
|
||||||
/* TT_Load_Table_Func 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 */
|
/* TT_Free_Table_Func free_svg */
|
||||||
|
PUT_SVG_SUPPORT( tt_face_load_svg_doc )
|
||||||
|
/* TT_Load_Svg_Doc_Func load_svg_doc */
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
207
src/sfnt/ttsvg.c
207
src/sfnt/ttsvg.c
|
@ -28,6 +28,8 @@
|
||||||
#include FT_INTERNAL_STREAM_H
|
#include FT_INTERNAL_STREAM_H
|
||||||
#include FT_INTERNAL_OBJECTS_H
|
#include FT_INTERNAL_OBJECTS_H
|
||||||
#include FT_TRUETYPE_TAGS_H
|
#include FT_TRUETYPE_TAGS_H
|
||||||
|
#include FT_GZIP_H
|
||||||
|
#include FT_OTSVG_H
|
||||||
|
|
||||||
#ifdef FT_CONFIG_OPTION_SVG
|
#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 */
|
#else /* !FT_CONFIG_OPTION_SVG */
|
||||||
|
|
||||||
/* ANSI C doesn't like empty source files */
|
/* ANSI C doesn't like empty source files */
|
||||||
|
|
|
@ -29,6 +29,10 @@ FT_BEGIN_HEADER
|
||||||
FT_LOCAL( void )
|
FT_LOCAL( void )
|
||||||
tt_face_free_svg( TT_Face face );
|
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
|
FT_END_HEADER
|
||||||
|
|
||||||
#endif /* __TTSVG_H__ */
|
#endif /* __TTSVG_H__ */
|
||||||
|
|
|
@ -2907,6 +2907,45 @@
|
||||||
goto Exit;
|
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 )
|
if ( load_flags & FT_LOAD_SBITS_ONLY )
|
||||||
{
|
{
|
||||||
error = FT_THROW( Invalid_Argument );
|
error = FT_THROW( Invalid_Argument );
|
||||||
|
|
Loading…
Reference in New Issue