From 54d9993505557af909d92291e1db549a2d4643e8 Mon Sep 17 00:00:00 2001 From: Dave Arnold Date: Tue, 18 Oct 2016 21:20:19 -0700 Subject: [PATCH] Corrections to parse fonts following 1.8 spec. INDEX count for CFF2 is 32 bits, while CFF is 16 bits This means INDEX header size is either 5 or 3 bytes. CFF2 header size is 5 bytes, while CFF is 4 bytes. In CFF2, offSize field is length of the Top DICT data and is 16 bits. Blend operator has changed from 31 to 23. --- src/cff/cffload.c | 63 ++++++++++++++++++++++++++++++---------------- src/cff/cfftoken.h | 2 +- src/cff/cfftypes.h | 4 ++- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/cff/cffload.c b/src/cff/cffload.c index 1342368e6..112a02107 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -225,19 +225,33 @@ static FT_Error cff_index_init( CFF_Index idx, FT_Stream stream, - FT_Bool load ) + FT_Bool load, + FT_Bool cff2 ) { FT_Error error; FT_Memory memory = stream->memory; - FT_UShort count; + FT_UInt count; FT_MEM_ZERO( idx, sizeof ( *idx ) ); idx->stream = stream; idx->start = FT_STREAM_POS(); - if ( !FT_READ_USHORT( count ) && - count > 0 ) + + if ( cff2 ) + { + if ( FT_READ_ULONG( count ) ) + goto Exit; + idx->hdr_size = 5; + } + else + { + if ( FT_READ_USHORT( count ) ) + goto Exit; + idx->hdr_size = 3; + } + + if ( count > 0 ) { FT_Byte offsize; FT_ULong size; @@ -258,7 +272,7 @@ idx->off_size = offsize; size = (FT_ULong)( count + 1 ) * offsize; - idx->data_offset = idx->start + 3 + size; + idx->data_offset = idx->start + idx->hdr_size + size; if ( FT_STREAM_SKIP( size - offsize ) ) goto Exit; @@ -335,7 +349,7 @@ data_size = (FT_ULong)( idx->count + 1 ) * offsize; if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) || - FT_STREAM_SEEK( idx->start + 3 ) || + FT_STREAM_SEEK( idx->start + idx->hdr_size ) || FT_FRAME_ENTER( data_size ) ) goto Exit; @@ -493,7 +507,7 @@ FT_ULong pos = element * idx->off_size; - if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) + if ( FT_STREAM_SEEK( idx->start + idx->hdr_size + pos ) ) goto Exit; off1 = cff_index_read_offset( idx, &error ); @@ -1478,6 +1492,7 @@ FT_ULong dict_len; CFF_FontRecDict top = &font->font_dict; CFF_Private priv = &font->private_dict; + FT_Bool cff2 = (code == CFF2_CODE_TOPDICT ); cff_parser_init( &parser, @@ -1582,7 +1597,7 @@ priv->local_subrs_offset ) ) goto Exit; - error = cff_index_init( &font->local_subrs_index, stream, 1 ); + error = cff_index_init( &font->local_subrs_index, stream, 1, cff2 ); if ( error ) goto Exit; @@ -1622,11 +1637,10 @@ #undef FT_STRUCTURE #define FT_STRUCTURE CFF_FontRec - FT_FRAME_START( 4 ), + FT_FRAME_START( 3 ), FT_FRAME_BYTE( version_major ), FT_FRAME_BYTE( version_minor ), FT_FRAME_BYTE( header_size ), - FT_FRAME_BYTE( absolute_offsize ), FT_FRAME_END }; @@ -1653,16 +1667,21 @@ /* check format */ if ( font->version_major != ( cff2 ? 2 : 1 ) || - font->header_size < 4 || - ( !cff2 && font->absolute_offsize > 4 ) ) + font->header_size < 4 ) { FT_TRACE2(( " not a CFF font header\n" )); error = FT_THROW( Unknown_File_Format ); goto Exit; } + if ( cff2 ) + { + if ( FT_READ_USHORT( font->top_dict_length ) ) + goto Exit; + } + /* skip the rest of the header */ - if ( FT_STREAM_SKIP( font->header_size - 4 ) ) + if ( FT_STREAM_SEEK( base_offset + font->header_size ) ) goto Exit; if ( cff2 ) @@ -1674,28 +1693,28 @@ /* length of data, but leave count at zero as an indicator */ FT_ZERO( &font->font_dict_index ); font->font_dict_index.data_offset = FT_STREAM_POS(); - font->font_dict_index.data_size = font->absolute_offsize; + font->font_dict_index.data_size = font->top_dict_length; /* skip the top dict data for now, we'll parse it later */ - if ( FT_STREAM_SKIP( font->absolute_offsize ) ) + if ( FT_STREAM_SKIP( font->top_dict_length ) ) goto Exit; /* next, read the global subrs index */ if ( FT_SET_ERROR( cff_index_init( &font->global_subrs_index, - stream, 1 ) ) ) + stream, 1, cff2 ) ) ) goto Exit; } else { /* for CFF, read the name, top dict, string and global subrs index */ if ( FT_SET_ERROR( cff_index_init( &font->name_index, - stream, 0 ) ) || + stream, 0, cff2 ) ) || FT_SET_ERROR( cff_index_init( &font->font_dict_index, - stream, 0 ) ) || + stream, 0, cff2 ) ) || FT_SET_ERROR( cff_index_init( &string_index, - stream, 1 ) ) || + stream, 1, cff2 ) ) || FT_SET_ERROR( cff_index_init( &font->global_subrs_index, - stream, 1 ) ) || + stream, 1, cff2 ) ) || FT_SET_ERROR( cff_index_get_pointers( &string_index, &font->strings, &font->string_pool, @@ -1755,7 +1774,7 @@ if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) goto Exit; - error = cff_index_init( &font->charstrings_index, stream, 0 ); + error = cff_index_init( &font->charstrings_index, stream, 0, cff2 ); if ( error ) goto Exit; @@ -1773,7 +1792,7 @@ if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) goto Exit; - error = cff_index_init( &fd_index, stream, 0 ); + error = cff_index_init( &fd_index, stream, 0, cff2 ); if ( error ) goto Exit; diff --git a/src/cff/cfftoken.h b/src/cff/cfftoken.h index c6712daf7..a1b8ae664 100644 --- a/src/cff/cfftoken.h +++ b/src/cff/cfftoken.h @@ -144,7 +144,7 @@ CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" ) CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" ) CFF_FIELD_NUM ( 22, vsindex, "vsindex" ) - CFF_FIELD_BLEND ( 31, "blend" ) + CFF_FIELD_BLEND ( 23, "blend" ) CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" ) diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h index 379c1d056..c6ed4df19 100644 --- a/src/cff/cfftypes.h +++ b/src/cff/cfftypes.h @@ -64,6 +64,7 @@ FT_BEGIN_HEADER { FT_Stream stream; FT_ULong start; + FT_UInt hdr_size; FT_UInt count; FT_Byte off_size; FT_ULong data_offset; @@ -272,7 +273,8 @@ FT_BEGIN_HEADER FT_Byte version_major; FT_Byte version_minor; FT_Byte header_size; - FT_Byte absolute_offsize; /* cff2_top_dict_length */ + + FT_UInt top_dict_length; /* cff2 only */ FT_Bool cff2;