diff options
Diffstat (limited to 'src/3rdparty/freetype/src/sfnt')
37 files changed, 1354 insertions, 797 deletions
diff --git a/src/3rdparty/freetype/src/sfnt/module.mk b/src/3rdparty/freetype/src/sfnt/module.mk index dbdde1564e..4491a1b22f 100644 --- a/src/3rdparty/freetype/src/sfnt/module.mk +++ b/src/3rdparty/freetype/src/sfnt/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2022 by +# 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, diff --git a/src/3rdparty/freetype/src/sfnt/pngshim.c b/src/3rdparty/freetype/src/sfnt/pngshim.c index 0ce4bdb6b5..33712162e0 100644 --- a/src/3rdparty/freetype/src/sfnt/pngshim.c +++ b/src/3rdparty/freetype/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2022 by + * Copyright (C) 2013-2023 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * @@ -239,7 +239,7 @@ *e = FT_THROW( Invalid_Stream_Read ); png_error( png, NULL ); - return; + /* return; (never reached) */ } ft_memcpy( data, stream->cursor, length ); @@ -406,9 +406,7 @@ switch ( color_type ) { - default: - /* Shouldn't happen, but fall through. */ - + default: /* Shouldn't happen, but ... */ case PNG_COLOR_TYPE_RGB_ALPHA: png_set_read_user_transform_fn( png, premultiply_data ); break; @@ -456,7 +454,7 @@ #else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* ANSI C doesn't like empty source files */ - typedef int _pngshim_dummy; + typedef int pngshim_dummy_; #endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ diff --git a/src/3rdparty/freetype/src/sfnt/pngshim.h b/src/3rdparty/freetype/src/sfnt/pngshim.h index 36d749c3c3..903bd2bc34 100644 --- a/src/3rdparty/freetype/src/sfnt/pngshim.h +++ b/src/3rdparty/freetype/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2022 by + * Copyright (C) 2013-2023 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/src/3rdparty/freetype/src/sfnt/rules.mk b/src/3rdparty/freetype/src/sfnt/rules.mk index ac4b571226..4d2d7e8d84 100644 --- a/src/3rdparty/freetype/src/sfnt/rules.mk +++ b/src/3rdparty/freetype/src/sfnt/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2022 by +# 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, diff --git a/src/3rdparty/freetype/src/sfnt/sfdriver.c b/src/3rdparty/freetype/src/sfnt/sfdriver.c index cc121e5790..0925940b03 100644 --- a/src/3rdparty/freetype/src/sfnt/sfdriver.c +++ b/src/3rdparty/freetype/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (body). * - * Copyright (C) 1996-2022 by + * 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, @@ -79,41 +79,57 @@ * */ - static void* - get_sfnt_table( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_load_table( FT_Face face, /* TT_Face */ + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + TT_Face ttface = (TT_Face)face; + + + return tt_face_load_any( ttface, tag, offset, buffer, length ); + } + + + FT_CALLBACK_DEF( void* ) + get_sfnt_table( FT_Face face, /* TT_Face */ FT_Sfnt_Tag tag ) { + TT_Face ttface = (TT_Face)face; + void* table; switch ( tag ) { case FT_SFNT_HEAD: - table = &face->header; + table = &ttface->header; break; case FT_SFNT_HHEA: - table = &face->horizontal; + table = &ttface->horizontal; break; case FT_SFNT_VHEA: - table = face->vertical_info ? &face->vertical : NULL; + table = ttface->vertical_info ? &ttface->vertical : NULL; break; case FT_SFNT_OS2: - table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2; + table = ( ttface->os2.version == 0xFFFFU ) ? NULL : &ttface->os2; break; case FT_SFNT_POST: - table = &face->postscript; + table = &ttface->postscript; break; case FT_SFNT_MAXP: - table = &face->max_profile; + table = &ttface->max_profile; break; case FT_SFNT_PCLT: - table = face->pclt.Version ? &face->pclt : NULL; + table = ttface->pclt.Version ? &ttface->pclt : NULL; break; default: @@ -124,26 +140,29 @@ } - static FT_Error - sfnt_table_info( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_table_info( FT_Face face, /* TT_Face */ FT_UInt idx, FT_ULong *tag, FT_ULong *offset, FT_ULong *length ) { + TT_Face ttface = (TT_Face)face; + + if ( !offset || !length ) return FT_THROW( Invalid_Argument ); if ( !tag ) - *length = face->num_tables; + *length = ttface->num_tables; else { - if ( idx >= face->num_tables ) + if ( idx >= ttface->num_tables ) return FT_THROW( Table_Missing ); - *tag = face->dir_tables[idx].Tag; - *offset = face->dir_tables[idx].Offset; - *length = face->dir_tables[idx].Length; + *tag = ttface->dir_tables[idx].Tag; + *offset = ttface->dir_tables[idx].Offset; + *length = ttface->dir_tables[idx].Length; } return FT_Err_Ok; @@ -153,9 +172,9 @@ FT_DEFINE_SERVICE_SFNT_TABLEREC( sfnt_service_sfnt_table, - (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */ - (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */ - (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */ + sfnt_load_table, /* FT_SFNT_TableLoadFunc load_table */ + get_sfnt_table, /* FT_SFNT_TableGetFunc get_table */ + sfnt_table_info /* FT_SFNT_TableInfoFunc table_info */ ) @@ -166,7 +185,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) sfnt_get_glyph_name( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, @@ -184,7 +203,7 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) sfnt_get_name_index( FT_Face face, const FT_String* glyph_name ) { @@ -221,8 +240,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( sfnt_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */ + sfnt_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + sfnt_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ @@ -378,61 +397,61 @@ { case 15: k4 ^= (FT_UInt32)tail[14] << 16; - /* fall through */ + FALL_THROUGH; case 14: k4 ^= (FT_UInt32)tail[13] << 8; - /* fall through */ + FALL_THROUGH; case 13: k4 ^= (FT_UInt32)tail[12]; k4 *= c4; k4 = ROTL32( k4, 18 ); k4 *= c1; h4 ^= k4; - /* fall through */ + FALL_THROUGH; case 12: k3 ^= (FT_UInt32)tail[11] << 24; - /* fall through */ + FALL_THROUGH; case 11: k3 ^= (FT_UInt32)tail[10] << 16; - /* fall through */ + FALL_THROUGH; case 10: k3 ^= (FT_UInt32)tail[9] << 8; - /* fall through */ + FALL_THROUGH; case 9: k3 ^= (FT_UInt32)tail[8]; k3 *= c3; k3 = ROTL32( k3, 17 ); k3 *= c4; h3 ^= k3; - /* fall through */ + FALL_THROUGH; case 8: k2 ^= (FT_UInt32)tail[7] << 24; - /* fall through */ + FALL_THROUGH; case 7: k2 ^= (FT_UInt32)tail[6] << 16; - /* fall through */ + FALL_THROUGH; case 6: k2 ^= (FT_UInt32)tail[5] << 8; - /* fall through */ + FALL_THROUGH; case 5: k2 ^= (FT_UInt32)tail[4]; k2 *= c2; k2 = ROTL32( k2, 16 ); k2 *= c3; h2 ^= k2; - /* fall through */ + FALL_THROUGH; case 4: k1 ^= (FT_UInt32)tail[3] << 24; - /* fall through */ + FALL_THROUGH; case 3: k1 ^= (FT_UInt32)tail[2] << 16; - /* fall through */ + FALL_THROUGH; case 2: k1 ^= (FT_UInt32)tail[1] << 8; - /* fall through */ + FALL_THROUGH; case 1: k1 ^= (FT_UInt32)tail[0]; k1 *= c1; @@ -523,15 +542,14 @@ FT_TRACE0(( "get_win_string:" " Character 0x%X invalid in PS name string\n", ((unsigned)p[0])*256 + (unsigned)p[1] )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_win_string_error: @@ -580,15 +598,14 @@ FT_TRACE0(( "get_apple_string:" " Character `%c' (0x%X) invalid in PS name string\n", *p, *p )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_apple_string_error: @@ -602,7 +619,7 @@ } - static FT_Bool + FT_CALLBACK_DEF( FT_Bool ) sfnt_get_name_id( TT_Face face, FT_UShort id, FT_Int *win, @@ -657,7 +674,7 @@ /* - * Find the shortest decimal representation of a 16.16 fixed point + * Find the shortest decimal representation of a 16.16 fixed-point * number. The function fills `buf' with the result, returning a pointer * to the position after the representation's last byte. */ @@ -733,7 +750,7 @@ an equivalent representation of `fixed'. The above FOR loop always finds the larger of the two values; I - verified this by iterating over all possible fixed point numbers. + verified this by iterating over all possible fixed-point numbers. If the remainder is 17232*10, both values are equally good, and we take the next even number (following IEEE 754's `round to nearest, @@ -741,7 +758,7 @@ If the remainder is smaller than 17232*10, the lower of the two numbers is nearer to the exact result (values 17232 and 34480 were - also found by testing all possible fixed point values). + also found by testing all possible fixed-point values). We use this to find a shorter decimal representation. If not ending with digit zero, we take the representation with less error. @@ -819,9 +836,9 @@ if ( !found ) { - /* as a last resort we try the family name; note that this is */ - /* not in the Adobe TechNote, but GX fonts (which predate the */ - /* TechNote) benefit from this behaviour */ + /* according to the 'name' documentation in the OpenType */ + /* specification the font family name is to be used if the */ + /* typographic family name is missing, so let's do that */ found = sfnt_get_name_id( face, TT_NAME_ID_FONT_FAMILY, &win, @@ -853,6 +870,10 @@ { FT_TRACE0(( "sfnt_get_var_ps_name:" " No valid PS name prefix for font instances found\n" )); + /* XXX It probably makes sense to never let this fail */ + /* since an arbitrary prefix should work, too. */ + /* On the other hand, it is very unlikely that */ + /* we ever reach this code at all. */ return NULL; } @@ -1041,47 +1062,49 @@ #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - static const char* - sfnt_get_ps_name( TT_Face face ) + FT_CALLBACK_DEF( const char* ) + sfnt_get_ps_name( FT_Face face ) /* TT_Face */ { + TT_Face ttface = (TT_Face)face; + FT_Int found, win, apple; const char* result = NULL; - if ( face->postscript_name ) - return face->postscript_name; + if ( ttface->postscript_name ) + return ttface->postscript_name; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->blend && - ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || - FT_IS_VARIATION( FT_FACE( face ) ) ) ) + if ( ttface->blend && + ( FT_IS_NAMED_INSTANCE( face ) || + FT_IS_VARIATION( face ) ) ) { - face->postscript_name = sfnt_get_var_ps_name( face ); - return face->postscript_name; + ttface->postscript_name = sfnt_get_var_ps_name( ttface ); + return ttface->postscript_name; } #endif /* scan the name table to see whether we have a Postscript name here, */ /* either in Macintosh or Windows platform encodings */ - found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + found = sfnt_get_name_id( ttface, TT_NAME_ID_PS_NAME, &win, &apple ); if ( !found ) return NULL; /* prefer Windows entries over Apple */ if ( win != -1 ) - result = get_win_string( face->root.memory, - face->name_table.stream, - face->name_table.names + win, + result = get_win_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + win, sfnt_is_postscript, 1 ); if ( !result && apple != -1 ) - result = get_apple_string( face->root.memory, - face->name_table.stream, - face->name_table.names + apple, + result = get_apple_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + apple, sfnt_is_postscript, 1 ); - face->postscript_name = result; + ttface->postscript_name = result; return result; } @@ -1090,7 +1113,7 @@ FT_DEFINE_SERVICE_PSFONTNAMEREC( sfnt_service_ps_name, - (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */ + sfnt_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -1100,14 +1123,14 @@ FT_DEFINE_SERVICE_TTCMAPSREC( tt_service_get_cmap_info, - (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */ + tt_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) #ifdef TT_CONFIG_OPTION_BDF static FT_Error - sfnt_get_charset_id( TT_Face face, + sfnt_get_charset_id( FT_Face face, const char* *acharset_encoding, const char* *acharset_registry ) { @@ -1145,8 +1168,8 @@ FT_DEFINE_SERVICE_BDFRec( sfnt_service_bdf, - (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */ - (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */ + sfnt_get_charset_id, /* FT_BDF_GetCharsetIdFunc get_charset_id */ + tt_face_find_bdf_prop /* FT_BDF_GetPropertyFunc get_property */ ) @@ -1337,9 +1360,9 @@ (const void*)&sfnt_interface, /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) sfnt_get_interface /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + sfnt_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/sfnt/sfdriver.h b/src/3rdparty/freetype/src/sfnt/sfdriver.h index 6a2e3e9c7b..2445958b69 100644 --- a/src/3rdparty/freetype/src/sfnt/sfdriver.h +++ b/src/3rdparty/freetype/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (specification). * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/sferrors.h b/src/3rdparty/freetype/src/sfnt/sferrors.h index 99ef3f9fce..e7a8eb04bb 100644 --- a/src/3rdparty/freetype/src/sfnt/sferrors.h +++ b/src/3rdparty/freetype/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ * * SFNT error codes (specification only). * - * Copyright (C) 2001-2022 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/3rdparty/freetype/src/sfnt/sfnt.c b/src/3rdparty/freetype/src/sfnt/sfnt.c index 9b3ceaedc0..8e4f08a90c 100644 --- a/src/3rdparty/freetype/src/sfnt/sfnt.c +++ b/src/3rdparty/freetype/src/sfnt/sfnt.c @@ -4,7 +4,7 @@ * * Single object library component. * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/sfobjs.c b/src/3rdparty/freetype/src/sfnt/sfobjs.c index a0da984e7a..f5d66ef840 100644 --- a/src/3rdparty/freetype/src/sfnt/sfobjs.c +++ b/src/3rdparty/freetype/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ * * SFNT object management (base). * - * Copyright (C) 1996-2022 by + * 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, @@ -534,17 +534,23 @@ 0 ); } - if ( !face->var ) + if ( !face->tt_var ) { /* we want the metrics variations interface */ /* from the `truetype' module only */ FT_Module tt_module = FT_Get_Module( library, "truetype" ); - face->var = ft_module_get_service( tt_module, - FT_SERVICE_ID_METRICS_VARIATIONS, - 0 ); + face->tt_var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); } + + if ( !face->face_var ) + face->face_var = ft_module_get_service( + &face->root.driver->root, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); #endif FT_TRACE2(( "SFNT driver\n" )); @@ -692,6 +698,9 @@ instance_offset += instance_size; } + /* named instance indices start with value 1 */ + face->var_default_named_instance = i + 1; + if ( i == num_instances ) { /* no default instance in named instance table; */ @@ -1054,6 +1063,16 @@ GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Memory memory = face->root.memory; + + + if ( FT_STRDUP( face->non_var_style_name, face->root.style_name ) ) + goto Exit; + } +#endif + /* now set up root fields */ { FT_Face root = &face->root; @@ -1107,13 +1126,7 @@ /* Don't bother to load the tables unless somebody asks for them. */ /* No need to do work which will (probably) not be used. */ if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) - { - if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && - tt_face_lookup_table( face, TTAG_gvar ) != 0 ) - flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; - if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 ) - flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; - } + flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; #endif root->face_flags = flags; @@ -1227,7 +1240,7 @@ if ( count > 0 ) { - FT_Memory memory = face->root.stream->memory; + FT_Memory memory = face->root.memory; FT_UShort em_size = face->header.Units_Per_EM; FT_Short avgwidth = face->os2.xAvgCharWidth; FT_Size_Metrics metrics; @@ -1506,6 +1519,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->var_postscript_prefix ); + FT_FREE( face->non_var_style_name ); #endif /* freeing glyph color palette data */ diff --git a/src/3rdparty/freetype/src/sfnt/sfobjs.h b/src/3rdparty/freetype/src/sfnt/sfobjs.h index 1d99bfede4..906aebbf90 100644 --- a/src/3rdparty/freetype/src/sfnt/sfobjs.h +++ b/src/3rdparty/freetype/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ * * SFNT object management (specification). * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff.c b/src/3rdparty/freetype/src/sfnt/sfwoff.c index 0e8ec3fa93..7c0ce2205e 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff.c +++ b/src/3rdparty/freetype/src/sfnt/sfwoff.c @@ -4,7 +4,7 @@ * * WOFF format management (base). * - * Copyright (C) 1996-2022 by + * 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, @@ -162,8 +162,7 @@ } /* Don't trust `totalSfntSize' before thorough checks. */ - if ( FT_QALLOC( sfnt, 12 + woff.num_tables * 16UL ) || - FT_NEW( sfnt_stream ) ) + if ( FT_QALLOC( sfnt, 12 ) || FT_NEW( sfnt_stream ) ) goto Exit; sfnt_header = sfnt; @@ -196,8 +195,8 @@ /* tag value, the tables themselves are not. We thus have to */ /* sort them by offset and check that they don't overlap. */ - if ( FT_NEW_ARRAY( tables, woff.num_tables ) || - FT_NEW_ARRAY( indices, woff.num_tables ) ) + if ( FT_QNEW_ARRAY( tables, woff.num_tables ) || + FT_QNEW_ARRAY( indices, woff.num_tables ) ) goto Exit; FT_TRACE2(( "\n" )); @@ -328,9 +327,7 @@ } /* Now use `totalSfntSize'. */ - if ( FT_REALLOC( sfnt, - 12 + woff.num_tables * 16UL, - woff.totalSfntSize ) ) + if ( FT_QREALLOC( sfnt, 12, woff.totalSfntSize ) ) goto Exit; sfnt_header = sfnt + 12; @@ -429,7 +426,7 @@ #else /* !FT_CONFIG_OPTION_USE_ZLIB */ /* ANSI C doesn't like empty source files */ - typedef int _sfwoff_dummy; + typedef int sfwoff_dummy_; #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff.h b/src/3rdparty/freetype/src/sfnt/sfwoff.h index 5866a16194..d438422737 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff.h +++ b/src/3rdparty/freetype/src/sfnt/sfwoff.h @@ -4,7 +4,7 @@ * * WOFFF format management (specification). * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff2.c b/src/3rdparty/freetype/src/sfnt/sfwoff2.c index b2855b8e72..2be44a347a 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-2022 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -36,6 +36,8 @@ #undef FT_COMPONENT #define FT_COMPONENT sfwoff2 + /* An arbitrary, heuristic size limit (67MByte) for expanded WOFF2 data. */ +#define MAX_SFNT_SIZE ( 1 << 26 ) #define READ_255USHORT( var ) FT_SET_ERROR( Read255UShort( stream, &var ) ) @@ -229,9 +231,9 @@ { FT_TRACE6(( "Reallocating %lu to %lu.\n", *dst_size, (*offset + size) )); - if ( FT_REALLOC( dst, - (FT_ULong)( *dst_size ), - (FT_ULong)( *offset + size ) ) ) + if ( FT_QREALLOC( dst, + (FT_ULong)( *dst_size ), + (FT_ULong)( *offset + size ) ) ) goto Exit; *dst_size = *offset + size; @@ -784,7 +786,7 @@ goto Fail; loca_buf_size = loca_values_size * offset_size; - if ( FT_QNEW_ARRAY( loca_buf, loca_buf_size ) ) + if ( FT_QALLOC( loca_buf, loca_buf_size ) ) goto Fail; dst = loca_buf; @@ -863,7 +865,7 @@ WOFF2_Point points = NULL; - if ( FT_NEW_ARRAY( substreams, num_substreams ) ) + if ( FT_QNEW_ARRAY( substreams, num_substreams ) ) goto Fail; if ( FT_STREAM_SKIP( 2 ) ) @@ -926,7 +928,7 @@ offset += overlap_bitmap_length; } - if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) ) + if ( FT_QNEW_ARRAY( loca_values, num_glyphs + 1 ) ) goto Fail; points_size = 0; @@ -938,10 +940,10 @@ substreams[BBOX_STREAM].offset += bbox_bitmap_length; glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF; - if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) ) + if ( FT_QALLOC( glyph_buf, glyph_buf_size ) ) goto Fail; - if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) ) + if ( FT_QNEW_ARRAY( info->x_mins, num_glyphs ) ) goto Fail; for ( i = 0; i < num_glyphs; ++i ) @@ -999,7 +1001,7 @@ size_needed = 12 + composite_size + instruction_size; if ( glyph_buf_size < size_needed ) { - if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) ) + if ( FT_QREALLOC( glyph_buf, glyph_buf_size, size_needed ) ) goto Fail; glyph_buf_size = size_needed; } @@ -1075,7 +1077,7 @@ have_overlap = TRUE; } - if ( FT_NEW_ARRAY( n_points_arr, n_contours ) ) + if ( FT_QNEW_ARRAY( n_points_arr, n_contours ) ) goto Fail; if ( FT_STREAM_SEEK( substreams[N_POINTS_STREAM].offset ) ) @@ -1112,7 +1114,7 @@ /* Create array to store point information. */ points_size = total_n_points; - if ( FT_NEW_ARRAY( points, points_size ) ) + if ( FT_QNEW_ARRAY( points, points_size ) ) goto Fail; if ( triplet_decode( flags_buf, @@ -1141,7 +1143,7 @@ instruction_size; if ( glyph_buf_size < size_needed ) { - if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) ) + if ( FT_QREALLOC( glyph_buf, glyph_buf_size, size_needed ) ) goto Fail; glyph_buf_size = size_needed; } @@ -1226,8 +1228,7 @@ *glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size ); /* Store x_mins, may be required to reconstruct `hmtx'. */ - if ( n_contours > 0 ) - info->x_mins[i] = (FT_Short)x_min; + info->x_mins[i] = (FT_Short)x_min; } info->glyf_table->dst_length = dest_offset - info->glyf_table->dst_offset; @@ -1344,7 +1345,7 @@ offset_size = index_format ? 4 : 2; /* Create `x_mins' array. */ - if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) ) + if ( FT_QNEW_ARRAY( info->x_mins, num_glyphs ) ) return error; loca_offset = info->loca_table->src_offset; @@ -1432,8 +1433,8 @@ if ( num_hmetrics < 1 ) goto Fail; - if ( FT_NEW_ARRAY( advance_widths, num_hmetrics ) || - FT_NEW_ARRAY( lsbs, num_glyphs ) ) + if ( FT_QNEW_ARRAY( advance_widths, num_hmetrics ) || + FT_QNEW_ARRAY( lsbs, num_glyphs ) ) goto Fail; /* Read `advanceWidth' stream. Always present. */ @@ -1484,7 +1485,7 @@ /* Build the hmtx table. */ hmtx_table_size = 2 * num_hmetrics + 2 * num_glyphs; - if ( FT_NEW_ARRAY( hmtx_table, hmtx_table_size ) ) + if ( FT_QALLOC( hmtx_table, hmtx_table_size ) ) goto Fail; dst = hmtx_table; @@ -1541,10 +1542,10 @@ { /* Memory management of `transformed_buf' is handled by the caller. */ - FT_Error error = FT_Err_Ok; - FT_Stream stream = NULL; - FT_Byte* buf_cursor = NULL; - FT_Byte* table_entry = NULL; + FT_Error error = FT_Err_Ok; + FT_Stream stream = NULL; + FT_Byte* buf_cursor = NULL; + FT_Byte table_entry[16]; /* We are reallocating memory for `sfnt', so its pointer may change. */ FT_Byte* sfnt = *sfnt_bytes; @@ -1585,10 +1586,6 @@ } } - /* Create buffer for table entries. */ - if ( FT_NEW_ARRAY( table_entry, 16 ) ) - goto Fail; - /* Create a stream for the uncompressed buffer. */ if ( FT_NEW( stream ) ) goto Fail; @@ -1751,7 +1748,6 @@ /* Set pointer of sfnt stream to its correct value. */ *sfnt_bytes = sfnt; - FT_FREE( table_entry ); FT_Stream_Close( stream ); FT_FREE( stream ); @@ -1764,7 +1760,6 @@ /* Set pointer of sfnt stream to its correct value. */ *sfnt_bytes = sfnt; - FT_FREE( table_entry ); FT_Stream_Close( stream ); FT_FREE( stream ); @@ -1877,8 +1872,8 @@ woff2.ttc_fonts = NULL; /* Read table directory. */ - if ( FT_NEW_ARRAY( tables, woff2.num_tables ) || - FT_NEW_ARRAY( indices, woff2.num_tables ) ) + if ( FT_QNEW_ARRAY( tables, woff2.num_tables ) || + FT_QNEW_ARRAY( indices, woff2.num_tables ) ) goto Exit; FT_TRACE2(( "\n" )); @@ -1949,10 +1944,11 @@ goto Exit; } + table->flags = flags; table->src_offset = src_offset; table->src_length = table->TransformLength; src_offset += table->TransformLength; - table->flags = flags; + table->dst_offset = 0; FT_TRACE2(( " %c%c%c%c %08d %08d %08ld %08ld %08ld\n", (FT_Char)( table->Tag >> 24 ), @@ -2010,6 +2006,7 @@ FT_TRACE4(( "Number of fonts in TTC: %d\n", woff2.num_fonts )); + /* pre-zero pointers within in case of failure */ if ( FT_NEW_ARRAY( woff2.ttc_fonts, woff2.num_fonts ) ) goto Exit; @@ -2023,7 +2020,7 @@ if ( FT_READ_ULONG( ttc_font->flavor ) ) goto Exit; - if ( FT_NEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) ) + if ( FT_QNEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) ) goto Exit; FT_TRACE5(( "Number of tables in font %d: %d\n", @@ -2185,9 +2182,8 @@ else sfnt_size = woff2.totalSfntSize; - /* Value 1<<26 = 67108864 is heuristic. */ - if (sfnt_size >= (1 << 26)) - sfnt_size = 1 << 26; + if ( sfnt_size >= MAX_SFNT_SIZE ) + sfnt_size = MAX_SFNT_SIZE; #ifdef FT_DEBUG_LEVEL_TRACE if ( sfnt_size != woff2.totalSfntSize ) @@ -2262,10 +2258,15 @@ goto Exit; } - if ( woff2.uncompressed_size > sfnt_size ) + /* We must not blindly trust `uncompressed_size` since its */ + /* value might be corrupted. If it is too large, reject the */ + /* font. In other words, we don't accept a WOFF2 font that */ + /* expands to something larger than MAX_SFNT_SIZE. If ever */ + /* necessary, this limit can be easily adjusted. */ + if ( woff2.uncompressed_size > MAX_SFNT_SIZE ) { - FT_ERROR(( "woff2_open_font: SFNT table lengths are too large.\n" )); - error = FT_THROW( Invalid_Table ); + FT_ERROR(( "Uncompressed font too large.\n" )); + error = FT_THROW( Array_Too_Large ); goto Exit; } @@ -2302,9 +2303,9 @@ { FT_TRACE5(( "Trimming sfnt stream from %lu to %lu.\n", sfnt_size, woff2.actual_sfnt_size )); - if ( FT_REALLOC( sfnt, - (FT_ULong)( sfnt_size ), - (FT_ULong)( woff2.actual_sfnt_size ) ) ) + if ( FT_QREALLOC( sfnt, + (FT_ULong)( sfnt_size ), + (FT_ULong)( woff2.actual_sfnt_size ) ) ) goto Exit; } @@ -2383,7 +2384,7 @@ #else /* !FT_CONFIG_OPTION_USE_BROTLI */ /* ANSI C doesn't like empty source files */ - typedef int _sfwoff2_dummy; + typedef int sfwoff2_dummy_; #endif /* !FT_CONFIG_OPTION_USE_BROTLI */ diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff2.h b/src/3rdparty/freetype/src/sfnt/sfwoff2.h index e84982ed9c..4901286ee0 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff2.h +++ b/src/3rdparty/freetype/src/sfnt/sfwoff2.h @@ -4,7 +4,7 @@ * * WOFFF2 format management (specification). * - * Copyright (C) 2019-2022 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/3rdparty/freetype/src/sfnt/ttbdf.c b/src/3rdparty/freetype/src/sfnt/ttbdf.c index 4d2faf2385..536fa7467e 100644 --- a/src/3rdparty/freetype/src/sfnt/ttbdf.c +++ b/src/3rdparty/freetype/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded BDF properties (body). * - * Copyright (C) 2005-2022 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -136,13 +136,14 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, /* TT_Face */ const char* property_name, BDF_PropertyRec *aprop ) { - TT_BDF bdf = &face->bdf; - FT_Size size = FT_FACE( face )->size; - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + TT_BDF bdf = &ttface->bdf; + FT_Size size = FT_FACE_SIZE( face ); + FT_Error error = FT_Err_Ok; FT_Byte* p; FT_UInt count; FT_Byte* strike; @@ -153,7 +154,7 @@ if ( bdf->loaded == 0 ) { - error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); + error = tt_face_load_bdf_props( ttface, FT_FACE_STREAM( face ) ); if ( error ) goto Exit; } @@ -248,7 +249,7 @@ #else /* !TT_CONFIG_OPTION_BDF */ /* ANSI C doesn't like empty source files */ - typedef int _tt_bdf_dummy; + typedef int tt_bdf_dummy_; #endif /* !TT_CONFIG_OPTION_BDF */ diff --git a/src/3rdparty/freetype/src/sfnt/ttbdf.h b/src/3rdparty/freetype/src/sfnt/ttbdf.h index b7b11c9bec..0d7a0acecc 100644 --- a/src/3rdparty/freetype/src/sfnt/ttbdf.h +++ b/src/3rdparty/freetype/src/sfnt/ttbdf.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded BDF properties (specification). * - * Copyright (C) 2005-2022 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -34,7 +34,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, const char* property_name, BDF_PropertyRec *aprop ); diff --git a/src/3rdparty/freetype/src/sfnt/ttcmap.c b/src/3rdparty/freetype/src/sfnt/ttcmap.c index bfeabacb7d..9ba25dcbc1 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcmap.c +++ b/src/3rdparty/freetype/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (body). * - * Copyright (C) 2002-2022 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -59,10 +59,14 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_init( TT_CMap cmap, - FT_Byte* table ) + tt_cmap_init( FT_CMap cmap, /* TT_CMap */ + void* table_ ) { - cmap->data = table; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = (FT_Byte*)table_; + + + ttcmap->data = table; return FT_Err_Ok; } @@ -128,21 +132,23 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap0_char_index( TT_CMap cmap, + tt_cmap0_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; return char_code < 256 ? table[6 + char_code] : 0; } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap0_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap0_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 charcode = *pchar_code; FT_UInt32 result = 0; FT_UInt gindex = 0; @@ -165,10 +171,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap0_get_info( TT_CMap cmap, + tt_cmap0_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 0; @@ -453,10 +460,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap2_char_index( TT_CMap cmap, + tt_cmap2_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* subheader; @@ -491,11 +499,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap2_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap2_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pcharcode ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt gindex = 0; FT_UInt32 result = 0; FT_UInt32 charcode = *pcharcode + 1; @@ -579,10 +588,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap2_get_info( TT_CMap cmap, + tt_cmap2_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 2; @@ -706,18 +716,20 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_init( TT_CMap4 cmap, - FT_Byte* table ) + tt_cmap4_init( FT_CMap cmap, /* TT_CMap4 */ + void* table_ ) { + TT_CMap4 ttcmap = (TT_CMap4)cmap; + FT_Byte* table = (FT_Byte*)table_; FT_Byte* p; - cmap->cmap.data = table; + ttcmap->cmap.data = table; - p = table + 6; - cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; - cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; - cmap->cur_gindex = 0; + p = table + 6; + ttcmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; + ttcmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; + ttcmap->cur_gindex = 0; return FT_Err_Ok; } @@ -755,7 +767,7 @@ cmap->cur_start == 0xFFFFU && cmap->cur_end == 0xFFFFU ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; @@ -788,15 +800,12 @@ static void tt_cmap4_next( TT_CMap4 cmap ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt charcode; - if ( cmap->cur_charcode >= 0xFFFFUL ) - goto Fail; - charcode = (FT_UInt)cmap->cur_charcode + 1; if ( charcode < cmap->cur_start ) @@ -882,7 +891,6 @@ charcode = cmap->cur_start; } - Fail: cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; cmap->cur_gindex = 0; } @@ -1097,32 +1105,26 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt i, num_segs; - FT_UInt32 charcode = *pcharcode; + FT_UInt32 charcode = *pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; FT_Byte* q; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); - - num_segs = num_segs2 >> 1; + num_segs = TT_PEEK_USHORT( p ) >> 1; if ( !num_segs ) return 0; - if ( next ) - charcode++; - - if ( charcode > 0xFFFFU ) - return 0; + num_segs2 = num_segs << 1; /* linear search */ p = cmap->data + 14; /* ends table */ @@ -1232,37 +1234,30 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt max, min, mid, num_segs; - FT_UInt charcode = (FT_UInt)*pcharcode; + FT_UInt charcode = (FT_UInt)*pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); + num_segs = TT_PEEK_USHORT( p ) >> 1; - if ( !num_segs2 ) + if ( !num_segs ) return 0; - num_segs = num_segs2 >> 1; - - /* make compiler happy */ - mid = num_segs; - end = 0xFFFFU; - - if ( next ) - charcode++; + num_segs2 = num_segs << 1; min = 0; max = num_segs; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 14 + mid * 2; @@ -1445,6 +1440,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -1454,12 +1450,8 @@ /* if `charcode' is not in any segment, then `mid' is */ /* the segment nearest to `charcode' */ - if ( charcode > end ) - { - mid++; - if ( mid == num_segs ) - return 0; - } + if ( charcode > end && ++mid == num_segs ) + return 0; if ( tt_cmap4_set_range( cmap4, mid ) ) { @@ -1474,7 +1466,6 @@ cmap4->cur_gindex = gindex; else { - cmap4->cur_charcode = charcode; tt_cmap4_next( cmap4 ); gindex = cmap4->cur_gindex; } @@ -1489,31 +1480,35 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap4_char_index( TT_CMap cmap, + tt_cmap4_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; + + if ( char_code >= 0x10000UL ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + return tt_cmap4_char_map_linear( ttcmap, &char_code, 0 ); else - return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap4_char_map_binary( ttcmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap4_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap4_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; FT_UInt gindex; if ( *pchar_code >= 0xFFFFU ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + gindex = tt_cmap4_char_map_linear( ttcmap, pchar_code, 1 ); else { TT_CMap4 cmap4 = (TT_CMap4)cmap; @@ -1528,7 +1523,7 @@ *pchar_code = cmap4->cur_charcode; } else - gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap4_char_map_binary( ttcmap, pchar_code, 1 ); } return gindex; @@ -1536,10 +1531,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_get_info( TT_CMap cmap, + tt_cmap4_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 4; @@ -1640,10 +1636,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap6_char_index( TT_CMap cmap, + tt_cmap6_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 6; FT_UInt start = TT_NEXT_USHORT( p ); @@ -1661,11 +1658,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap6_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap6_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; FT_UInt gindex = 0; @@ -1706,10 +1704,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap6_get_info( TT_CMap cmap, + tt_cmap6_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 6; @@ -1900,10 +1899,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap8_char_index( TT_CMap cmap, + tt_cmap8_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); @@ -1932,15 +1932,16 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap8_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap8_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Face face = cmap->cmap.charmap.face; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); FT_UInt32 result = 0; FT_UInt32 char_code; FT_UInt gindex = 0; - FT_Byte* table = cmap->data; + FT_Byte* table = ttcmap->data; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); FT_UInt32 start, end, start_id; @@ -2000,10 +2001,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap8_get_info( TT_CMap cmap, + tt_cmap8_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 8; @@ -2104,10 +2106,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap10_char_index( TT_CMap cmap, + tt_cmap10_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 12; FT_UInt32 start = TT_NEXT_ULONG( p ); @@ -2130,11 +2133,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap10_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap10_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 char_code; FT_UInt gindex = 0; FT_Byte* p = table + 12; @@ -2172,10 +2176,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap10_get_info( TT_CMap cmap, + tt_cmap10_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 10; @@ -2253,15 +2258,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_init( TT_CMap12 cmap, - FT_Byte* table ) + tt_cmap12_init( FT_CMap cmap, /* TT_CMap12 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Byte* table = (FT_Byte*)table_; + - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); + ttcmap->cmap.data = table; - cmap->valid = 0; + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2331,23 +2340,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap12_next( TT_CMap12 cmap ) + tt_cmap12_next( FT_CMap cmap ) /* TT_CMap12 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, start_id, char_code; - FT_ULong n; - FT_UInt gindex; - + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, start_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; - char_code = cmap->cur_charcode + 1; + char_code = ttcmap->cur_charcode + 1; - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); start_id = TT_PEEK_ULONG( p ); @@ -2379,16 +2386,16 @@ if ( gindex >= (FT_UInt)face->num_glyphs ) continue; - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2400,7 +2407,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end, start_id; FT_UInt32 max, min, mid; @@ -2408,23 +2415,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2448,22 +2443,19 @@ break; } } + while ( min < max ); if ( next ) { - FT_Face face = cmap->cmap.charmap.face; + FT_Face face = FT_CMAP_FACE( cmap ); TT_CMap12 cmap12 = (TT_CMap12)cmap; /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap12->valid = 1; cmap12->cur_charcode = char_code; @@ -2474,7 +2466,7 @@ if ( !gindex ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) gindex = cmap12->cur_gindex; @@ -2490,25 +2482,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap12_char_index( TT_CMap cmap, + tt_cmap12_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap12_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap12_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap12_char_next( FT_CMap cmap, /* TT_CMap12 */ FT_UInt32 *pchar_code ) { TT_CMap12 cmap12 = (TT_CMap12)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) { gindex = cmap12->cur_gindex; @@ -2518,17 +2513,18 @@ gindex = 0; } else - gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap12_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_get_info( TT_CMap cmap, + tt_cmap12_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 12; @@ -2606,15 +2602,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_init( TT_CMap13 cmap, - FT_Byte* table ) + tt_cmap13_init( FT_CMap cmap, /* TT_CMap13 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Byte* table = (FT_Byte*)table_; + - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); + ttcmap->cmap.data = table; - cmap->valid = 0; + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2679,23 +2679,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap13_next( TT_CMap13 cmap ) + tt_cmap13_next( FT_CMap cmap ) /* TT_CMap13 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, glyph_id, char_code; - FT_ULong n; - FT_UInt gindex; - + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, glyph_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; - char_code = cmap->cur_charcode + 1; + char_code = ttcmap->cur_charcode + 1; - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); glyph_id = TT_PEEK_ULONG( p ); @@ -2709,17 +2707,16 @@ if ( gindex && gindex < (FT_UInt)face->num_glyphs ) { - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } } - Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2731,7 +2728,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end; FT_UInt32 max, min, mid; @@ -2739,23 +2736,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2774,6 +2759,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -2784,12 +2770,8 @@ /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap13->valid = 1; cmap13->cur_charcode = char_code; @@ -2800,7 +2782,7 @@ if ( !gindex ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) gindex = cmap13->cur_gindex; @@ -2816,25 +2798,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap13_char_index( TT_CMap cmap, + tt_cmap13_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap13_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap13_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap13_char_next( FT_CMap cmap, /* TT_CMap13 */ FT_UInt32 *pchar_code ) { TT_CMap13 cmap13 = (TT_CMap13)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) { gindex = cmap13->cur_gindex; @@ -2844,17 +2829,18 @@ gindex = 0; } else - gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap13_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_get_info( TT_CMap cmap, + tt_cmap13_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 13; @@ -2969,14 +2955,15 @@ FT_CALLBACK_DEF( void ) - tt_cmap14_done( TT_CMap14 cmap ) + tt_cmap14_done( FT_CMap cmap ) /* TT_CMap14 */ { - FT_Memory memory = cmap->memory; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Memory memory = ttcmap->memory; - cmap->max_results = 0; - if ( memory && cmap->results ) - FT_FREE( cmap->results ); + ttcmap->max_results = 0; + if ( memory && ttcmap->results ) + FT_FREE( ttcmap->results ); } @@ -3004,15 +2991,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_init( TT_CMap14 cmap, - FT_Byte* table ) + tt_cmap14_init( FT_CMap cmap, /* TT_CMap14 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 6; - cmap->num_selectors = FT_PEEK_ULONG( table ); - cmap->max_results = 0; - cmap->results = NULL; + + ttcmap->cmap.data = table; + + table += 6; + ttcmap->num_selectors = FT_PEEK_ULONG( table ); + ttcmap->max_results = 0; + ttcmap->results = NULL; return FT_Err_Ok; } @@ -3142,7 +3133,7 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_index( TT_CMap cmap, + tt_cmap14_char_index( FT_CMap cmap, FT_UInt32 char_code ) { FT_UNUSED( cmap ); @@ -3153,8 +3144,8 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap14_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap14_char_next( FT_CMap cmap, FT_UInt32 *pchar_code ) { FT_UNUSED( cmap ); @@ -3166,7 +3157,7 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_get_info( TT_CMap cmap, + tt_cmap14_get_info( FT_CharMap cmap, TT_CMapInfo *cmap_info ) { FT_UNUSED( cmap ); @@ -3280,12 +3271,16 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_var_index( TT_CMap cmap, - TT_CMap ucmap, + tt_cmap14_char_var_index( FT_CMap cmap, /* TT_CMap */ + FT_CMap ucmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap ttucmap = (TT_CMap)ucmap; + + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3296,16 +3291,16 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_PEEK_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) { /* This is the default variant of this charcode. GID not stored */ /* here; stored in the normal Unicode charmap instead. */ - return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); + return ttucmap->cmap.clazz->char_index( &ttucmap->cmap, charcode ); } if ( nondefOff != 0 ) - return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, + return tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, charcode ); return 0; @@ -3313,11 +3308,13 @@ FT_CALLBACK_DEF( FT_Int ) - tt_cmap14_char_var_isdefault( TT_CMap cmap, + tt_cmap14_char_var_isdefault( FT_CMap cmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3328,13 +3325,13 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_NEXT_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) return 1; - if ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charcode ) != 0 ) + if ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charcode ) != 0 ) return 0; return -1; @@ -3342,12 +3339,13 @@ FT_CALLBACK_DEF( FT_UInt32* ) - tt_cmap14_variants( TT_CMap cmap, + tt_cmap14_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory ) { + TT_CMap ttcmap = (TT_CMap)cmap; TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* result; FT_UInt32 i; @@ -3368,13 +3366,14 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_char_variants( TT_CMap cmap, + tt_cmap14_char_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory, FT_UInt32 charCode ) { - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* q; @@ -3388,12 +3387,12 @@ FT_ULong nondefOff = TT_NEXT_ULONG( p ); - if ( ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, - charCode ) ) || - ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charCode ) != 0 ) ) + if ( ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, + charCode ) ) || + ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charCode ) != 0 ) ) { q[0] = varSel; q++; @@ -3489,15 +3488,16 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_variant_chars( TT_CMap cmap, + tt_cmap14_variant_chars( FT_CMap cmap, /* TT_CMap */ FT_Memory memory, FT_UInt32 variantSelector ) { - FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, - variantSelector ); - FT_Int i; - FT_ULong defOff; - FT_ULong nondefOff; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte *p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); + FT_Int i; + FT_ULong defOff; + FT_ULong nondefOff; if ( !p ) @@ -3510,16 +3510,16 @@ return NULL; if ( defOff == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); else if ( nondefOff == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); else { /* Both a default and a non-default glyph set? That's probably not */ /* good font design, but the spec allows for it... */ - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 numRanges; FT_UInt32 numMappings; FT_UInt32 duni; @@ -3531,18 +3531,18 @@ FT_UInt32 *ret; - p = cmap->data + nondefOff; - dp = cmap->data + defOff; + p = ttcmap->data + nondefOff; + dp = ttcmap->data + defOff; numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); dcnt = tt_cmap14_def_char_count( dp ); numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); if ( numMappings == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); if ( dcnt == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) @@ -3664,9 +3664,10 @@ #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_CALLBACK_DEF( const char * ) - tt_get_glyph_name( TT_Face face, + tt_get_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; FT_String* PSname = NULL; @@ -3677,12 +3678,13 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + tt_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -3693,17 +3695,18 @@ return psnames->unicodes_init( memory, unicodes, face->root.num_glyphs, - (PS_GetGlyphNameFunc)&tt_get_glyph_name, + &tt_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - tt_cmap_unicode_done( PS_Unicodes unicodes ) + tt_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -3712,23 +3715,25 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + tt_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); @@ -3879,13 +3884,14 @@ } - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) tt_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { - FT_CMap cmap = (FT_CMap)charmap; + FT_CMap cmap = FT_CMAP( charmap ); TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; + if ( clazz->get_cmap_info ) return clazz->get_cmap_info( charmap, cmap_info ); else diff --git a/src/3rdparty/freetype/src/sfnt/ttcmap.h b/src/3rdparty/freetype/src/sfnt/ttcmap.h index b10860b345..ff52917ed5 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcmap.h +++ b/src/3rdparty/freetype/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2022 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/3rdparty/freetype/src/sfnt/ttcmapc.h b/src/3rdparty/freetype/src/sfnt/ttcmapc.h index 6822a9cd6b..0af48c2478 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcmapc.h +++ b/src/3rdparty/freetype/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ * * TT CMAP classes definitions (specification only). * - * Copyright (C) 2009-2022 by + * Copyright (C) 2009-2023 by * Oran Agra and Mickey Gabel. * * This file is part of the FreeType project, and may only be used, diff --git a/src/3rdparty/freetype/src/sfnt/ttcolr.c b/src/3rdparty/freetype/src/sfnt/ttcolr.c index d54231fd64..281e7135ee 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcolr.c +++ b/src/3rdparty/freetype/src/sfnt/ttcolr.c @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (body). * - * Copyright (C) 2018-2022 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. @@ -34,6 +34,9 @@ #include <freetype/ftcolor.h> #include <freetype/config/integer-types.h> +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include <freetype/internal/services/svmm.h> +#endif #ifdef TT_CONFIG_OPTION_COLOR_LAYERS @@ -46,17 +49,42 @@ #define LAYER_V1_LIST_PAINT_OFFSET_SIZE 4U #define LAYER_V1_LIST_NUM_LAYERS_SIZE 4U #define COLOR_STOP_SIZE 6U +#define VAR_IDX_BASE_SIZE 4U #define LAYER_SIZE 4U -#define COLR_HEADER_SIZE 14U +/* https://docs.microsoft.com/en-us/typography/opentype/spec/colr#colr-header */ +/* 3 * uint16 + 2 * Offset32 */ +#define COLRV0_HEADER_SIZE 14U +/* COLRV0_HEADER_SIZE + 5 * Offset32 */ +#define COLRV1_HEADER_SIZE 34U + + +#define ENSURE_READ_BYTES( byte_size ) \ + if ( p < colr->paints_start_v1 || \ + p > (FT_Byte*)colr->table + colr->table_size - byte_size ) \ + return 0 typedef enum FT_PaintFormat_Internal_ { - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER = 18, - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM = 20, - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22, - FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER = 26, - FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER = 30 + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID = 3, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT = 5, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT = 7, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT = 9, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM = 13, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE = 15, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE = 17, + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER = 18, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER = 19, + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM = 20, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM = 21, + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER = 23, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE = 25, + FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER = 26, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER = 27, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW = 29, + FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER = 30, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER = 31, } FT_PaintFormat_Internal; @@ -104,6 +132,12 @@ */ FT_Byte* paints_start_v1; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* Item Variation Store for variable 'COLR' v1. */ + GX_ItemVarStoreRec var_store; + GX_DeltaSetIdxMapRec delta_set_idx_map; +#endif + /* The memory that backs up the `COLR' table. */ void* table; FT_ULong table_size; @@ -139,6 +173,9 @@ FT_ULong base_glyphs_offset_v1, num_base_glyphs_v1; FT_ULong layer_offset_v1, num_layers_v1, clip_list_offset; FT_ULong table_size; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + FT_ULong colr_offset_in_stream; +#endif /* `COLR' always needs `CPAL' */ @@ -149,8 +186,12 @@ if ( error ) goto NoColr; - if ( table_size < COLR_HEADER_SIZE ) - goto InvalidTable; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + colr_offset_in_stream = FT_STREAM_POS(); +#endif + + if ( table_size < COLRV0_HEADER_SIZE ) + goto NoColr; if ( FT_FRAME_EXTRACT( table_size, table ) ) goto NoColr; @@ -183,9 +224,12 @@ if ( colr->version == 1 ) { + if ( table_size < COLRV1_HEADER_SIZE ) + goto InvalidTable; + base_glyphs_offset_v1 = FT_NEXT_ULONG( p ); - if ( base_glyphs_offset_v1 >= table_size ) + if ( base_glyphs_offset_v1 >= table_size - 4 ) goto InvalidTable; p1 = (FT_Byte*)( table + base_glyphs_offset_v1 ); @@ -205,6 +249,9 @@ if ( layer_offset_v1 ) { + if ( layer_offset_v1 >= table_size - 4 ) + goto InvalidTable; + p1 = (FT_Byte*)( table + layer_offset_v1 ); num_layers_v1 = FT_PEEK_ULONG( p1 ); @@ -239,6 +286,65 @@ colr->clip_list = (FT_Byte*)( table + clip_list_offset ); else colr->clip_list = 0; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + colr->var_store.dataCount = 0; + colr->var_store.varData = NULL; + colr->var_store.axisCount = 0; + colr->var_store.regionCount = 0; + colr->var_store.varRegionList = 0; + + colr->delta_set_idx_map.mapCount = 0; + colr->delta_set_idx_map.outerIndex = NULL; + colr->delta_set_idx_map.innerIndex = NULL; + + if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) + { + FT_ULong var_idx_map_offset, var_store_offset; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + var_idx_map_offset = FT_NEXT_ULONG( p ); + + if ( var_idx_map_offset >= table_size ) + goto InvalidTable; + + var_store_offset = FT_NEXT_ULONG( p ); + if ( var_store_offset >= table_size ) + goto InvalidTable; + + if ( var_store_offset ) + { + /* If variation info has not been initialized yet, try doing so, */ + /* otherwise loading the variation store will fail as it */ + /* requires access to `blend` for checking the number of axes. */ + if ( !face->blend ) + if ( mm->get_mm_var( FT_FACE( face ), NULL ) ) + goto InvalidTable; + + /* Try loading `VarIdxMap` and `VarStore`. */ + error = mm->load_item_var_store( + FT_FACE( face ), + colr_offset_in_stream + var_store_offset, + &colr->var_store ); + if ( error != FT_Err_Ok ) + goto InvalidTable; + } + + if ( colr->var_store.axisCount && var_idx_map_offset ) + { + error = mm->load_delta_set_idx_map( + FT_FACE( face ), + colr_offset_in_stream + var_idx_map_offset, + &colr->delta_set_idx_map, + &colr->var_store, + table_size ); + if ( error != FT_Err_Ok ) + goto InvalidTable; + } + } +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ } colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset ); @@ -251,6 +357,18 @@ return FT_Err_Ok; InvalidTable: +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + mm->done_delta_set_idx_map( FT_FACE( face ), + &colr->delta_set_idx_map ); + mm->done_item_var_store( FT_FACE( face ), + &colr->var_store ); + } +#endif + error = FT_THROW( Invalid_Table ); NoColr: @@ -272,6 +390,17 @@ if ( colr ) { +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + mm->done_delta_set_idx_map( FT_FACE( face ), + &colr->delta_set_idx_map ); + mm->done_item_var_store( FT_FACE( face ), + &colr->var_store ); + } +#endif FT_FRAME_RELEASE( colr->table ); FT_FREE( colr ); } @@ -354,7 +483,9 @@ iterator->p = colr->layers + offset; } - if ( iterator->layer >= iterator->num_layers ) + if ( iterator->layer >= iterator->num_layers || + iterator->p < colr->layers || + iterator->p >= ( (FT_Byte*)colr->table + colr->table_size ) ) return 0; *aglyph_index = FT_NEXT_USHORT( iterator->p ); @@ -372,13 +503,17 @@ static FT_Bool - read_color_line( FT_Byte* color_line_p, - FT_ColorLine *colorline ) + read_color_line( Colr* colr, + FT_Byte* color_line_p, + FT_ColorLine* colorline, + FT_Bool read_variable ) { FT_Byte* p = color_line_p; FT_PaintExtend paint_extend; + ENSURE_READ_BYTES( 3 ); + paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p ); if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT ) return 0; @@ -388,6 +523,7 @@ colorline->color_stop_iterator.num_color_stops = FT_NEXT_USHORT( p ); colorline->color_stop_iterator.p = p; colorline->color_stop_iterator.current_color_stop = 0; + colorline->color_stop_iterator.read_variable = read_variable; return 1; } @@ -413,6 +549,10 @@ if ( !child_table_pointer ) return 0; + if ( *p < colr->paints_start_v1 || + *p > (FT_Byte*)colr->table + colr->table_size - 1 - 3 ) + return 0; + paint_offset = FT_NEXT_UOFF3( *p ); if ( !paint_offset ) return 0; @@ -428,20 +568,85 @@ } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + static FT_Bool - read_paint( Colr* colr, + get_deltas_for_var_index_base ( TT_Face face, + Colr* colr, + FT_ULong var_index_base, + FT_UInt num_deltas, + FT_ItemVarDelta* deltas ) + { + FT_UInt outer_index = 0; + FT_UInt inner_index = 0; + FT_ULong loop_var_index = var_index_base; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + FT_UInt i = 0; + + + if ( var_index_base == 0xFFFFFFFF ) + { + for ( i = 0; i < num_deltas; ++i ) + deltas[i] = 0; + return 1; + } + + for ( i = 0; i < num_deltas; ++i ) + { + loop_var_index = var_index_base + i; + + if ( colr->delta_set_idx_map.innerIndex ) + { + if ( loop_var_index >= colr->delta_set_idx_map.mapCount ) + loop_var_index = colr->delta_set_idx_map.mapCount - 1; + + outer_index = colr->delta_set_idx_map.outerIndex[loop_var_index]; + inner_index = colr->delta_set_idx_map.innerIndex[loop_var_index]; + } + else + { + outer_index = 0; + inner_index = loop_var_index; + } + + deltas[i] = mm->get_item_delta( FT_FACE( face ), &colr->var_store, + outer_index, inner_index ); + } + + return 1; + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + static FT_Bool + read_paint( TT_Face face, + Colr* colr, FT_Byte* p, FT_COLR_Paint* apaint ) { - FT_Byte* paint_base = p; - FT_Byte* child_table_p = NULL; + FT_Byte* paint_base = p; + FT_Byte* child_table_p = NULL; + FT_Bool do_read_var = FALSE; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + FT_ULong var_index_base = 0; + /* Longest varIndexBase offset is 5 in the spec. */ + FT_ItemVarDelta item_deltas[6] = { 0, 0, 0, 0, 0, 0 }; +#else + FT_UNUSED( face ); +#endif if ( !p || !colr || !colr->table ) return 0; - if ( p < colr->paints_start_v1 || - p >= ( (FT_Byte*)colr->table + colr->table_size ) ) + /* The last byte of the 'COLR' table is at 'size-1'; subtract 1 of */ + /* that to account for the expected format byte we are going to read. */ + if ( p < colr->paints_start_v1 || + p > (FT_Byte*)colr->table + colr->table_size - 2 ) return 0; apaint->format = (FT_PaintFormat)FT_NEXT_BYTE( p ); @@ -475,16 +680,37 @@ return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID ) + else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID ) { + ENSURE_READ_BYTES( 4 ); apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p ); apaint->u.solid.color.alpha = FT_NEXT_SHORT( p ); +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1, + item_deltas ) ) + return 0; + + apaint->u.solid.color.alpha += (FT_F2Dot14)item_deltas[0]; + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_SOLID; + return 1; } else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH ) { + ENSURE_READ_BYTES(2); apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p ); return 1; @@ -500,16 +726,23 @@ if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) return 0; - if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ) + if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT || + ( do_read_var = + ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT ) ) ) { - if ( !read_color_line( child_table_p, - &apaint->u.linear_gradient.colorline ) ) + if ( !read_color_line( colr, + child_table_p, + &apaint->u.linear_gradient.colorline, + do_read_var ) ) return 0; /* - * In order to support variations expose these as FT_Fixed 16.16 values so - * that we can support fractional values after interpolation. + * In order to support variations expose these as FT_Fixed 16.16 + * values so that we can support fractional values after + * interpolation. */ + ENSURE_READ_BYTES( 12 ); apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); @@ -517,23 +750,52 @@ apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( do_read_var ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG ( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, + item_deltas ) ) + return 0; + + apaint->u.linear_gradient.p0.x += INT_TO_FIXED( item_deltas[0] ); + apaint->u.linear_gradient.p0.y += INT_TO_FIXED( item_deltas[1] ); + apaint->u.linear_gradient.p1.x += INT_TO_FIXED( item_deltas[2] ); + apaint->u.linear_gradient.p1.y += INT_TO_FIXED( item_deltas[3] ); + apaint->u.linear_gradient.p2.x += INT_TO_FIXED( item_deltas[4] ); + apaint->u.linear_gradient.p2.y += INT_TO_FIXED( item_deltas[5] ); + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_LINEAR_GRADIENT; + return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ) + else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT || + ( do_read_var = + ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT ) ) ) { FT_Pos tmp; - if ( !read_color_line( child_table_p, - &apaint->u.radial_gradient.colorline ) ) + if ( !read_color_line( colr, + child_table_p, + &apaint->u.radial_gradient.colorline, + do_read_var ) ) return 0; + /* In the OpenType specification, `r0` and `r1` are defined as */ /* `UFWORD`. Since FreeType doesn't have a corresponding 16.16 */ /* format we convert to `FWORD` and replace negative values with */ /* (32bit) `FT_INT_MAX`. */ + ENSURE_READ_BYTES( 12 ); + apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); @@ -546,15 +808,47 @@ tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( do_read_var ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG ( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, + item_deltas ) ) + return 0; + + apaint->u.radial_gradient.c0.x += INT_TO_FIXED( item_deltas[0] ); + apaint->u.radial_gradient.c0.y += INT_TO_FIXED( item_deltas[1] ); + + // TODO: Anything to be done about UFWORD deltas here? + apaint->u.radial_gradient.r0 += INT_TO_FIXED( item_deltas[2] ); + + apaint->u.radial_gradient.c1.x += INT_TO_FIXED( item_deltas[3] ); + apaint->u.radial_gradient.c1.y += INT_TO_FIXED( item_deltas[4] ); + + apaint->u.radial_gradient.r1 += INT_TO_FIXED( item_deltas[5] ); + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_RADIAL_GRADIENT; + return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT ) + else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT || + ( do_read_var = + ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT ) ) ) { - if ( !read_color_line( child_table_p, - &apaint->u.sweep_gradient.colorline ) ) + if ( !read_color_line( colr, + child_table_p, + &apaint->u.sweep_gradient.colorline, + do_read_var) ) return 0; + ENSURE_READ_BYTES( 8 ); + apaint->u.sweep_gradient.center.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.sweep_gradient.center.y = @@ -565,11 +859,34 @@ apaint->u.sweep_gradient.end_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( do_read_var ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG ( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + // TODO: Handle overflow? + apaint->u.sweep_gradient.center.x += INT_TO_FIXED( item_deltas[0] ); + apaint->u.sweep_gradient.center.y += INT_TO_FIXED( item_deltas[1] ); + + apaint->u.sweep_gradient.start_angle += + F2DOT14_TO_FIXED( item_deltas[2] ); + apaint->u.sweep_gradient.end_angle += + F2DOT14_TO_FIXED( item_deltas[3] ); + } +#endif + apaint->format = FT_COLR_PAINTFORMAT_SWEEP_GRADIENT; + return 1; } if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH ) { + ENSURE_READ_BYTES( 2 ); apaint->u.glyph.paint.p = child_table_p; apaint->u.glyph.paint.insert_root_transform = 0; apaint->u.glyph.glyphID = FT_NEXT_USHORT( p ); @@ -577,7 +894,9 @@ return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM ) + else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM ) { apaint->u.transform.paint.p = child_table_p; apaint->u.transform.paint.insert_root_transform = 0; @@ -591,6 +910,7 @@ * The following matrix coefficients are encoded as * OpenType 16.16 fixed-point values. */ + ENSURE_READ_BYTES( 24 ); apaint->u.transform.affine.xx = FT_NEXT_LONG( p ); apaint->u.transform.affine.yx = FT_NEXT_LONG( p ); apaint->u.transform.affine.xy = FT_NEXT_LONG( p ); @@ -598,51 +918,101 @@ apaint->u.transform.affine.dx = FT_NEXT_LONG( p ); apaint->u.transform.affine.dy = FT_NEXT_LONG( p ); +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, + item_deltas ) ) + return 0; + + apaint->u.transform.affine.xx += (FT_Fixed)item_deltas[0]; + apaint->u.transform.affine.yx += (FT_Fixed)item_deltas[1]; + apaint->u.transform.affine.xy += (FT_Fixed)item_deltas[2]; + apaint->u.transform.affine.yy += (FT_Fixed)item_deltas[3]; + apaint->u.transform.affine.dx += (FT_Fixed)item_deltas[4]; + apaint->u.transform.affine.dy += (FT_Fixed)item_deltas[5]; + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_TRANSFORM; + return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE ) + else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE ) { apaint->u.translate.paint.p = child_table_p; apaint->u.translate.paint.insert_root_transform = 0; + ENSURE_READ_BYTES( 4 ); apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, + item_deltas ) ) + return 0; + + apaint->u.translate.dx += INT_TO_FIXED( item_deltas[0] ); + apaint->u.translate.dy += INT_TO_FIXED( item_deltas[1] ); + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_TRANSLATE; + return 1; } - else if ( apaint->format == - FT_COLR_PAINTFORMAT_SCALE || - (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || - (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM || - (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER ) + else if ( apaint->format >= FT_COLR_PAINTFORMAT_SCALE && + (FT_PaintFormat_Internal)apaint->format <= + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) { apaint->u.scale.paint.p = child_table_p; apaint->u.scale.paint.insert_root_transform = 0; /* All scale paints get at least one scale value. */ + ENSURE_READ_BYTES( 2 ); apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); /* Non-uniform ones read an extra y value. */ - if ( apaint->format == - FT_COLR_PAINTFORMAT_SCALE || + if ( apaint->format == FT_COLR_PAINTFORMAT_SCALE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER ) + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER ) + { + ENSURE_READ_BYTES( 2 ); apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + } else apaint->u.scale.scale_y = apaint->u.scale.scale_x; /* Scale paints that have a center read center coordinates, */ /* otherwise the center is (0,0). */ if ( (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER || (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER ) + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) { + ENSURE_READ_BYTES( 4 ); apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); } @@ -652,6 +1022,71 @@ apaint->u.scale.center_y = 0; } + /* Base values set, now handle variations. */ + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] ); + apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[2] ); + apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[3] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 3, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[1] ); + apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[2] ); + } + } +#endif + /* FT 'COLR' v1 API output format always returns fully defined */ /* structs; we thus set the format to the public API value. */ apaint->format = FT_COLR_PAINTFORMAT_SCALE; @@ -659,18 +1094,26 @@ return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE || + else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER || (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER ) + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) { apaint->u.rotate.paint.p = child_table_p; apaint->u.rotate.paint.insert_root_transform = 0; + ENSURE_READ_BYTES( 2 ); apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); if ( (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER ) + FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) { + ENSURE_READ_BYTES( 4 ); apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); } @@ -680,24 +1123,69 @@ apaint->u.rotate.center_y = 0; } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) + { + FT_UInt num_deltas = 0; + + + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) + num_deltas = 3; + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE ) + num_deltas = 1; + + if ( num_deltas > 0 ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, + num_deltas, item_deltas ) ) + return 0; + + apaint->u.rotate.angle += F2DOT14_TO_FIXED( item_deltas[0] ); + + if ( num_deltas == 3 ) + { + apaint->u.rotate.center_x += INT_TO_FIXED( item_deltas[1] ); + apaint->u.rotate.center_y += INT_TO_FIXED( item_deltas[2] ); + } + } + } +#endif + apaint->format = FT_COLR_PAINTFORMAT_ROTATE; + return 1; } - else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW || + else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER || (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER ) + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) { apaint->u.skew.paint.p = child_table_p; apaint->u.skew.paint.insert_root_transform = 0; + ENSURE_READ_BYTES( 4 ); apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); if ( (FT_PaintFormat_Internal)apaint->format == - FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER ) + FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) { + ENSURE_READ_BYTES( 4 ); apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); } @@ -707,6 +1195,42 @@ apaint->u.skew.center_y = 0; } + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, + item_deltas ) ) + return 0; + + apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] ); + apaint->u.skew.center_x += INT_TO_FIXED( item_deltas[2] ); + apaint->u.skew.center_y += INT_TO_FIXED( item_deltas[3] ); + } + } +#endif + apaint->format = FT_COLR_PAINTFORMAT_SKEW; return 1; @@ -720,6 +1244,7 @@ apaint->u.composite.source_paint.p = child_table_p; apaint->u.composite.source_paint.insert_root_transform = 0; + ENSURE_READ_BYTES( 1 ); composite_mode = FT_NEXT_BYTE( p ); if ( composite_mode >= FT_COLR_COMPOSITE_MAX ) return 0; @@ -871,7 +1396,7 @@ clip_list_format = FT_NEXT_BYTE ( p ); /* Format byte used here to be able to upgrade ClipList for >16bit */ - /* glyph ids; for now we can expect it to be 0. */ + /* glyph ids; for now we can expect it to be 1. */ if ( !( clip_list_format == 1 ) ) return 0; @@ -899,7 +1424,7 @@ format = FT_NEXT_BYTE( p1 ); - if ( format > 1 ) + if ( format > 2 ) return 0; /* Check whether we can extract four `FWORD`. */ @@ -913,11 +1438,40 @@ font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ), face->root.size->metrics.x_scale ); font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ), - face->root.size->metrics.x_scale ); + face->root.size->metrics.y_scale ); font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ), face->root.size->metrics.x_scale ); font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ), - face->root.size->metrics.x_scale ); + face->root.size->metrics.y_scale ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( format == 2 ) + { + FT_ULong var_index_base = 0; + /* varIndexBase offset for clipbox is 3 at most. */ + FT_ItemVarDelta item_deltas[4] = { 0, 0, 0, 0 }; + + + /* Check whether we can extract a 32-bit varIndexBase now. */ + if ( p1 > limit - 4 ) + return 0; + + var_index_base = FT_NEXT_ULONG( p1 ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + font_clip_box.xMin += + FT_MulFix( item_deltas[0], face->root.size->metrics.x_scale ); + font_clip_box.yMin += + FT_MulFix( item_deltas[1], face->root.size->metrics.y_scale ); + font_clip_box.xMax += + FT_MulFix( item_deltas[2], face->root.size->metrics.x_scale ); + font_clip_box.yMax += + FT_MulFix( item_deltas[3], face->root.size->metrics.y_scale ); + } +#endif /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */ /* them. If we we would only transform two corner points and */ @@ -986,13 +1540,6 @@ p = iterator->p; /* - * First ensure that p is within COLRv1. - */ - if ( p < colr->layers_v1 || - p >= ( (FT_Byte*)colr->table + colr->table_size ) ) - return 0; - - /* * Do a cursor sanity check of the iterator. Counting backwards from * where it stands, we need to end up at a position after the beginning * of the `LayerV1List` table and not after the end of the @@ -1008,6 +1555,14 @@ colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) ) return 0; + /* + * Before reading, ensure that `p` is within 'COLR' v1 and we can read a + * 4-byte ULONG. + */ + if ( p < colr->layers_v1 || + p > (FT_Byte*)colr->table + colr->table_size - 4 ) + return 0; + paint_offset = FT_NEXT_ULONG( p ); opaque_paint->insert_root_transform = @@ -1037,29 +1592,67 @@ Colr* colr = (Colr*)face->colr; FT_Byte* p; + FT_ULong var_index_base; + FT_Byte* last_entry_p = NULL; + FT_UInt entry_size = COLOR_STOP_SIZE; - if ( !colr || !colr->table ) + if ( !colr || !colr->table || !iterator ) return 0; if ( iterator->current_color_stop >= iterator->num_color_stops ) return 0; - if ( iterator->p + - ( ( iterator->num_color_stops - iterator->current_color_stop ) * - COLOR_STOP_SIZE ) > - ( (FT_Byte *)colr->table + colr->table_size ) ) + if ( iterator->read_variable ) + entry_size += VAR_IDX_BASE_SIZE; + + /* Calculate the start pointer for the last to-be-read (Var)ColorStop */ + /* and check whether we can read a full (Var)ColorStop at that */ + /* position by comparing it to the position that is the size of one */ + /* (Var)ColorStop before the end of the 'COLR' table. */ + last_entry_p = + iterator->p + ( iterator->num_color_stops - 1 - + iterator->current_color_stop ) * entry_size; + if ( iterator->p < colr->paints_start_v1 || + last_entry_p > (FT_Byte*)colr->table + + colr->table_size - entry_size ) return 0; /* Iterator points at first `ColorStop` of `ColorLine`. */ p = iterator->p; - color_stop->stop_offset = FT_NEXT_SHORT( p ); + color_stop->stop_offset = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); color_stop->color.palette_index = FT_NEXT_USHORT( p ); color_stop->color.alpha = FT_NEXT_SHORT( p ); + if ( iterator->read_variable ) + { + /* Pointer p needs to be advanced independently of whether we intend */ + /* to take variable deltas into account or not. Otherwise iteration */ + /* would fail due to wrong offsets. */ + var_index_base = FT_NEXT_ULONG( p ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Int item_deltas[2]; + + + if ( !get_deltas_for_var_index_base( face, colr, + var_index_base, + 2, + item_deltas ) ) + return 0; + + color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] ); + color_stop->color.alpha += (FT_F2Dot14)item_deltas[1]; + } +#else + FT_UNUSED( var_index_base ); +#endif + } + iterator->p = p; iterator->current_color_stop++; @@ -1139,7 +1732,7 @@ return 1; } - return read_paint( colr, opaque_paint.p, paint ); + return read_paint( face, colr, opaque_paint.p, paint ); } @@ -1321,7 +1914,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_colr_dummy; + typedef int tt_colr_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttcolr.h b/src/3rdparty/freetype/src/sfnt/ttcolr.h index 4200cb2976..20c85f0359 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcolr.h +++ b/src/3rdparty/freetype/src/sfnt/ttcolr.h @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (specification). * - * Copyright (C) 2018-2022 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/src/3rdparty/freetype/src/sfnt/ttcpal.c b/src/3rdparty/freetype/src/sfnt/ttcpal.c index 9ae535cbda..46ae08596f 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcpal.c +++ b/src/3rdparty/freetype/src/sfnt/ttcpal.c @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (body). * - * Copyright (C) 2018-2022 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. @@ -303,7 +303,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_cpal_dummy; + typedef int tt_cpal_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttcpal.h b/src/3rdparty/freetype/src/sfnt/ttcpal.h index 4717d224fc..8e9913f0cc 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcpal.h +++ b/src/3rdparty/freetype/src/sfnt/ttcpal.h @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (specification). * - * Copyright (C) 2018-2022 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/src/3rdparty/freetype/src/sfnt/ttkern.c b/src/3rdparty/freetype/src/sfnt/ttkern.c index ca1c509406..a47d08bd6d 100644 --- a/src/3rdparty/freetype/src/sfnt/ttkern.c +++ b/src/3rdparty/freetype/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/ttkern.h b/src/3rdparty/freetype/src/sfnt/ttkern.h index f063558313..960c7da494 100644 --- a/src/3rdparty/freetype/src/sfnt/ttkern.h +++ b/src/3rdparty/freetype/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/ttload.c b/src/3rdparty/freetype/src/sfnt/ttload.c index c83bd197fe..7b44e9cd2e 100644 --- a/src/3rdparty/freetype/src/sfnt/ttload.c +++ b/src/3rdparty/freetype/src/sfnt/ttload.c @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (body). * - * Copyright (C) 1996-2022 by + * 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, @@ -206,7 +206,7 @@ if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) { FT_TRACE2(( "check_table_dir:" - " can read only %d table%s in font (instead of %d)\n", + " can read only %hu table%s in font (instead of %hu)\n", nn, nn == 1 ? "" : "s", sfnt->num_tables )); sfnt->num_tables = nn; break; @@ -216,7 +216,7 @@ if ( table.Offset > stream->size ) { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); + FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn )); continue; } else if ( table.Length > stream->size - table.Offset ) @@ -231,7 +231,7 @@ valid_entries++; else { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); + FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn )); continue; } } @@ -380,7 +380,7 @@ /* load the table directory */ - FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables )); + FT_TRACE2(( "-- Number of tables: %10hu\n", sfnt.num_tables )); FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag )); if ( sfnt.format_tag != TTAG_OTTO ) @@ -504,6 +504,13 @@ FT_FRAME_EXIT(); + if ( !valid_entries ) + { + FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" )); + error = FT_THROW( Unknown_File_Format ); + goto Exit; + } + FT_TRACE2(( "table directory loaded\n" )); FT_TRACE2(( "\n" )); @@ -671,8 +678,8 @@ if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) goto Exit; - FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM )); - FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format )); + FT_TRACE3(( "Units per EM: %4hu\n", header->Units_Per_EM )); + FT_TRACE3(( "IndexToLoc: %4hd\n", header->Index_To_Loc_Format )); Exit: return error; @@ -802,7 +809,7 @@ } } - FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); + FT_TRACE3(( "numGlyphs: %hu\n", maxProfile->numGlyphs )); Exit: return error; @@ -1265,11 +1272,11 @@ } } - FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); - FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); - FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); - FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); - FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); + FT_TRACE3(( "sTypoAscender: %4hd\n", os2->sTypoAscender )); + FT_TRACE3(( "sTypoDescender: %4hd\n", os2->sTypoDescender )); + FT_TRACE3(( "usWinAscent: %4hu\n", os2->usWinAscent )); + FT_TRACE3(( "usWinDescent: %4hu\n", os2->usWinDescent )); + FT_TRACE3(( "fsSelection: 0x%2hx\n", os2->fsSelection )); Exit: return error; @@ -1468,7 +1475,7 @@ gasp_ranges[j].maxPPEM = FT_GET_USHORT(); gasp_ranges[j].gaspFlag = FT_GET_USHORT(); - FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n", + FT_TRACE3(( "gaspRange %hu: rangeMaxPPEM %5hu, rangeGaspBehavior 0x%hx\n", j, gasp_ranges[j].maxPPEM, gasp_ranges[j].gaspFlag )); diff --git a/src/3rdparty/freetype/src/sfnt/ttload.h b/src/3rdparty/freetype/src/sfnt/ttload.h index 5368971c31..1499dd5735 100644 --- a/src/3rdparty/freetype/src/sfnt/ttload.h +++ b/src/3rdparty/freetype/src/sfnt/ttload.h @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (specification). * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/ttmtx.c b/src/3rdparty/freetype/src/sfnt/ttmtx.c index 88377327c6..38ee9ae728 100644 --- a/src/3rdparty/freetype/src/sfnt/ttmtx.c +++ b/src/3rdparty/freetype/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (body). * - * Copyright (C) 2006-2022 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -239,7 +239,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Service_MetricsVariations var = - (FT_Service_MetricsVariations)face->var; + (FT_Service_MetricsVariations)face->tt_var; #endif @@ -306,7 +306,7 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( var ) + if ( var && face->blend ) { FT_Face f = FT_FACE( face ); FT_Int a = (FT_Int)*aadvance; diff --git a/src/3rdparty/freetype/src/sfnt/ttmtx.h b/src/3rdparty/freetype/src/sfnt/ttmtx.h index 1e45b949a5..56d2b62766 100644 --- a/src/3rdparty/freetype/src/sfnt/ttmtx.h +++ b/src/3rdparty/freetype/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (specification). * - * Copyright (C) 2006-2022 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/3rdparty/freetype/src/sfnt/ttpost.c b/src/3rdparty/freetype/src/sfnt/ttpost.c index 1a885a15c5..1dfad4298b 100644 --- a/src/3rdparty/freetype/src/sfnt/ttpost.c +++ b/src/3rdparty/freetype/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (body). * - * Copyright (C) 1996-2022 by + * 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, @@ -58,7 +58,7 @@ #define MAC_NAME( x ) (FT_String*)psnames->macintosh_name( (FT_UInt)(x) ) -#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ +#else /* !FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* Otherwise, we ignore the `psnames' module, and provide our own */ @@ -152,90 +152,70 @@ }; -#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ +#endif /* !FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ static FT_Error - load_format_20( TT_Face face, - FT_Stream stream, - FT_ULong post_len ) + load_format_20( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_UShort num_names; + FT_UShort n; + FT_UShort num_names = 0; FT_UShort* glyph_indices = NULL; - FT_Char** name_strings = NULL; - FT_Byte* strings = NULL; + FT_Byte** name_strings = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ - /* than the value in the maxp table (cf. cyberbit.ttf). */ - - /* There already exist fonts which have more than 32768 glyph names */ - /* in this table, so the test for this threshold has been dropped. */ - - if ( num_glyphs > face->max_profile.numGlyphs || - (FT_ULong)num_glyphs * 2UL > post_len - 2 ) + if ( (FT_ULong)num_glyphs * 2 > post_len ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - /* load the indices */ - { - FT_Int n; - - - if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || - FT_FRAME_ENTER( num_glyphs * 2L ) ) - goto Fail; - - for ( n = 0; n < num_glyphs; n++ ) - glyph_indices[n] = FT_GET_USHORT(); + /* load the indices and note their maximum */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs * 2 ) ) + goto Fail; - FT_FRAME_EXIT(); - } + q = (FT_Byte*)stream->cursor; - /* compute number of names stored in table */ + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_UShort idx = FT_NEXT_USHORT( q ); - num_names = 0; + if ( idx > num_names ) + num_names = idx; - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Int idx; + glyph_indices[n] = idx; + } + FT_FRAME_EXIT(); - idx = glyph_indices[n]; - if ( idx >= 258 ) - { - idx -= 257; - if ( idx > num_names ) - num_names = (FT_UShort)idx; - } - } - } + /* compute number of names stored in the table */ + num_names = num_names > 257 ? num_names - 257 : 0; /* now load the name strings */ if ( num_names ) { - FT_UShort n; FT_ULong p; + FT_Byte* strings; - post_len -= (FT_ULong)num_glyphs * 2UL + 2; + post_len -= (FT_ULong)num_glyphs * 2; + + if ( FT_QALLOC( name_strings, num_names * sizeof ( FT_Byte* ) + + post_len + 1 ) ) + goto Fail; - if ( FT_QALLOC( strings, post_len + 1 ) || - FT_STREAM_READ( strings, post_len ) || - FT_QNEW_ARRAY( name_strings, num_names ) ) + strings = (FT_Byte*)( name_strings + num_names ); + if ( FT_STREAM_READ( strings, post_len ) ) goto Fail; /* convert from Pascal- to C-strings and set pointers */ @@ -251,7 +231,7 @@ } strings[p] = 0; - name_strings[n] = (FT_Char*)strings + p + 1; + name_strings[n] = strings + p + 1; p += len + 1; } strings[post_len] = 0; @@ -259,40 +239,24 @@ /* deal with missing or insufficient string data */ if ( n < num_names ) { - if ( post_len == 0 ) - { - /* fake empty string */ - if ( FT_QREALLOC( strings, 1, 2 ) ) - goto Fail; - - post_len = 1; - strings[post_len] = 0; - } + FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n", + num_names - n )); - FT_ERROR(( "load_format_20:" - " all entries in post table are already parsed," - " using NULL names for gid %d - %d\n", - n, num_names - 1 )); for ( ; n < num_names; n++ ) - name_strings[n] = (FT_Char*)strings + post_len; + name_strings[n] = strings + post_len; } } /* all right, set table fields and exit successfully */ - { - TT_Post_20 table = &face->postscript_names.names.format_20; - + names->num_glyphs = num_glyphs; + names->num_names = num_names; + names->glyph_indices = glyph_indices; + names->glyph_names = name_strings; - table->num_glyphs = (FT_UShort)num_glyphs; - table->num_names = (FT_UShort)num_names; - table->glyph_indices = glyph_indices; - table->glyph_names = name_strings; - } return FT_Err_Ok; Fail: FT_FREE( name_strings ); - FT_FREE( strings ); FT_FREE( glyph_indices ); Exit: @@ -301,66 +265,55 @@ static FT_Error - load_format_25( TT_Face face, - FT_Stream stream, - FT_ULong post_len ) + load_format_25( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_Char* offset_table = NULL; - - FT_UNUSED( post_len ); + FT_UShort n; + FT_UShort* glyph_indices = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* check the number of glyphs */ - if ( num_glyphs > face->max_profile.numGlyphs || - num_glyphs > 258 || - num_glyphs < 1 ) + /* check the number of glyphs, including the theoretical limit */ + if ( num_glyphs > post_len || + num_glyphs > 258 + 128 ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - if ( FT_QNEW_ARRAY( offset_table, num_glyphs ) || - FT_STREAM_READ( offset_table, num_glyphs ) ) + /* load the indices and check their Mac range */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs ) ) goto Fail; - /* now check the offset table */ - { - FT_Int n; + q = (FT_Byte*)stream->cursor; + for ( n = 0; n < num_glyphs; n++ ) + { + FT_Int idx = n + FT_NEXT_CHAR( q ); - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Long idx = (FT_Long)n + offset_table[n]; + if ( idx < 0 || idx > 257 ) + idx = 0; - if ( idx < 0 || idx > num_glyphs ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - } + glyph_indices[n] = (FT_UShort)idx; } - /* OK, set table fields and exit successfully */ - { - TT_Post_25 table = &face->postscript_names.names.format_25; - + FT_FRAME_EXIT(); - table->num_glyphs = (FT_UShort)num_glyphs; - table->offsets = offset_table; - } + /* OK, set table fields and exit successfully */ + names->num_glyphs = num_glyphs; + names->glyph_indices = glyph_indices; return FT_Err_Ok; Fail: - FT_FREE( offset_table ); + FT_FREE( glyph_indices ); Exit: return error; @@ -370,37 +323,37 @@ static FT_Error load_post_names( TT_Face face ) { - FT_Stream stream; - FT_Error error; - FT_Fixed format; + FT_Error error = FT_Err_Ok; + FT_Stream stream = face->root.stream; + FT_Fixed format = face->postscript.FormatType; FT_ULong post_len; + FT_UShort num_glyphs; - /* get a stream for the face's resource */ - stream = face->root.stream; - /* seek to the beginning of the PS names table */ error = face->goto_table( face, TTAG_post, stream, &post_len ); if ( error ) goto Exit; - format = face->postscript.FormatType; - - /* go to beginning of subtable */ - if ( FT_STREAM_SKIP( 32 ) ) + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + if ( post_len < 34 || + FT_STREAM_SKIP( 32 ) || + FT_READ_USHORT( num_glyphs ) || + num_glyphs > face->max_profile.numGlyphs || + num_glyphs == 0 ) goto Exit; - /* now read postscript table */ - if ( format == 0x00020000L && post_len >= 34 ) - error = load_format_20( face, stream, post_len - 32 ); - else if ( format == 0x00025000L && post_len >= 34 ) - error = load_format_25( face, stream, post_len - 32 ); - else - error = FT_THROW( Invalid_File_Format ); - - face->postscript_names.loaded = 1; + /* now read postscript names data */ + if ( format == 0x00020000L ) + error = load_format_20( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); + else if ( format == 0x00025000L ) + error = load_format_25( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); Exit: + face->postscript_names.loaded = 1; /* even if failed */ return error; } @@ -410,39 +363,20 @@ { FT_Memory memory = face->root.memory; TT_Post_Names names = &face->postscript_names; - FT_Fixed format; - if ( names->loaded ) + if ( names->num_glyphs ) { - format = face->postscript.FormatType; - - if ( format == 0x00020000L ) - { - TT_Post_20 table = &names->names.format_20; - - - FT_FREE( table->glyph_indices ); - table->num_glyphs = 0; - - if ( table->num_names ) - { - table->glyph_names[0]--; - FT_FREE( table->glyph_names[0] ); - - FT_FREE( table->glyph_names ); - table->num_names = 0; - } - } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - + FT_FREE( names->glyph_indices ); + names->num_glyphs = 0; + } - FT_FREE( table->offsets ); - table->num_glyphs = 0; - } + if ( names->num_names ) + { + FT_FREE( names->glyph_names ); + names->num_names = 0; } + names->loaded = 0; } @@ -478,7 +412,6 @@ FT_String** PSname ) { FT_Error error; - TT_Post_Names names; FT_Fixed format; #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES @@ -498,8 +431,6 @@ return FT_THROW( Unimplemented_Feature ); #endif - names = &face->postscript_names; - /* `.notdef' by default */ *PSname = MAC_NAME( 0 ); @@ -510,9 +441,10 @@ if ( idx < 258 ) /* paranoid checking */ *PSname = MAC_NAME( idx ); } - else if ( format == 0x00020000L ) + else if ( format == 0x00020000L || + format == 0x00025000L ) { - TT_Post_20 table = &names->names.format_20; + TT_Post_Names names = &face->postscript_names; if ( !names->loaded ) @@ -522,43 +454,29 @@ goto End; } - if ( idx < (FT_UInt)table->num_glyphs ) + if ( idx < (FT_UInt)names->num_glyphs ) { - FT_UShort name_index = table->glyph_indices[idx]; + FT_UShort name_index = names->glyph_indices[idx]; if ( name_index < 258 ) *PSname = MAC_NAME( name_index ); - else - *PSname = (FT_String*)table->glyph_names[name_index - 258]; - } - } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - if ( !names->loaded ) - { - error = load_post_names( face ); - if ( error ) - goto End; + else /* only for version 2.0 */ + *PSname = (FT_String*)names->glyph_names[name_index - 258]; } - - if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ - *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] ); } /* nothing to do for format == 0x00030000L */ End: + /* post format errors ignored */ return FT_Err_Ok; } #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* ANSI C doesn't like empty source files */ - typedef int _tt_post_dummy; + typedef int tt_post_dummy_; #endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ diff --git a/src/3rdparty/freetype/src/sfnt/ttpost.h b/src/3rdparty/freetype/src/sfnt/ttpost.h index bf9342a9f5..528f1c5f2f 100644 --- a/src/3rdparty/freetype/src/sfnt/ttpost.h +++ b/src/3rdparty/freetype/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (specification). * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/ttsbit.c b/src/3rdparty/freetype/src/sfnt/ttsbit.c index bf73d04e54..03f90a628d 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsbit.c +++ b/src/3rdparty/freetype/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (body). * - * Copyright (C) 2005-2022 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Copyright 2013 by Google, Inc. @@ -385,11 +385,9 @@ /* set the scale values (in 16.16 units) so advances */ /* from the hmtx and vmtx table are scaled correctly */ - metrics->x_scale = FT_MulDiv( metrics->x_ppem, - 64 * 0x10000, + metrics->x_scale = FT_DivFix( metrics->x_ppem * 64, face->header.Units_Per_EM ); - metrics->y_scale = FT_MulDiv( metrics->y_ppem, - 64 * 0x10000, + metrics->y_scale = FT_DivFix( metrics->y_ppem * 64, face->header.Units_Per_EM ); return FT_Err_Ok; @@ -399,9 +397,9 @@ { FT_Stream stream = face->root.stream; FT_UInt offset; - FT_UShort upem, ppem, resolution; + FT_UShort ppem, resolution; TT_HoriHeader *hori; - FT_Pos ppem_; /* to reduce casts */ + FT_Fixed scale; FT_Error error; FT_Byte* p; @@ -424,32 +422,23 @@ FT_FRAME_EXIT(); - upem = face->header.Units_Per_EM; - hori = &face->horizontal; - metrics->x_ppem = ppem; metrics->y_ppem = ppem; - ppem_ = (FT_Pos)ppem; + scale = FT_DivFix( ppem * 64, face->header.Units_Per_EM ); + hori = &face->horizontal; - metrics->ascender = - FT_MulDiv( hori->Ascender, ppem_ * 64, upem ); - metrics->descender = - FT_MulDiv( hori->Descender, ppem_ * 64, upem ); - metrics->height = - FT_MulDiv( hori->Ascender - hori->Descender + hori->Line_Gap, - ppem_ * 64, upem ); - metrics->max_advance = - FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem ); + metrics->ascender = FT_MulFix( hori->Ascender, scale ); + metrics->descender = FT_MulFix( hori->Descender, scale ); + metrics->height = + FT_MulFix( hori->Ascender - hori->Descender + hori->Line_Gap, + scale ); + metrics->max_advance = FT_MulFix( hori->advance_Width_Max, scale ); /* set the scale values (in 16.16 units) so advances */ /* from the hmtx and vmtx table are scaled correctly */ - metrics->x_scale = FT_MulDiv( metrics->x_ppem, - 64 * 0x10000, - face->header.Units_Per_EM ); - metrics->y_scale = FT_MulDiv( metrics->y_ppem, - 64 * 0x10000, - face->header.Units_Per_EM ); + metrics->x_scale = scale; + metrics->y_scale = scale; return error; } @@ -1204,7 +1193,7 @@ goto Fail; p += 1; /* skip padding */ - /* fall-through */ + FALL_THROUGH; case 9: loader = tt_sbit_decoder_load_compound; @@ -1604,7 +1593,7 @@ return error; } - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) tt_face_load_sbit_image( TT_Face face, FT_ULong strike_index, FT_UInt glyph_index, @@ -1688,7 +1677,7 @@ #else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_sbit_dummy; + typedef int tt_sbit_dummy_; #endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttsbit.h b/src/3rdparty/freetype/src/sfnt/ttsbit.h index c967bffba3..07e2db461a 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsbit.h +++ b/src/3rdparty/freetype/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (specification). * - * Copyright (C) 1996-2022 by + * 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, diff --git a/src/3rdparty/freetype/src/sfnt/ttsvg.c b/src/3rdparty/freetype/src/sfnt/ttsvg.c index 69277da577..4461d483b0 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsvg.c +++ b/src/3rdparty/freetype/src/sfnt/ttsvg.c @@ -4,7 +4,7 @@ * * OpenType SVG Color (specification). * - * Copyright (C) 2022 by + * Copyright (C) 2022-2023 by * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. * * This file is part of the FreeType project, and may only be used, @@ -114,7 +114,7 @@ FT_TRACE3(( "version: %d\n", svg->version )); FT_TRACE3(( "number of entries: %d\n", svg->num_entries )); - if ( offsetToSVGDocumentList + + if ( offsetToSVGDocumentList + 2U + svg->num_entries * SVG_DOCUMENT_RECORD_SIZE > table_size ) goto InvalidTable; @@ -196,7 +196,7 @@ static FT_Error - find_doc( FT_Byte* stream, + find_doc( FT_Byte* document_records, FT_UShort num_entries, FT_UInt glyph_index, FT_ULong *doc_offset, @@ -207,7 +207,7 @@ FT_Error error; Svg_doc start_doc; - Svg_doc mid_doc; + Svg_doc mid_doc = { 0, 0, 0, 0 }; /* pacify compiler */ Svg_doc end_doc; FT_Bool found = FALSE; @@ -225,8 +225,8 @@ return error; } - start_doc = extract_svg_doc( stream + start_index * 12 ); - end_doc = extract_svg_doc( stream + end_index * 12 ); + start_doc = extract_svg_doc( document_records + start_index * 12 ); + end_doc = extract_svg_doc( document_records + end_index * 12 ); if ( ( compare_svg_doc( start_doc, glyph_index ) == -1 ) || ( compare_svg_doc( end_doc, glyph_index ) == 1 ) ) @@ -238,18 +238,18 @@ while ( start_index <= end_index ) { i = ( start_index + end_index ) / 2; - mid_doc = extract_svg_doc( stream + i * 12 ); + mid_doc = extract_svg_doc( document_records + i * 12 ); comp_res = compare_svg_doc( mid_doc, glyph_index ); if ( comp_res == 1 ) { start_index = i + 1; - start_doc = extract_svg_doc( stream + start_index * 4 ); + start_doc = extract_svg_doc( document_records + start_index * 4 ); } else if ( comp_res == -1 ) { end_index = i - 1; - end_doc = extract_svg_doc( stream + end_index * 4 ); + end_doc = extract_svg_doc( document_records + end_index * 4 ); } else { @@ -283,38 +283,48 @@ tt_face_load_svg_doc( FT_GlyphSlot glyph, FT_UInt glyph_index ) { - FT_Byte* doc_list; /* pointer to the SVG doc list */ - FT_UShort num_entries; /* total number of entries in doc list */ - FT_ULong doc_offset; - FT_ULong doc_length; - - FT_UShort start_glyph_id; - FT_UShort end_glyph_id; - FT_Error error = FT_Err_Ok; TT_Face face = (TT_Face)glyph->face; FT_Memory memory = face->root.memory; Svg* svg = (Svg*)face->svg; + FT_Byte* doc_list; + FT_ULong doc_limit; + + FT_Byte* doc; + FT_ULong doc_offset; + FT_ULong doc_length; + FT_UShort doc_start_glyph_id; + FT_UShort doc_end_glyph_id; + FT_SVG_Document svg_document = (FT_SVG_Document)glyph->other; FT_ASSERT( !( svg == NULL ) ); - doc_list = svg->svg_doc_list; - num_entries = FT_NEXT_USHORT( doc_list ); + doc_list = svg->svg_doc_list; - error = find_doc( doc_list, num_entries, glyph_index, - &doc_offset, &doc_length, - &start_glyph_id, &end_glyph_id ); + error = find_doc( doc_list + 2, svg->num_entries, glyph_index, + &doc_offset, &doc_length, + &doc_start_glyph_id, &doc_end_glyph_id ); if ( error != FT_Err_Ok ) goto Exit; - doc_list = svg->svg_doc_list; /* reset, so we can use it again */ - doc_list = (FT_Byte*)( doc_list + doc_offset ); + doc_limit = svg->table_size - + (FT_ULong)( doc_list - (FT_Byte*)svg->table ); + if ( doc_offset > doc_limit || + doc_length > doc_limit - doc_offset ) + { + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + doc = doc_list + doc_offset; - if ( ( doc_list[0] == 0x1F ) && ( doc_list[1] == 0x8B ) - && ( doc_list[2] == 0x08 ) ) + if ( doc_length > 6 && + doc[0] == 0x1F && + doc[1] == 0x8B && + doc[2] == 0x08 ) { #ifdef FT_CONFIG_OPTION_USE_ZLIB @@ -331,10 +341,10 @@ * little-endian format. */ FT_TRACE4(( "SVG document is GZIP compressed\n" )); - uncomp_size = (FT_ULong)doc_list[doc_length - 1] << 24 | - (FT_ULong)doc_list[doc_length - 2] << 16 | - (FT_ULong)doc_list[doc_length - 3] << 8 | - (FT_ULong)doc_list[doc_length - 4]; + uncomp_size = (FT_ULong)doc[doc_length - 1] << 24 | + (FT_ULong)doc[doc_length - 2] << 16 | + (FT_ULong)doc[doc_length - 3] << 8 | + (FT_ULong)doc[doc_length - 4]; if ( FT_QALLOC( uncomp_buffer, uncomp_size ) ) goto Exit; @@ -342,7 +352,7 @@ error = FT_Gzip_Uncompress( memory, uncomp_buffer, &uncomp_size, - doc_list, + doc, doc_length ); if ( error ) { @@ -353,7 +363,7 @@ glyph->internal->flags |= FT_GLYPH_OWN_GZIP_SVG; - doc_list = uncomp_buffer; + doc = uncomp_buffer; doc_length = uncomp_size; #else /* !FT_CONFIG_OPTION_USE_ZLIB */ @@ -364,14 +374,14 @@ #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ } - svg_document->svg_document = doc_list; + svg_document->svg_document = doc; svg_document->svg_document_length = doc_length; svg_document->metrics = glyph->face->size->metrics; svg_document->units_per_EM = glyph->face->units_per_EM; - svg_document->start_glyph_id = start_glyph_id; - svg_document->end_glyph_id = end_glyph_id; + svg_document->start_glyph_id = doc_start_glyph_id; + svg_document->end_glyph_id = doc_end_glyph_id; svg_document->transform.xx = 0x10000; svg_document->transform.xy = 0; @@ -381,10 +391,10 @@ svg_document->delta.x = 0; svg_document->delta.y = 0; - FT_TRACE5(( "start_glyph_id: %d\n", start_glyph_id )); - FT_TRACE5(( "end_glyph_id: %d\n", end_glyph_id )); + FT_TRACE5(( "start_glyph_id: %d\n", doc_start_glyph_id )); + FT_TRACE5(( "end_glyph_id: %d\n", doc_end_glyph_id )); FT_TRACE5(( "svg_document:\n" )); - FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc_list )); + FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc )); glyph->other = svg_document; @@ -395,7 +405,7 @@ #else /* !FT_CONFIG_OPTION_SVG */ /* ANSI C doesn't like empty source files */ - typedef int _tt_svg_dummy; + typedef int tt_svg_dummy_; #endif /* !FT_CONFIG_OPTION_SVG */ diff --git a/src/3rdparty/freetype/src/sfnt/ttsvg.h b/src/3rdparty/freetype/src/sfnt/ttsvg.h index 7c234fd524..3f32321ded 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsvg.h +++ b/src/3rdparty/freetype/src/sfnt/ttsvg.h @@ -4,7 +4,7 @@ * * OpenType SVG Color (specification). * - * Copyright (C) 2022 by + * Copyright (C) 2022-2023 by * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. * * This file is part of the FreeType project, and may only be used, diff --git a/src/3rdparty/freetype/src/sfnt/woff2tags.c b/src/3rdparty/freetype/src/sfnt/woff2tags.c index 7d79fef39a..eeedd9906b 100644 --- a/src/3rdparty/freetype/src/sfnt/woff2tags.c +++ b/src/3rdparty/freetype/src/sfnt/woff2tags.c @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (base). * - * Copyright (C) 2019-2022 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -111,7 +111,7 @@ #else /* !FT_CONFIG_OPTION_USE_BROTLI */ /* ANSI C doesn't like empty source files */ - typedef int _woff2tags_dummy; + typedef int woff2tags_dummy_; #endif /* !FT_CONFIG_OPTION_USE_BROTLI */ diff --git a/src/3rdparty/freetype/src/sfnt/woff2tags.h b/src/3rdparty/freetype/src/sfnt/woff2tags.h index 05df85aba0..1201848e5e 100644 --- a/src/3rdparty/freetype/src/sfnt/woff2tags.h +++ b/src/3rdparty/freetype/src/sfnt/woff2tags.h @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (specification). * - * Copyright (C) 2019-2022 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, |