diff options
Diffstat (limited to 'src/3rdparty/freetype/src/cff/cffparse.c')
-rw-r--r-- | src/3rdparty/freetype/src/cff/cffparse.c | 471 |
1 files changed, 145 insertions, 326 deletions
diff --git a/src/3rdparty/freetype/src/cff/cffparse.c b/src/3rdparty/freetype/src/cff/cffparse.c index b9611cf548..3b076704cf 100644 --- a/src/3rdparty/freetype/src/cff/cffparse.c +++ b/src/3rdparty/freetype/src/cff/cffparse.c @@ -1,41 +1,40 @@ -/***************************************************************************/ -/* */ -/* cffparse.c */ -/* */ -/* CFF token stream parser (body) */ -/* */ -/* Copyright 1996-2018 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> +/**************************************************************************** + * + * cffparse.c + * + * CFF token stream parser (body) + * + * Copyright (C) 1996-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + #include "cffparse.h" -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include <freetype/internal/ftstream.h> +#include <freetype/internal/ftdebug.h> +#include <freetype/internal/ftcalc.h> +#include <freetype/internal/psaux.h> +#include <freetype/ftlist.h> #include "cfferrs.h" -#include "cffpic.h" #include "cffload.h" - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ #undef FT_COMPONENT -#define FT_COMPONENT trace_cffparse +#define FT_COMPONENT cffparse FT_LOCAL_DEF( FT_Error ) @@ -63,11 +62,8 @@ parser->num_axes = num_axes; /* allocate the stack buffer */ - if ( FT_NEW_ARRAY( parser->stack, stackSize ) ) - { - FT_FREE( parser->stack ); + if ( FT_QNEW_ARRAY( parser->stack, stackSize ) ) goto Exit; - } parser->stackSize = stackSize; parser->top = parser->stack; /* empty stack */ @@ -84,9 +80,17 @@ FT_FREE( parser->stack ); + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + FT_List_Finalize( &parser->t2_strings, NULL, memory, NULL ); +#endif } + /* The parser limit checks in the next two functions are supposed */ + /* to detect the immediate crossing of the stream boundary. They */ + /* shall not be triggered from the distant t2_strings buffers. */ + /* read an integer */ static FT_Long cff_parse_integer( FT_Byte* start, @@ -99,14 +103,14 @@ if ( v == 28 ) { - if ( p + 2 > limit ) + if ( p + 2 > limit && limit >= p ) goto Bad; val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] ); } else if ( v == 29 ) { - if ( p + 4 > limit ) + if ( p + 4 > limit && limit >= p ) goto Bad; val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) | @@ -120,14 +124,14 @@ } else if ( v < 251 ) { - if ( p + 1 > limit ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = ( v - 247 ) * 256 + p[0] + 108; } else { - if ( p + 1 > limit ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = -( v - 251 ) * 256 - p[0] - 108; @@ -214,7 +218,7 @@ p++; /* Make sure we don't read past the end. */ - if ( p >= limit ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -251,7 +255,7 @@ p++; /* Make sure we don't read past the end. */ - if ( p >= limit ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -290,7 +294,7 @@ p++; /* Make sure we don't read past the end. */ - if ( p >= limit ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -462,7 +466,7 @@ else if ( **d == 255 ) { - /* 16.16 fixed point is used internally for CFF2 blend results. */ + /* 16.16 fixed-point is used internally for CFF2 blend results. */ /* Since these are trusted values, a limit check is not needed. */ /* After the 255, 4 bytes give the number. */ @@ -495,6 +499,24 @@ { if ( **d == 30 ) return cff_parse_real( *d, parser->limit, scaling, NULL ); + else if ( **d == 255 ) + { + FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | + (FT_UInt32)*( d[0] + 4 ) ) ); + + if ( scaling ) + { + if ( FT_ABS( val ) > power_ten_limits[scaling] ) + { + FT_TRACE4(( "!!!OVERFLOW:!!!" )); + return val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; + } + val *= power_tens[scaling]; + } + return val; + } else { FT_Long val = cff_parse_integer( *d, parser->limit ); @@ -502,7 +524,7 @@ if ( scaling ) { - if ( FT_ABS( val ) > power_ten_limits[scaling] ) + if ( ( FT_ABS( val ) << 16 ) > power_ten_limits[scaling] ) { val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; goto Overflow; @@ -532,7 +554,7 @@ /* read a floating point number, either integer or real */ - static FT_Fixed + FT_LOCAL_DEF( FT_Fixed ) cff_parse_fixed( CFF_Parser parser, FT_Byte** d ) { @@ -569,7 +591,7 @@ FT_Int integer_length; - number = cff_parse_integer( d[0], d[1] ); + number = cff_parse_integer( *d, parser->limit ); if ( number > 0x7FFFL ) { @@ -605,7 +627,6 @@ FT_Vector* offset = &dict->font_offset; FT_ULong* upm = &dict->units_per_em; FT_Byte** data = parser->stack; - FT_Error error = FT_ERR( Stack_Underflow ); if ( parser->top >= parser->stack + 6 ) @@ -617,11 +638,9 @@ int i; - error = FT_Err_Ok; - dict->has_font_matrix = TRUE; - /* We expect a well-formed font matrix, this is, the matrix elements */ + /* We expect a well-formed font matrix, that is, the matrix elements */ /* `xx' and `yy' are of approximately the same magnitude. To avoid */ /* loss of precision, we use the magnitude of the largest matrix */ /* element to scale all other elements. The scaling factor is then */ @@ -647,22 +666,12 @@ ( max_scaling - min_scaling ) < 0 || ( max_scaling - min_scaling ) > 9 ) { - /* Return default matrix in case of unlikely values. */ - FT_TRACE1(( "cff_parse_font_matrix:" - " strange scaling values (minimum %d, maximum %d),\n" - " " - " using default matrix\n", min_scaling, max_scaling )); - - matrix->xx = 0x10000L; - matrix->yx = 0; - matrix->xy = 0; - matrix->yy = 0x10000L; - offset->x = 0; - offset->y = 0; - *upm = 1; - - goto Exit; + " strange scaling values (minimum %ld, maximum %ld),\n", + min_scaling, max_scaling )); + FT_TRACE1(( " " + " using default matrix\n" )); + goto Unlikely; } for ( i = 0; i < 6; i++ ) @@ -703,16 +712,37 @@ *upm = (FT_ULong)power_tens[-max_scaling]; FT_TRACE4(( " [%f %f %f %f %f %f]\n", - (double)matrix->xx / *upm / 65536, - (double)matrix->xy / *upm / 65536, - (double)matrix->yx / *upm / 65536, - (double)matrix->yy / *upm / 65536, - (double)offset->x / *upm / 65536, - (double)offset->y / *upm / 65536 )); + (double)matrix->xx / (double)*upm / 65536, + (double)matrix->xy / (double)*upm / 65536, + (double)matrix->yx / (double)*upm / 65536, + (double)matrix->yy / (double)*upm / 65536, + (double)offset->x / (double)*upm / 65536, + (double)offset->y / (double)*upm / 65536 )); + + if ( !FT_Matrix_Check( matrix ) ) + { + FT_TRACE1(( "cff_parse_font_matrix:" + " degenerate values, using default matrix\n" )); + goto Unlikely; + } + + return FT_Err_Ok; } + else + return FT_THROW( Stack_Underflow ); - Exit: - return error; + Unlikely: + /* Return default matrix in case of unlikely values. */ + + matrix->xx = 0x10000L; + matrix->yx = 0; + matrix->xy = 0; + matrix->yy = 0x10000L; + offset->x = 0; + offset->y = 0; + *upm = 1; + + return FT_Err_Ok; } @@ -735,7 +765,7 @@ bbox->yMax = FT_RoundFix( cff_parse_fixed( parser, data ) ); error = FT_Err_Ok; - FT_TRACE4(( " [%d %d %d %d]\n", + FT_TRACE4(( " [%ld %ld %ld %ld]\n", bbox->xMin / 65536, bbox->yMin / 65536, bbox->xMax / 65536, @@ -802,7 +832,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE /* beautify tracing message */ - if ( ft_trace_levels[FT_COMPONENT] < 4 ) + if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] < 4 ) FT_TRACE1(( "Multiple Master CFFs not supported yet," " handling first master design only\n" )); else @@ -858,11 +888,11 @@ FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" )); dict->cid_supplement = cff_parse_num( parser, data ); if ( dict->cid_supplement < 0 ) - FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n", + FT_TRACE1(( "cff_parse_cid_ros: negative supplement %ld is found\n", dict->cid_supplement )); error = FT_Err_Ok; - FT_TRACE4(( " %d %d %d\n", + FT_TRACE4(( " %d %d %ld\n", dict->cid_registry, dict->cid_ordering, dict->cid_supplement )); @@ -1003,9 +1033,6 @@ CFF_FIELD( code, name, id, cff_kind_bool ) -#ifndef FT_CONFIG_OPTION_PIC - - #undef CFF_FIELD #undef CFF_FIELD_DELTA @@ -1118,199 +1145,20 @@ #endif /* FT_DEBUG_LEVEL_TRACE */ -#else /* FT_CONFIG_OPTION_PIC */ - - - void - FT_Destroy_Class_cff_field_handlers( FT_Library library, - CFF_Field_Handler* clazz ) - { - FT_Memory memory = library->memory; - - - if ( clazz ) - FT_FREE( clazz ); - } - - - FT_Error - FT_Create_Class_cff_field_handlers( FT_Library library, - CFF_Field_Handler** output_class ) - { - CFF_Field_Handler* clazz = NULL; - FT_Error error; - FT_Memory memory = library->memory; - - int i = 0; - - -#undef CFF_FIELD -#define CFF_FIELD( code, name, id, kind ) i++; -#undef CFF_FIELD_DELTA -#define CFF_FIELD_DELTA( code, name, max, id ) i++; -#undef CFF_FIELD_CALLBACK -#define CFF_FIELD_CALLBACK( code, name, id ) i++; -#undef CFF_FIELD_BLEND -#define CFF_FIELD_BLEND( code, id ) i++; - -#include "cfftoken.h" - - i++; /* { 0, 0, 0, 0, 0, 0, 0 } */ - - if ( FT_ALLOC( clazz, sizeof ( CFF_Field_Handler ) * i ) ) - return error; - - i = 0; - - -#ifndef FT_DEBUG_LEVEL_TRACE - - -#undef CFF_FIELD_CALLBACK -#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \ - clazz[i].kind = cff_kind_callback; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = 0; \ - clazz[i].size = 0; \ - clazz[i].reader = cff_parse_ ## name_; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - i++; - -#undef CFF_FIELD -#define CFF_FIELD( code_, name_, id_, kind_ ) \ - clazz[i].kind = kind_; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - i++; \ - -#undef CFF_FIELD_DELTA -#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \ - clazz[i].kind = cff_kind_delta; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = max_; \ - clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ - i++; - -#undef CFF_FIELD_BLEND -#define CFF_FIELD_BLEND( code_, id_ ) \ - clazz[i].kind = cff_kind_blend; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = 0; \ - clazz[i].size = 0; \ - clazz[i].reader = cff_parse_blend; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - i++; - -#include "cfftoken.h" - - clazz[i].kind = 0; - clazz[i].code = 0; - clazz[i].offset = 0; - clazz[i].size = 0; - clazz[i].reader = 0; - clazz[i].array_max = 0; - clazz[i].count_offset = 0; - - -#else /* FT_DEBUG_LEVEL_TRACE */ - - -#undef CFF_FIELD_CALLBACK -#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \ - clazz[i].kind = cff_kind_callback; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = 0; \ - clazz[i].size = 0; \ - clazz[i].reader = cff_parse_ ## name_; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - clazz[i].id = id_; \ - i++; - -#undef CFF_FIELD -#define CFF_FIELD( code_, name_, id_, kind_ ) \ - clazz[i].kind = kind_; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - clazz[i].id = id_; \ - i++; \ - -#undef CFF_FIELD_DELTA -#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \ - clazz[i].kind = cff_kind_delta; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = max_; \ - clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ - clazz[i].id = id_; \ - i++; - -#undef CFF_FIELD_BLEND -#define CFF_FIELD_BLEND( code_, id_ ) \ - clazz[i].kind = cff_kind_blend; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = 0; \ - clazz[i].size = 0; \ - clazz[i].reader = cff_parse_blend; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - clazz[i].id = id_; \ - i++; - -#include "cfftoken.h" - - clazz[i].kind = 0; - clazz[i].code = 0; - clazz[i].offset = 0; - clazz[i].size = 0; - clazz[i].reader = 0; - clazz[i].array_max = 0; - clazz[i].count_offset = 0; - clazz[i].id = 0; - - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - - *output_class = clazz; - - return FT_Err_Ok; - } - - -#endif /* FT_CONFIG_OPTION_PIC */ - - FT_LOCAL_DEF( FT_Error ) cff_parser_run( CFF_Parser parser, FT_Byte* start, FT_Byte* limit ) { + FT_Byte* p = start; + FT_Error error = FT_Err_Ok; + #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PSAux_Service psaux; -#endif - FT_Byte* p = start; - FT_Error error = FT_Err_Ok; FT_Library library = parser->library; - - FT_UNUSED( library ); - + FT_Memory memory = library->memory; +#endif parser->top = parser->stack; parser->start = start; @@ -1321,6 +1169,7 @@ { FT_UInt v = *p; + /* Opcode 31 is legacy MM T2 operator, not a number. */ /* Opcode 255 is reserved and should not appear in fonts; */ /* it is used internally for CFF2 blends. */ @@ -1370,7 +1219,7 @@ FT_ULong charstring_len; FT_Fixed* stack; - FT_Byte* q; + FT_Byte* q = NULL; charstring_base = ++p; @@ -1405,23 +1254,24 @@ error = psaux->cff_decoder_funcs->parse_charstrings_old( &decoder, charstring_base, charstring_len, 1 ); + if ( error ) + goto Exit; /* Now copy the stack data in the temporary decoder object, */ /* converting it back to charstring number representations */ /* (this is ugly, I know). */ - /* */ - /* We overwrite the original top DICT charstring under the */ - /* assumption that the charstring representation of the result */ - /* of `cff_decoder_parse_charstrings' is shorter, which should */ - /* be always true. */ + /* The maximum required size is 5 bytes per stack element. */ + if ( FT_QALLOC( q, (FT_Long)( 2 * sizeof ( FT_ListNode ) ) + + 5 * ( decoder.top - decoder.stack ) ) ) + goto Exit; + + FT_List_Add( &parser->t2_strings, (FT_ListNode)q ); - q = charstring_base - 1; - stack = decoder.stack; + q += 2 * sizeof ( FT_ListNode ); - while ( stack < decoder.top ) + for ( stack = decoder.stack; stack < decoder.top; stack++ ) { - FT_ULong num; - FT_Bool neg; + FT_Long num = *stack; if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize ) @@ -1429,69 +1279,37 @@ *parser->top++ = q; - if ( *stack < 0 ) - { - num = (FT_ULong)-*stack; - neg = 1; - } - else - { - num = (FT_ULong)*stack; - neg = 0; - } - if ( num & 0xFFFFU ) { - if ( neg ) - num = (FT_ULong)-num; - *q++ = 255; - *q++ = ( num & 0xFF000000U ) >> 24; - *q++ = ( num & 0x00FF0000U ) >> 16; - *q++ = ( num & 0x0000FF00U ) >> 8; - *q++ = num & 0x000000FFU; + *q++ = (FT_Byte)( ( num >> 24 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 16 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 8 ) & 0xFF ); + *q++ = (FT_Byte)( ( num ) & 0xFF ); } else { num >>= 16; - if ( neg ) + if ( -107 <= num && num <= 107 ) + *q++ = (FT_Byte)( num + 139 ); + else if ( 108 <= num && num <= 1131 ) { - if ( num <= 107 ) - *q++ = (FT_Byte)( 139 - num ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - num = (FT_ULong)-num; - - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); + *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); + } + else if ( -1131 <= num && num <= -108 ) + { + *q++ = (FT_Byte)( ( ( -num - 108 ) >> 8 ) + 251 ); + *q++ = (FT_Byte)( ( -num - 108) & 0xFF ); } else { - if ( num <= 107 ) - *q++ = (FT_Byte)( num + 139 ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = 28; + *q++ = (FT_Byte)( num >> 8 ); + *q++ = (FT_Byte)( num & 0xFF ); } } - - stack++; } } #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ @@ -1523,7 +1341,7 @@ } code = code | parser->object_code; - for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ ) + for ( field = cff_field_handlers; field->kind; field++ ) { if ( field->code == (FT_Int)code ) { @@ -1596,6 +1414,7 @@ case cff_kind_fixed_thousand: FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 )); + break; default: ; /* never reached */ @@ -1672,7 +1491,7 @@ parser->top = parser->stack; } p++; - } + } /* while ( p < limit ) */ Exit: return error; |