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>
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
|
|
@ -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_
|
||||
{
|
||||
|
|
|
@ -312,6 +312,31 @@ FT_BEGIN_HEADER
|
|||
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:
|
||||
|
@ -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_ \
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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_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 );
|
||||
|
||||
|
|
|
@ -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) */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
)
|
||||
|
||||
|
||||
|
|
207
src/sfnt/ttsvg.c
207
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 */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue