From dccfebc0f58370f74a6eae875914a97dfee021d9 Mon Sep 17 00:00:00 2001 From: Dave Arnold Date: Wed, 28 Sep 2016 15:14:28 -0700 Subject: Support v10 CFF2 fonts remove string index, font index top dict follows header, but has no index font dict in FDArray, but skip FDSelect when there's only one font dict --- src/cff/cffload.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--------- src/cff/cfftypes.h | 3 ++- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/cff/cffload.c b/src/cff/cffload.c index c357a1acb..f792261c5 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -726,6 +726,10 @@ { FT_Byte fd = 0; + /* if there is no FDSelect, return zero */ + /* Note: CFF2 with just one Font Dict has no FDSelect */ + if ( fdselect->data == NULL ) + goto Exit; switch ( fdselect->format ) { @@ -779,6 +783,7 @@ ; } + Exit: return fd; } @@ -1505,14 +1510,27 @@ top->cid_ordering = 0xFFFFU; top->cid_font_name = 0xFFFFU; - error = cff_index_access_element( idx, font_index, &dict, &dict_len ); + if ( idx->count ) /* count is nonzero for a real index */ + error = cff_index_access_element( idx, font_index, &dict, &dict_len ); + else + { + /* cff2 has a fake top dict index. simulate cff_index_access_element */ + /* Note: macros implicitly use "stream" and set "error" */ + if ( !FT_STREAM_SEEK( idx->data_offset ) ) + FT_FRAME_EXTRACT( idx->data_size, dict ); + dict_len = idx->data_size; + } if ( !error ) { FT_TRACE4(( " top dictionary:\n" )); error = cff_parser_run( &parser, dict, dict + dict_len ); } - cff_index_forget_element( idx, &dict ); + /* clean up regardless of error */ + if ( idx->count ) + cff_index_forget_element( idx, &dict ); + else + FT_FRAME_RELEASE( dict ); if ( error ) goto Exit; @@ -1624,6 +1642,7 @@ font->stream = stream; font->memory = memory; + font->cff2 = cff2; dict = &font->top_font.font_dict; base_offset = FT_STREAM_POS(); @@ -1634,7 +1653,7 @@ /* check format */ if ( font->version_major != ( cff2 ? 2 : 1 ) || font->header_size < 4 || - font->absolute_offsize > 4 ) + ( !cff2 && font->absolute_offsize > 4 ) ) { FT_TRACE2(( " not a CFF font header\n" )); error = FT_THROW( Unknown_File_Format ); @@ -1645,10 +1664,31 @@ if ( FT_STREAM_SKIP( font->header_size - 4 ) ) goto Exit; - /* read the name, top dict, string and global subrs index */ - /* CFF2 does not contain a name index */ - if ( ( !cff2 && FT_SET_ERROR( cff_index_init( &font->name_index, - stream, 0 ) ) ) || + if ( cff2 ) + { + /* For CFF2, the top dict data immediately follow the header */ + /* and the length is stored in the header offSize field */ + /* there is no index for it. */ + /* use the font_dict_index to save the current position and */ + /* 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; + + /* skip the top dict data for now, we'll parse it later */ + if ( FT_STREAM_SKIP( font->absolute_offsize ) ) + goto Exit; + + /* next, read the global subrs index */ + if ( FT_SET_ERROR( cff_index_init( &font->global_subrs_index, + stream, 1 ) ) ) + 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 ) ) || FT_SET_ERROR( cff_index_init( &font->font_dict_index, stream, 0 ) ) || FT_SET_ERROR( cff_index_init( &string_index, @@ -1659,7 +1699,8 @@ &font->strings, &font->string_pool, &font->string_pool_size ) ) ) - goto Exit; + goto Exit; + } font->num_strings = string_index.count; @@ -1716,8 +1757,9 @@ if ( error ) goto Exit; - /* now, check for a CID font */ - if ( dict->cid_registry != 0xFFFFU ) + /* now, check for a CID or CFF2 font */ + if ( dict->cid_registry != 0xFFFFU || + cff2 ) { CFF_IndexRec fd_index; CFF_SubFont sub = NULL; @@ -1760,6 +1802,8 @@ } /* now load the FD Select array */ + /* CFF2 omits FDSelect if there's only one FD */ + if ( !cff2 || fd_index.count > 1 ) error = CFF_Load_FD_Select( &font->fd_select, font->charstrings_index.count, stream, @@ -1847,7 +1891,7 @@ cff_index_done( &font->charstrings_index ); /* release font dictionaries, but only if working with */ - /* a CID keyed CFF font */ + /* a CID keyed CFF font or a CFF2 font */ if ( font->num_subfonts > 0 ) { for ( idx = 0; idx < font->num_subfonts; idx++ ) diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h index d8fc1e9ab..ee0308681 100644 --- a/src/cff/cfftypes.h +++ b/src/cff/cfftypes.h @@ -269,8 +269,9 @@ FT_BEGIN_HEADER FT_Byte version_major; FT_Byte version_minor; FT_Byte header_size; - FT_Byte absolute_offsize; + FT_Byte absolute_offsize; /* cff2_top_dict_length */ + FT_Bool cff2; CFF_IndexRec name_index; CFF_IndexRec top_dict_index; -- cgit v1.2.1