From 68d1cab0e16a1925584f5de7c5e0cd78fa811584 Mon Sep 17 00:00:00 2001 From: Moazin Khatti Date: Sun, 9 Jun 2019 17:52:46 +0500 Subject: [PATCH] Very crude way to handle SVG data with only TTF outlined OT fonts. Gonna revert soon. --- include/freetype/internal/sfnt.h | 13 +++- include/freetype/internal/tttypes.h | 30 +++++++- src/sfnt/sfdriver.c | 5 +- src/sfnt/ttsvg.c | 111 +++++++++++++++++++++++++++- src/sfnt/ttsvg.h | 4 + src/truetype/ttgload.c | 76 +++++++++++-------- src/truetype/ttobjs.h | 15 ---- 7 files changed, 202 insertions(+), 52 deletions(-) diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h index 94f512270..996cae895 100644 --- a/include/freetype/internal/sfnt.h +++ b/include/freetype/internal/sfnt.h @@ -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_ \ }; diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 42a921fe7..9ec8a1c96 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -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 diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index 11148b2cf..cff8ad69d 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -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 ) diff --git a/src/sfnt/ttsvg.c b/src/sfnt/ttsvg.c index 0ebe162e7..27e82968d 100644 --- a/src/sfnt/ttsvg.c +++ b/src/sfnt/ttsvg.c @@ -1,6 +1,6 @@ /**************************************************************************** * - * ttsvg.h + * ttsvg.c * * OpenType SVG Color (specification). * @@ -27,6 +27,7 @@ #include #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; + } + + diff --git a/src/sfnt/ttsvg.h b/src/sfnt/ttsvg.h index 1c6413be5..186d4c8e0 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 a04684086..6b2bb697a 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -2204,7 +2204,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; @@ -2392,7 +2393,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; @@ -2401,35 +2402,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; } } @@ -2438,6 +2439,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, @@ -2454,12 +2471,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 ); @@ -2711,7 +2728,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 ); @@ -2775,13 +2792,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 )); @@ -2796,7 +2813,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; */ @@ -2863,7 +2880,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; @@ -2885,11 +2902,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 ) @@ -2898,7 +2914,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; diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h index 9fc654d5d..d131a9a86 100644 --- a/src/truetype/ttobjs.h +++ b/src/truetype/ttobjs.h @@ -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: