forked from minhngoc25a/freetype2
Very crude way to handle SVG data with only TTF outlined OT fonts. Gonna revert soon.
This commit is contained in:
parent
82f8102da6
commit
b9734fd870
|
@ -312,6 +312,12 @@ FT_BEGIN_HEADER
|
|||
TT_SBit_MetricsRec *ametrics );
|
||||
|
||||
|
||||
/* OT-SVG to be documented later */
|
||||
typedef FT_Error
|
||||
(*TT_Load_Svg_Doc_Func)( FT_GlyphSlot glyph,
|
||||
FT_UInt glyph_index );
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @functype:
|
||||
|
@ -781,6 +787,7 @@ FT_BEGIN_HEADER
|
|||
/* Open Type SVG Support */
|
||||
TT_Load_Table_Func load_svg;
|
||||
TT_Free_Table_Func free_svg;
|
||||
TT_Load_Svg_Doc_Func load_svg_doc;
|
||||
} SFNT_Interface;
|
||||
|
||||
|
||||
|
@ -829,7 +836,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_, \
|
||||
|
@ -871,7 +879,8 @@ FT_BEGIN_HEADER
|
|||
get_name_, \
|
||||
get_name_id_, \
|
||||
load_svg_, \
|
||||
free_svg_ \
|
||||
free_svg_, \
|
||||
load_svg_doc_ \
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -967,8 +967,8 @@ FT_BEGIN_HEADER
|
|||
* This structure/class is defined here because it is common to the
|
||||
* following formats: TTF, OpenType-TT, and OpenType-CFF.
|
||||
*
|
||||
* Note, however, that the classes TT_Size and TT_GlyphSlot are not shared
|
||||
* between font drivers, and are thus defined in `ttobjs.h`.
|
||||
* Note, however, that the classes TT_Size and `TT_GlyphSlot'(not anymore),
|
||||
* are not shared between font drivers, and are thus defined in `ttobjs.h`.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -988,6 +988,32 @@ FT_BEGIN_HEADER
|
|||
*/
|
||||
typedef struct TT_FaceRec_* TT_Face;
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Type:
|
||||
* TT_GlyphSlotRec_
|
||||
*
|
||||
* @Description:
|
||||
* A glyph slot that inherits from FT_GlyphSlotRec_ but adds more fields
|
||||
*
|
||||
*/
|
||||
typedef struct TT_GlyphSlotRec_
|
||||
{
|
||||
FT_GlyphSlotRec root;
|
||||
FT_Byte* svg_document;
|
||||
FT_ULong svg_document_length;
|
||||
} TT_GlyphSlotRec;
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Type:
|
||||
* TT_GlyphSlot
|
||||
*
|
||||
* @Description:
|
||||
* A handle to a TrueType glyph slot object.
|
||||
*/
|
||||
typedef struct TT_GlyphSlotRec_* TT_GlyphSlot;
|
||||
|
||||
|
||||
/* a function type used for the truetype bytecode interpreter hooks */
|
||||
typedef FT_Error
|
||||
|
|
|
@ -1297,8 +1297,9 @@
|
|||
|
||||
tt_face_get_name, /* TT_Get_Name_Func get_name */
|
||||
sfnt_get_name_id, /* TT_Get_Name_ID_Func get_name_id */
|
||||
tt_face_load_svg, /* TT_Load_Table_Func load_svg */
|
||||
tt_face_free_svg /* TT_Free_Table_Func free_svg */
|
||||
tt_face_load_svg, /* TT_Load_Table_Func load_svg */
|
||||
tt_face_free_svg, /* TT_Free_Table_Func free_svg */
|
||||
tt_face_load_svg_doc
|
||||
)
|
||||
|
||||
|
||||
|
|
111
src/sfnt/ttsvg.c
111
src/sfnt/ttsvg.c
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* ttsvg.h
|
||||
* ttsvg.c
|
||||
*
|
||||
* OpenType SVG Color (specification).
|
||||
*
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include <ft2build.h>
|
||||
#include FT_INTERNAL_STREAM_H
|
||||
#include FT_TRUETYPE_TAGS_H
|
||||
#include FT_GZIP_H
|
||||
|
||||
|
||||
#include "ttsvg.h"
|
||||
|
@ -113,3 +114,111 @@
|
|||
FT_FREE( svg );
|
||||
}
|
||||
}
|
||||
|
||||
FT_Error
|
||||
find_doc( FT_Byte* stream,
|
||||
FT_UShort num_entries,
|
||||
FT_UInt glyph_index,
|
||||
FT_ULong *doc_offset,
|
||||
FT_ULong *doc_length )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_UShort start_glyph_id;
|
||||
FT_UShort end_glyph_id;
|
||||
FT_ULong cur_doc_offset;
|
||||
FT_ULong cur_doc_length;
|
||||
|
||||
FT_Bool found = FALSE;
|
||||
FT_UInt i = 0;
|
||||
|
||||
/* For now it's linear search, later convert to binary search */
|
||||
for ( i = 0; i < num_entries; i++)
|
||||
{
|
||||
start_glyph_id = FT_NEXT_USHORT( stream );
|
||||
end_glyph_id = FT_NEXT_USHORT( stream );
|
||||
cur_doc_offset = FT_NEXT_ULONG( stream );
|
||||
cur_doc_length = FT_NEXT_ULONG( stream );
|
||||
|
||||
if ( ( glyph_index >= start_glyph_id) &&
|
||||
( glyph_index <= end_glyph_id ) )
|
||||
{
|
||||
found = TRUE;
|
||||
*doc_offset = cur_doc_offset;
|
||||
*doc_length = cur_doc_length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( found != TRUE )
|
||||
error = FT_THROW( Invalid_Glyph_Index );
|
||||
else
|
||||
error = FT_Err_Ok;
|
||||
return error;
|
||||
}
|
||||
|
||||
FT_LOCAL_DEF(FT_Error)
|
||||
tt_face_load_svg_doc( FT_GlyphSlot glyph_,
|
||||
FT_UInt glyph_index )
|
||||
{
|
||||
|
||||
TT_GlyphSlot glyph = (TT_GlyphSlot) glyph_;
|
||||
|
||||
/* TODO: properly clean stuff here on errors */
|
||||
|
||||
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_ULong uncomp_size;
|
||||
FT_Byte* uncomp_buffer;
|
||||
|
||||
FT_Bool is_gzip_encoded = FALSE;
|
||||
|
||||
FT_Error error = FT_Err_Ok;
|
||||
TT_Face face = (TT_Face)glyph->root.face;
|
||||
FT_Memory memory = face->root.memory;
|
||||
Svg* svg = face->svg;
|
||||
|
||||
/* handle svg being 0x0 situation here */
|
||||
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 );
|
||||
if ( error != FT_Err_Ok )
|
||||
return error;
|
||||
|
||||
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 ) )
|
||||
{
|
||||
is_gzip_encoded = TRUE;
|
||||
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];
|
||||
|
||||
/* TODO: memory allocated here needs to be freed somewhere */
|
||||
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 )
|
||||
{
|
||||
error = FT_THROW( Invalid_Table );
|
||||
return error;
|
||||
}
|
||||
|
||||
glyph->svg_document = uncomp_buffer;
|
||||
glyph->svg_document_length = uncomp_size;
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
glyph->svg_document = doc_list;
|
||||
glyph->svg_document_length = doc_length;
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -2219,7 +2219,8 @@
|
|||
|
||||
FT_BBox bbox;
|
||||
FT_Fixed y_scale;
|
||||
TT_GlyphSlot glyph = loader->glyph;
|
||||
TT_GlyphSlot glyph_ = (TT_GlyphSlot)loader->glyph;
|
||||
FT_GlyphSlot glyph = (FT_GlyphSlot)glyph_;
|
||||
TT_Size size = loader->size;
|
||||
|
||||
|
||||
|
@ -2407,7 +2408,7 @@
|
|||
TT_SBit_MetricsRec sbit_metrics;
|
||||
|
||||
|
||||
face = (TT_Face)glyph->face;
|
||||
face = (TT_Face)(glyph->root.face);
|
||||
sfnt = (SFNT_Service)face->sfnt;
|
||||
stream = face->root.stream;
|
||||
|
||||
|
@ -2416,35 +2417,35 @@
|
|||
glyph_index,
|
||||
(FT_UInt)load_flags,
|
||||
stream,
|
||||
&glyph->bitmap,
|
||||
&(glyph->root.bitmap),
|
||||
&sbit_metrics );
|
||||
if ( !error )
|
||||
{
|
||||
glyph->outline.n_points = 0;
|
||||
glyph->outline.n_contours = 0;
|
||||
(glyph->root).outline.n_points = 0;
|
||||
(glyph->root).outline.n_contours = 0;
|
||||
|
||||
glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64;
|
||||
glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
|
||||
(glyph->root).metrics.width = (FT_Pos)sbit_metrics.width * 64;
|
||||
(glyph->root).metrics.height = (FT_Pos)sbit_metrics.height * 64;
|
||||
|
||||
glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
|
||||
glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
|
||||
glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
|
||||
(glyph->root).metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
|
||||
(glyph->root).metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
|
||||
(glyph->root).metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
|
||||
|
||||
glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
|
||||
glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
|
||||
glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
|
||||
(glyph->root).metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
|
||||
(glyph->root).metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
|
||||
(glyph->root).metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
|
||||
|
||||
glyph->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
(glyph->root).format = FT_GLYPH_FORMAT_BITMAP;
|
||||
|
||||
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
|
||||
{
|
||||
glyph->bitmap_left = sbit_metrics.vertBearingX;
|
||||
glyph->bitmap_top = sbit_metrics.vertBearingY;
|
||||
(glyph->root).bitmap_left = sbit_metrics.vertBearingX;
|
||||
(glyph->root).bitmap_top = sbit_metrics.vertBearingY;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph->bitmap_left = sbit_metrics.horiBearingX;
|
||||
glyph->bitmap_top = sbit_metrics.horiBearingY;
|
||||
(glyph->root).bitmap_left = sbit_metrics.horiBearingX;
|
||||
(glyph->root).bitmap_top = sbit_metrics.horiBearingY;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2453,6 +2454,22 @@
|
|||
|
||||
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
|
||||
|
||||
static FT_Error
|
||||
load_svg_glyph( TT_GlyphSlot glyph,
|
||||
FT_ULong glyph_index )
|
||||
{
|
||||
FT_Error error;
|
||||
TT_Face face;
|
||||
SFNT_Service sfnt;
|
||||
FT_Byte* doc_list;
|
||||
|
||||
face = (TT_Face)(glyph->root).face;
|
||||
sfnt = (SFNT_Service)face->sfnt;
|
||||
|
||||
error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index );
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
tt_loader_init( TT_Loader loader,
|
||||
|
@ -2469,12 +2486,12 @@
|
|||
FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
|
||||
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
|
||||
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)(glyph->root).face );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
face = (TT_Face)glyph->face;
|
||||
face = (TT_Face)(glyph->root.face);
|
||||
stream = face->root.stream;
|
||||
|
||||
FT_ZERO( loader );
|
||||
|
@ -2726,7 +2743,7 @@
|
|||
/* get face's glyph loader */
|
||||
if ( !glyf_table_only )
|
||||
{
|
||||
FT_GlyphLoader gloader = glyph->internal->loader;
|
||||
FT_GlyphLoader gloader = (glyph->root).internal->loader;
|
||||
|
||||
|
||||
FT_GlyphLoader_Rewind( gloader );
|
||||
|
@ -2790,13 +2807,13 @@
|
|||
*/
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
TT_Load_Glyph( TT_Size size,
|
||||
TT_GlyphSlot glyph,
|
||||
TT_GlyphSlot glyph_,
|
||||
FT_UInt glyph_index,
|
||||
FT_Int32 load_flags )
|
||||
{
|
||||
FT_Error error;
|
||||
TT_LoaderRec loader;
|
||||
|
||||
FT_GlyphSlot glyph = (FT_GlyphSlot)glyph_;
|
||||
|
||||
FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
|
||||
|
||||
|
@ -2811,7 +2828,7 @@
|
|||
FT_Fixed y_scale = size->root.metrics.y_scale;
|
||||
|
||||
|
||||
error = load_sbit_image( size, glyph, glyph_index, load_flags );
|
||||
error = load_sbit_image( size, glyph_, glyph_index, load_flags );
|
||||
if ( FT_ERR_EQ( error, Missing_Bitmap ) )
|
||||
{
|
||||
/* the bitmap strike is incomplete and misses the requested glyph; */
|
||||
|
@ -2878,7 +2895,7 @@
|
|||
if ( FT_IS_SCALABLE( glyph->face ) )
|
||||
{
|
||||
/* for the bbox we need the header only */
|
||||
(void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
|
||||
(void)tt_loader_init( &loader, size, glyph_, load_flags, TRUE );
|
||||
(void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
|
||||
tt_loader_done( &loader );
|
||||
glyph->linearHoriAdvance = loader.linear;
|
||||
|
@ -2900,11 +2917,10 @@
|
|||
|
||||
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
|
||||
|
||||
/* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
|
||||
if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
|
||||
/* OT-SVG part here */
|
||||
if ( ( load_flags & FT_LOAD_COLOR ) && ( ((TT_Face)glyph->face)->svg ) )
|
||||
{
|
||||
error = FT_THROW( Invalid_Size_Handle );
|
||||
goto Exit;
|
||||
error = load_svg_glyph( glyph_, glyph_index );
|
||||
}
|
||||
|
||||
if ( load_flags & FT_LOAD_SBITS_ONLY )
|
||||
|
@ -2913,7 +2929,7 @@
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
|
||||
error = tt_loader_init( &loader, size, glyph_, load_flags, FALSE );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
|
|
|
@ -39,21 +39,6 @@ FT_BEGIN_HEADER
|
|||
typedef struct TT_DriverRec_* TT_Driver;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Type:
|
||||
* TT_GlyphSlot
|
||||
*
|
||||
* @Description:
|
||||
* A handle to a TrueType glyph slot object.
|
||||
*
|
||||
* @Note:
|
||||
* This is a direct typedef of FT_GlyphSlot, as there is nothing
|
||||
* specific about the TrueType glyph slot.
|
||||
*/
|
||||
typedef FT_GlyphSlot TT_GlyphSlot;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Struct:
|
||||
|
|
Loading…
Reference in New Issue