diff options
Diffstat (limited to 'src/3rdparty/freetype/src/sfnt/sfwoff2.c')
-rw-r--r-- | src/3rdparty/freetype/src/sfnt/sfwoff2.c | 144 |
1 files changed, 99 insertions, 45 deletions
diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff2.c b/src/3rdparty/freetype/src/sfnt/sfwoff2.c index 5c8202f823..b2855b8e72 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff2.c +++ b/src/3rdparty/freetype/src/sfnt/sfwoff2.c @@ -4,7 +4,7 @@ * * WOFF2 format management (base). * - * Copyright (C) 2019-2020 by + * Copyright (C) 2019-2022 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,8 +26,6 @@ #include <brotli/decode.h> -#endif - /************************************************************************** * @@ -86,6 +84,8 @@ #define BBOX_STREAM 5 #define INSTRUCTION_STREAM 6 +#define HAVE_OVERLAP_SIMPLE_BITMAP 0x1 + static void stream_close( FT_Stream stream ) @@ -96,20 +96,19 @@ FT_FREE( stream->base ); stream->size = 0; - stream->base = NULL; stream->close = NULL; } - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_tags( const void* a, const void* b ) { WOFF2_Table table1 = *(WOFF2_Table*)a; WOFF2_Table table2 = *(WOFF2_Table*)b; - FT_ULong tag1 = table1->Tag; - FT_ULong tag2 = table2->Tag; + FT_Tag tag1 = table1->Tag; + FT_Tag tag2 = table2->Tag; if ( tag1 > tag2 ) @@ -316,8 +315,6 @@ const FT_Byte* src, FT_ULong src_size ) { -#ifdef FT_CONFIG_OPTION_USE_BROTLI - /* this cast is only of importance on 32bit systems; */ /* we don't validate it */ FT_Offset uncompressed_size = (FT_Offset)dst_size; @@ -338,20 +335,13 @@ FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" )); return FT_Err_Ok; - -#else /* !FT_CONFIG_OPTION_USE_BROTLI */ - - FT_ERROR(( "woff2_decompress: Brotli support not available.\n" )); - return FT_THROW( Unimplemented_Feature ); - -#endif /* !FT_CONFIG_OPTION_USE_BROTLI */ } static WOFF2_Table find_table( WOFF2_Table* tables, FT_UShort num_tables, - FT_ULong tag ) + FT_Tag tag ) { FT_Int i; @@ -534,6 +524,7 @@ const WOFF2_Point points, FT_UShort n_contours, FT_UShort instruction_len, + FT_Bool have_overlap, FT_Byte* dst, FT_ULong dst_size, FT_ULong* glyph_size ) @@ -561,6 +552,9 @@ FT_Int dy = point.y - last_y; + if ( i == 0 && have_overlap ) + flag |= GLYF_OVERLAP_SIMPLE; + if ( dx == 0 ) flag |= GLYF_THIS_X_IS_SAME; else if ( dx > -256 && dx < 256 ) @@ -790,7 +784,7 @@ goto Fail; loca_buf_size = loca_values_size * offset_size; - if ( FT_NEW_ARRAY( loca_buf, loca_buf_size ) ) + if ( FT_QNEW_ARRAY( loca_buf, loca_buf_size ) ) goto Fail; dst = loca_buf; @@ -845,15 +839,18 @@ FT_UInt num_substreams = 7; + FT_UShort option_flags; FT_UShort num_glyphs; FT_UShort index_format; FT_ULong expected_loca_length; FT_UInt offset; FT_UInt i; FT_ULong points_size; - FT_ULong bitmap_length; FT_ULong glyph_buf_size; FT_ULong bbox_bitmap_offset; + FT_ULong bbox_bitmap_length; + FT_ULong overlap_bitmap_offset = 0; + FT_ULong overlap_bitmap_length = 0; const FT_ULong glyf_start = *out_offset; FT_ULong dest_offset = *out_offset; @@ -869,15 +866,17 @@ if ( FT_NEW_ARRAY( substreams, num_substreams ) ) goto Fail; - if ( FT_STREAM_SKIP( 4 ) ) + if ( FT_STREAM_SKIP( 2 ) ) + goto Fail; + if ( FT_READ_USHORT( option_flags ) ) goto Fail; if ( FT_READ_USHORT( num_glyphs ) ) goto Fail; if ( FT_READ_USHORT( index_format ) ) goto Fail; - FT_TRACE4(( "num_glyphs = %u; index_format = %u\n", - num_glyphs, index_format )); + FT_TRACE4(( "option_flags = %u; num_glyphs = %u; index_format = %u\n", + option_flags, num_glyphs, index_format )); info->num_glyphs = num_glyphs; @@ -890,7 +889,7 @@ if ( info->loca_table->dst_length != expected_loca_length ) goto Fail; - offset = ( 2 + num_substreams ) * 4; + offset = 2 + 2 + 2 + 2 + ( num_substreams * 4 ); if ( offset > info->glyf_table->TransformLength ) goto Fail; @@ -913,6 +912,20 @@ offset += substream_size; } + if ( option_flags & HAVE_OVERLAP_SIMPLE_BITMAP ) + { + /* Size of overlapBitmap = floor((numGlyphs + 7) / 8) */ + overlap_bitmap_length = ( num_glyphs + 7U ) >> 3; + if ( overlap_bitmap_length > info->glyf_table->TransformLength - offset ) + goto Fail; + + overlap_bitmap_offset = pos + offset; + + FT_TRACE5(( " Overlap bitmap: offset = %lu; size = %lu;\n", + overlap_bitmap_offset, overlap_bitmap_length )); + offset += overlap_bitmap_length; + } + if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) ) goto Fail; @@ -920,8 +933,9 @@ bbox_bitmap_offset = substreams[BBOX_STREAM].offset; /* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */ - bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2; - substreams[BBOX_STREAM].offset += bitmap_length; + bbox_bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2; + /* bboxStreamSize is the combined size of bboxBitmap and bboxStream. */ + substreams[BBOX_STREAM].offset += bbox_bitmap_length; glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF; if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) ) @@ -959,7 +973,7 @@ /* composite glyph */ FT_Bool have_instructions = FALSE; FT_UShort instruction_size = 0; - FT_ULong composite_size; + FT_ULong composite_size = 0; FT_ULong size_needed; FT_Byte* pointer = NULL; @@ -1037,8 +1051,11 @@ FT_ULong flag_size; FT_ULong triplet_size; FT_ULong triplet_bytes_used; - FT_Byte* flags_buf = NULL; - FT_Byte* triplet_buf = NULL; + FT_Bool have_overlap = FALSE; + FT_Byte overlap_bitmap; + FT_ULong overlap_offset; + FT_Byte* flags_buf = NULL; + FT_Byte* triplet_buf = NULL; FT_UShort instruction_size; FT_ULong size_needed; FT_Int end_point; @@ -1047,6 +1064,17 @@ FT_Byte* pointer = NULL; + /* Set `have_overlap`. */ + if ( overlap_bitmap_offset ) + { + overlap_offset = overlap_bitmap_offset + ( i >> 3 ); + if ( FT_STREAM_SEEK( overlap_offset ) || + FT_READ_BYTE( overlap_bitmap ) ) + goto Fail; + if ( overlap_bitmap & ( 0x80 >> ( i & 7 ) ) ) + have_overlap = TRUE; + } + if ( FT_NEW_ARRAY( n_points_arr, n_contours ) ) goto Fail; @@ -1167,6 +1195,7 @@ points, n_contours, instruction_size, + have_overlap, glyph_buf, glyph_buf_size, &glyph_size ) ) @@ -1852,11 +1881,10 @@ FT_NEW_ARRAY( indices, woff2.num_tables ) ) goto Exit; - FT_TRACE2(( - "\n" - " tag flags transform origLen transformLen offset\n" - " -----------------------------------------------------------\n" )); - /* " XXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX" */ + FT_TRACE2(( "\n" )); + FT_TRACE2(( " tag flags transform origLen transformLen offset\n" )); + FT_TRACE2(( " -----------------------------------------------------------\n" )); + /* " XXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX" */ for ( nn = 0; nn < woff2.num_tables; nn++ ) { @@ -2076,7 +2104,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.metaOffset + woff2.metaLength); + file_offset = ROUND4( woff2.metaOffset + woff2.metaLength ); } if ( woff2.privOffset ) @@ -2086,7 +2114,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.privOffset + woff2.privLength); + file_offset = ROUND4( woff2.privOffset + woff2.privLength ); } if ( file_offset != ( ROUND4( woff2.length ) ) ) @@ -2098,7 +2126,7 @@ /* Validate requested face index. */ *num_faces = woff2.num_fonts; /* value -(N+1) requests information on index N */ - if ( *face_instance_index < 0 ) + if ( *face_instance_index < 0 && face_index > 0 ) face_index--; if ( face_index >= woff2.num_fonts ) @@ -2119,8 +2147,8 @@ /* Create a temporary array. */ - if ( FT_NEW_ARRAY( temp_indices, - ttc_font->num_tables ) ) + if ( FT_QNEW_ARRAY( temp_indices, + ttc_font->num_tables ) ) goto Exit; FT_TRACE4(( "Storing tables for TTC face index %d.\n", face_index )); @@ -2128,9 +2156,9 @@ temp_indices[nn] = indices[ttc_font->table_indices[nn]]; /* Resize array to required size. */ - if ( FT_RENEW_ARRAY( indices, - woff2.num_tables, - ttc_font->num_tables ) ) + if ( FT_QRENEW_ARRAY( indices, + woff2.num_tables, + ttc_font->num_tables ) ) goto Exit; for ( nn = 0; nn < ttc_font->num_tables; nn++ ) @@ -2170,8 +2198,8 @@ } /* Write sfnt header. */ - if ( FT_ALLOC( sfnt, sfnt_size ) || - FT_NEW( sfnt_stream ) ) + if ( FT_QALLOC( sfnt, sfnt_size ) || + FT_NEW( sfnt_stream ) ) goto Exit; sfnt_header = sfnt; @@ -2209,6 +2237,25 @@ sizeof ( WOFF2_Table ), compare_tags ); + /* reject fonts that have multiple tables with the same tag */ + for ( nn = 1; nn < woff2.num_tables; nn++ ) + { + FT_Tag tag = indices[nn]->Tag; + + + if ( tag == indices[nn - 1]->Tag ) + { + FT_ERROR(( "woff2_open_font:" + " multiple tables with tag `%c%c%c%c'.\n", + (FT_Char)( tag >> 24 ), + (FT_Char)( tag >> 16 ), + (FT_Char)( tag >> 8 ), + (FT_Char)( tag ) )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + } + if ( woff2.uncompressed_size < 1 ) { error = FT_THROW( Invalid_Table ); @@ -2223,8 +2270,8 @@ } /* Allocate memory for uncompressed table data. */ - if ( FT_ALLOC( uncompressed_buf, woff2.uncompressed_size ) || - FT_FRAME_ENTER( woff2.totalCompressedSize ) ) + if ( FT_QALLOC( uncompressed_buf, woff2.uncompressed_size ) || + FT_FRAME_ENTER( woff2.totalCompressedSize ) ) goto Exit; /* Uncompress the stream. */ @@ -2333,5 +2380,12 @@ #undef BBOX_STREAM #undef INSTRUCTION_STREAM +#else /* !FT_CONFIG_OPTION_USE_BROTLI */ + + /* ANSI C doesn't like empty source files */ + typedef int _sfwoff2_dummy; + +#endif /* !FT_CONFIG_OPTION_USE_BROTLI */ + /* END */ |