summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/cff/cffload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/freetype/src/cff/cffload.c')
-rw-r--r--src/3rdparty/freetype/src/cff/cffload.c341
1 files changed, 203 insertions, 138 deletions
diff --git a/src/3rdparty/freetype/src/cff/cffload.c b/src/3rdparty/freetype/src/cff/cffload.c
index 64d1395723..d9bec5966b 100644
--- a/src/3rdparty/freetype/src/cff/cffload.c
+++ b/src/3rdparty/freetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType and CFF data/program tables loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2014 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,7 +20,6 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_STREAM_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_TRUETYPE_TAGS_H
#include FT_TYPE1_TABLES_H
@@ -251,7 +250,7 @@
if ( offsize < 1 || offsize > 4 )
{
- error = FT_Err_Invalid_Table;
+ error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -270,7 +269,7 @@
if ( size == 0 )
{
- error = CFF_Err_Invalid_Table;
+ error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -319,7 +318,7 @@
static FT_Error
cff_index_load_offsets( CFF_Index idx )
{
- FT_Error error = CFF_Err_Ok;
+ FT_Error error = FT_Err_Ok;
FT_Stream stream = idx->stream;
FT_Memory memory = stream->memory;
@@ -377,18 +376,22 @@
}
- /* allocate a table containing pointers to an index's elements */
+ /* Allocate a table containing pointers to an index's elements. */
+ /* The `pool' argument makes this function convert the index */
+ /* entries to C-style strings (this is, NULL-terminated). */
static FT_Error
cff_index_get_pointers( CFF_Index idx,
- FT_Byte*** table )
+ FT_Byte*** table,
+ FT_Byte** pool )
{
- FT_Error error = CFF_Err_Ok;
- FT_Memory memory = idx->stream->memory;
- FT_ULong n, offset, old_offset;
- FT_Byte** t;
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = idx->stream->memory;
+ FT_Byte** t = NULL;
+ FT_Byte* new_bytes = NULL;
- *table = 0;
+
+ *table = NULL;
if ( idx->offsets == NULL )
{
@@ -397,28 +400,65 @@
goto Exit;
}
- if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
+ if ( idx->count > 0 &&
+ !FT_NEW_ARRAY( t, idx->count + 1 ) &&
+ ( !pool || !FT_ALLOC( new_bytes,
+ idx->data_size + idx->count ) ) )
{
- old_offset = 1;
- for ( n = 0; n <= idx->count; n++ )
+ FT_ULong n, cur_offset;
+ FT_ULong extra = 0;
+ FT_Byte* org_bytes = idx->bytes;
+
+
+ /* at this point, `idx->offsets' can't be NULL */
+ cur_offset = idx->offsets[0] - 1;
+
+ /* sanity check */
+ if ( cur_offset != 0 )
+ {
+ FT_TRACE0(( "cff_index_get_pointers:"
+ " invalid first offset value %d set to zero\n",
+ cur_offset ));
+ cur_offset = 0;
+ }
+
+ if ( !pool )
+ t[0] = org_bytes + cur_offset;
+ else
+ t[0] = new_bytes + cur_offset;
+
+ for ( n = 1; n <= idx->count; n++ )
{
- /* at this point, `idx->offsets' can't be NULL */
- offset = idx->offsets[n];
- if ( !offset )
- offset = old_offset;
+ FT_ULong next_offset = idx->offsets[n] - 1;
+
/* two sanity checks for invalid offset tables */
- else if ( offset < old_offset )
- offset = old_offset;
+ if ( next_offset < cur_offset )
+ next_offset = cur_offset;
+ else if ( next_offset > idx->data_size )
+ next_offset = idx->data_size;
- else if ( offset - 1 >= idx->data_size && n < idx->count )
- offset = old_offset;
+ if ( !pool )
+ t[n] = org_bytes + next_offset;
+ else
+ {
+ t[n] = new_bytes + next_offset + extra;
- t[n] = idx->bytes + offset - 1;
+ if ( next_offset != cur_offset )
+ {
+ FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
+ t[n][0] = '\0';
+ t[n] += 1;
+ extra++;
+ }
+ }
- old_offset = offset;
+ cur_offset = next_offset;
}
*table = t;
+
+ if ( pool )
+ *pool = new_bytes;
}
Exit:
@@ -432,7 +472,7 @@
FT_Byte** pbytes,
FT_ULong* pbyte_len )
{
- FT_Error error = CFF_Err_Ok;
+ FT_Error error = FT_Err_Ok;
if ( idx && idx->count > element )
@@ -479,6 +519,18 @@
}
}
+ /* XXX: should check off2 does not exceed the end of this entry; */
+ /* at present, only truncate off2 at the end of this stream */
+ if ( off2 > stream->size + 1 ||
+ idx->data_offset > stream->size - off2 + 1 )
+ {
+ FT_ERROR(( "cff_index_access_element:"
+ " offset to next entry (%d)"
+ " exceeds the end of stream (%d)\n",
+ off2, stream->size - idx->data_offset + 1 ));
+ off2 = stream->size - idx->data_offset + 1;
+ }
+
/* access element */
if ( off1 && off2 > off1 )
{
@@ -505,7 +557,7 @@
}
}
else
- error = CFF_Err_Invalid_Argument;
+ error = FT_THROW( Invalid_Argument );
Exit:
return error;
@@ -526,10 +578,12 @@
}
+ /* get an entry from Name INDEX */
FT_LOCAL_DEF( FT_String* )
- cff_index_get_name( CFF_Index idx,
- FT_UInt element )
+ cff_index_get_name( CFF_Font font,
+ FT_UInt element )
{
+ CFF_Index idx = &font->name_index;
FT_Memory memory = idx->stream->memory;
FT_Byte* bytes;
FT_ULong byte_len;
@@ -553,42 +607,35 @@
}
+ /* get an entry from String INDEX */
FT_LOCAL_DEF( FT_String* )
- cff_index_get_sid_string( CFF_Index idx,
- FT_UInt sid,
- FT_Service_PsCMaps psnames )
+ cff_index_get_string( CFF_Font font,
+ FT_UInt element )
+ {
+ return ( element < font->num_strings )
+ ? (FT_String*)font->strings[element]
+ : NULL;
+ }
+
+
+ FT_LOCAL_DEF( FT_String* )
+ cff_index_get_sid_string( CFF_Font font,
+ FT_UInt sid )
{
/* value 0xFFFFU indicates a missing dictionary entry */
if ( sid == 0xFFFFU )
- return 0;
+ return NULL;
/* if it is not a standard string, return it */
if ( sid > 390 )
- return cff_index_get_name( idx, sid - 391 );
+ return cff_index_get_string( font, sid - 391 );
/* CID-keyed CFF fonts don't have glyph names */
- if ( !psnames )
- return 0;
-
- /* that's a standard string, fetch a copy from the PSName module */
- {
- FT_String* name = 0;
- const char* adobe_name = psnames->adobe_std_strings( sid );
-
-
- if ( adobe_name )
- {
- FT_Memory memory = idx->stream->memory;
- FT_Error error;
+ if ( !font->psnames )
+ return NULL;
-
- (void)FT_STRDUP( name, adobe_name );
-
- FT_UNUSED( error );
- }
-
- return name;
- }
+ /* this is a standard string */
+ return (FT_String *)font->psnames->adobe_std_strings( sid );
}
@@ -642,6 +689,13 @@
if ( FT_READ_USHORT( num_ranges ) )
goto Exit;
+ if ( !num_ranges )
+ {
+ FT_TRACE0(( "CFF_Load_FD_Select: empty FDSelect array\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
fdselect->data_size = num_ranges * 3 + 2;
Load_Data:
@@ -650,7 +704,7 @@
break;
default: /* hmm... that's wrong */
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
}
Exit:
@@ -672,7 +726,7 @@
break;
case 3:
- /* first, compare to cache */
+ /* first, compare to the cache */
if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
fdselect->cache_count )
{
@@ -680,7 +734,7 @@
break;
}
- /* then, lookup the ranges array */
+ /* then, look up the ranges array */
{
FT_Byte* p = fdselect->data;
FT_Byte* p_limit = p + fdselect->data_size;
@@ -703,7 +757,7 @@
/* update cache */
fdselect->cache_first = first;
- fdselect->cache_count = limit-first;
+ fdselect->cache_count = limit - first;
fdselect->cache_fd = fd2;
break;
}
@@ -744,11 +798,12 @@
goto Exit;
for ( i = 0; i < num_glyphs; i++ )
+ {
if ( charset->sids[i] > max_cid )
max_cid = charset->sids[i];
- max_cid++;
+ }
- if ( FT_NEW_ARRAY( charset->cids, max_cid ) )
+ if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
goto Exit;
/* When multiple GIDs map to the same CID, we choose the lowest */
@@ -772,7 +827,7 @@
FT_UInt result = 0;
- if ( cid < charset->max_cid )
+ if ( cid <= charset->max_cid )
result = charset->cids[cid];
return result;
@@ -812,7 +867,7 @@
FT_Bool invert )
{
FT_Memory memory = stream->memory;
- FT_Error error = CFF_Err_Ok;
+ FT_Error error = FT_Err_Ok;
FT_UShort glyph_sid;
@@ -846,20 +901,7 @@
goto Exit;
for ( j = 1; j < num_glyphs; j++ )
- {
- FT_UShort sid = FT_GET_USHORT();
-
-
- /* this constant is given in the CFF specification */
- if ( sid < 65000L )
- charset->sids[j] = sid;
- else
- {
- FT_TRACE0(( "cff_charset_load:"
- " invalid SID value %d set to zero\n", sid ));
- charset->sids[j] = 0;
- }
- }
+ charset->sids[j] = FT_GET_USHORT();
FT_FRAME_EXIT();
}
@@ -892,18 +934,12 @@
goto Exit;
}
- /* check whether the range contains at least one valid glyph; */
- /* the constant is given in the CFF specification */
- if ( glyph_sid >= 65000L ) {
- FT_ERROR(( "cff_charset_load: invalid SID range\n" ));
- error = CFF_Err_Invalid_File_Format;
- goto Exit;
- }
-
/* try to rescue some of the SIDs if `nleft' is too large */
- if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft ) {
- FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" ));
- nleft = ( FT_UInt )( 65000L - 1L - glyph_sid );
+ if ( glyph_sid > 0xFFFFL - nleft )
+ {
+ FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
+ " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
+ nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
}
/* Fill in the range of sids -- `nleft + 1' glyphs. */
@@ -915,7 +951,7 @@
default:
FT_ERROR(( "cff_charset_load: invalid table format\n" ));
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
@@ -938,7 +974,7 @@
{
FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
"predefined charset (Adobe ISO-Latin)\n" ));
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -956,7 +992,7 @@
{
FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
"predefined charset (Adobe Expert)\n" ));
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -974,7 +1010,7 @@
{
FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
"predefined charset (Adobe Expert Subset)\n" ));
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -988,7 +1024,7 @@
break;
default:
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
@@ -1029,7 +1065,7 @@
FT_ULong base_offset,
FT_ULong offset )
{
- FT_Error error = CFF_Err_Ok;
+ FT_Error error = FT_Err_Ok;
FT_UInt count;
FT_UInt j;
FT_UShort glyph_sid;
@@ -1039,7 +1075,7 @@
/* Check for charset->sids. If we do not have this, we fail. */
if ( !charset->sids )
{
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -1159,7 +1195,7 @@
default:
FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -1240,9 +1276,7 @@
if ( gid != 0 )
{
encoding->codes[j] = (FT_UShort)gid;
-
- if ( encoding->count < j + 1 )
- encoding->count = j + 1;
+ encoding->count = j + 1;
}
else
{
@@ -1254,7 +1288,7 @@
default:
FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
- error = CFF_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
@@ -1287,7 +1321,7 @@
/* set defaults */
FT_MEM_ZERO( top, sizeof ( *top ) );
- top->underline_position = -100L << 16;
+ top->underline_position = -( 100L << 16 );
top->underline_thickness = 50L << 16;
top->charstring_type = 2;
top->font_matrix.xx = 0x10000L;
@@ -1310,7 +1344,10 @@
error = cff_index_access_element( idx, font_index, &dict, &dict_len );
if ( !error )
+ {
+ FT_TRACE4(( " top dictionary:\n" ));
error = cff_parser_run( &parser, dict, dict + dict_len );
+ }
cff_index_forget_element( idx, &dict );
@@ -1339,6 +1376,7 @@
FT_FRAME_ENTER( font->font_dict.private_size ) )
goto Exit;
+ FT_TRACE4(( " private dictionary:\n" ));
error = cff_parser_run( &parser,
(FT_Byte*)stream->cursor,
(FT_Byte*)stream->limit );
@@ -1361,9 +1399,8 @@
if ( error )
goto Exit;
- font->num_local_subrs = font->local_subrs_index.count;
error = cff_index_get_pointers( &font->local_subrs_index,
- &font->local_subrs );
+ &font->local_subrs, NULL );
if ( error )
goto Exit;
}
@@ -1409,9 +1446,12 @@
FT_Memory memory = stream->memory;
FT_ULong base_offset;
CFF_FontRecDict dict;
+ CFF_IndexRec string_index;
+ FT_Int subfont_index;
FT_ZERO( font );
+ FT_ZERO( &string_index );
font->stream = stream;
font->memory = memory;
@@ -1427,8 +1467,8 @@
font->header_size < 4 ||
font->absolute_offsize > 4 )
{
- FT_TRACE2(( "[not a CFF font header]\n" ));
- error = CFF_Err_Unknown_File_Format;
+ FT_TRACE2(( " not a CFF font header\n" ));
+ error = FT_THROW( Unknown_File_Format );
goto Exit;
}
@@ -1438,22 +1478,49 @@
/* read the name, top dict, string and global subrs index */
if ( FT_SET_ERROR( cff_index_init( &font->name_index,
- stream, 0 ) ) ||
+ stream, 0 ) ) ||
FT_SET_ERROR( cff_index_init( &font->font_dict_index,
- stream, 0 ) ) ||
- FT_SET_ERROR( cff_index_init( &font->string_index,
- stream, 0 ) ) ||
+ stream, 0 ) ) ||
+ FT_SET_ERROR( cff_index_init( &string_index,
+ stream, 1 ) ) ||
FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
- stream, 1 ) ) )
+ stream, 1 ) ) ||
+ FT_SET_ERROR( cff_index_get_pointers( &string_index,
+ &font->strings,
+ &font->string_pool ) ) )
goto Exit;
- /* well, we don't really forget the `disabled' fonts... */
- font->num_faces = font->name_index.count;
- if ( face_index >= (FT_Int)font->num_faces )
+ font->num_strings = string_index.count;
+
+ if ( pure_cff )
+ {
+ /* well, we don't really forget the `disabled' fonts... */
+ subfont_index = face_index;
+
+ if ( subfont_index >= (FT_Int)font->name_index.count )
+ {
+ FT_ERROR(( "cff_font_load:"
+ " invalid subfont index for pure CFF font (%d)\n",
+ subfont_index ));
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ font->num_faces = font->name_index.count;
+ }
+ else
{
- FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
- face_index ));
- error = CFF_Err_Invalid_Argument;
+ subfont_index = 0;
+
+ if ( font->name_index.count > 1 )
+ {
+ FT_ERROR(( "cff_font_load:"
+ " invalid CFF font with multiple subfonts\n"
+ " "
+ " in SFNT wrapper\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
}
/* in case of a font format check, simply exit now */
@@ -1461,9 +1528,10 @@
goto Exit;
/* now, parse the top-level font dictionary */
+ FT_TRACE4(( "parsing top-level\n" ));
error = cff_subfont_load( &font->top_font,
&font->font_dict_index,
- face_index,
+ subfont_index,
stream,
base_offset,
library );
@@ -1481,7 +1549,7 @@
if ( dict->cid_registry != 0xFFFFU )
{
CFF_IndexRec fd_index;
- CFF_SubFont sub;
+ CFF_SubFont sub = NULL;
FT_UInt idx;
@@ -1513,6 +1581,7 @@
for ( idx = 0; idx < fd_index.count; idx++ )
{
sub = font->subfonts[idx];
+ FT_TRACE4(( "parsing subfont %u\n", idx ));
error = cff_subfont_load( sub, &fd_index, idx,
stream, base_offset, library );
if ( error )
@@ -1538,16 +1607,14 @@
if ( dict->charstrings_offset == 0 )
{
FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
- error = CFF_Err_Unknown_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Exit;
}
- /* explicit the global subrs */
- font->num_global_subrs = font->global_subrs_index.count;
- font->num_glyphs = font->charstrings_index.count;
+ font->num_glyphs = font->charstrings_index.count;
error = cff_index_get_pointers( &font->global_subrs_index,
- &font->global_subrs ) ;
+ &font->global_subrs, NULL );
if ( error )
goto Exit;
@@ -1579,9 +1646,11 @@
/* get the font name (/CIDFontName for CID-keyed fonts, */
/* /FontName otherwise) */
- font->font_name = cff_index_get_name( &font->name_index, face_index );
+ font->font_name = cff_index_get_name( font, subfont_index );
Exit:
+ cff_index_done( &string_index );
+
return error;
}
@@ -1594,7 +1663,6 @@
cff_index_done( &font->global_subrs_index );
- cff_index_done( &font->string_index );
cff_index_done( &font->font_dict_index );
cff_index_done( &font->name_index );
cff_index_done( &font->charstrings_index );
@@ -1617,21 +1685,18 @@
CFF_Done_FD_Select( &font->fd_select, font->stream );
- if (font->font_info != NULL)
- {
- FT_FREE( font->font_info->version );
- FT_FREE( font->font_info->notice );
- FT_FREE( font->font_info->full_name );
- FT_FREE( font->font_info->family_name );
- FT_FREE( font->font_info->weight );
- FT_FREE( font->font_info );
- }
+ FT_FREE( font->font_info );
- FT_FREE( font->registry );
- FT_FREE( font->ordering );
-
- FT_FREE( font->global_subrs );
FT_FREE( font->font_name );
+ FT_FREE( font->global_subrs );
+ FT_FREE( font->strings );
+ FT_FREE( font->string_pool );
+
+ if ( font->cf2_instance.finalizer )
+ {
+ font->cf2_instance.finalizer( font->cf2_instance.data );
+ FT_FREE( font->cf2_instance.data );
+ }
}