From 674d629b5e9e59a376922113a3b5de019e2c9fe2 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 14 Apr 2024 13:06:01 -0400 Subject: [PATCH 01/60] [smooth] Store persistent clipping box. * src/smooth/ftgrays.c (gray_TWorker, gray_raster_render): Add and set the new structure field. (gray_convert_glyph): Use it. --- src/smooth/ftgrays.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 576e837dc..0ca5e30b3 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -489,7 +489,7 @@ typedef ptrdiff_t FT_PtrDist; typedef struct gray_TWorker_ { - ft_jmp_buf jump_buffer; + FT_BBox cbox; TCoord min_ex, max_ex; /* min and max integer pixel coordinates */ TCoord min_ey, max_ey; @@ -510,6 +510,8 @@ typedef ptrdiff_t FT_PtrDist; FT_Raster_Span_Func render_span; void* render_span_data; + ft_jmp_buf jump_buffer; + } gray_TWorker, *gray_PWorker; #if defined( _MSC_VER ) @@ -1863,11 +1865,8 @@ typedef ptrdiff_t FT_PtrDist; static int gray_convert_glyph( RAS_ARG ) { - const TCoord yMin = ras.min_ey; - const TCoord yMax = ras.max_ey; - TCell buffer[FT_MAX_GRAY_POOL]; - size_t height = (size_t)( yMax - yMin ); + size_t height = (size_t)( ras.cbox.yMax - ras.cbox.yMin ); size_t n = FT_MAX_GRAY_POOL / 8; TCoord y; TCoord bands[32]; /* enough to accommodate bisections */ @@ -1893,11 +1892,14 @@ typedef ptrdiff_t FT_PtrDist; height = ( height + n - 1 ) / n; } - for ( y = yMin; y < yMax; ) + ras.min_ex = ras.cbox.xMin; + ras.max_ex = ras.cbox.xMax; + + for ( y = ras.cbox.yMin; y < ras.cbox.yMax; ) { ras.min_ey = y; y += height; - ras.max_ey = FT_MIN( y, yMax ); + ras.max_ey = FT_MIN( y, ras.cbox.yMax ); band = bands; band[1] = ras.min_ey; @@ -2001,10 +2003,7 @@ typedef ptrdiff_t FT_PtrDist; ras.render_span = (FT_Raster_Span_Func)params->gray_spans; ras.render_span_data = params->user; - ras.min_ex = params->clip_box.xMin; - ras.min_ey = params->clip_box.yMin; - ras.max_ex = params->clip_box.xMax; - ras.max_ey = params->clip_box.yMax; + ras.cbox = params->clip_box; } else { @@ -2030,14 +2029,14 @@ typedef ptrdiff_t FT_PtrDist; ras.render_span = (FT_Raster_Span_Func)NULL; ras.render_span_data = NULL; - ras.min_ex = 0; - ras.min_ey = 0; - ras.max_ex = (FT_Pos)target_map->width; - ras.max_ey = (FT_Pos)target_map->rows; + ras.cbox.xMin = 0; + ras.cbox.yMin = 0; + ras.cbox.xMax = (FT_Pos)target_map->width; + ras.cbox.yMax = (FT_Pos)target_map->rows; } /* exit if nothing to do */ - if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey ) + if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax ) return Smooth_Err_Ok; return gray_convert_glyph( RAS_VAR ); From fff58f5424e4214c5ce3b35f8735d670ec40496f Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 14 Apr 2024 15:12:31 -0400 Subject: [PATCH 02/60] * src/smooth/ftgrays.c (gray_convert_glyph): Refactor for convenience. --- src/smooth/ftgrays.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 0ca5e30b3..3345e7991 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -1907,23 +1907,24 @@ typedef ptrdiff_t FT_PtrDist; do { - TCoord width = band[0] - band[1]; - TCoord w; + TCoord i; int error; - for ( w = 0; w < width; ++w ) - ras.ycells[w] = ras.cell_null; + ras.min_ey = band[1]; + ras.max_ey = band[0]; - /* memory management: skip ycells */ - n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / - sizeof ( TCell ); + ras.count_ey = ras.max_ey - ras.min_ey; + + /* memory management: zero out and skip ycells */ + for ( i = 0; i < ras.count_ey; ++i ) + ras.ycells[i] = ras.cell_null; + + n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) + / sizeof ( TCell ); ras.cell_free = buffer + n; ras.cell = ras.cell_null; - ras.min_ey = band[1]; - ras.max_ey = band[0]; - ras.count_ey = width; error = gray_convert_glyph_inner( RAS_VAR_ continued ); continued = 1; @@ -1941,10 +1942,10 @@ typedef ptrdiff_t FT_PtrDist; return error; /* render pool overflow; we will reduce the render band by half */ - width >>= 1; + i = ( band[0] - band[1] ) >> 1; /* this should never happen even with tiny rendering pool */ - if ( width == 0 ) + if ( i == 0 ) { FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); return FT_THROW( Raster_Overflow ); @@ -1952,7 +1953,7 @@ typedef ptrdiff_t FT_PtrDist; band++; band[1] = band[0]; - band[0] += width; + band[0] += i; } while ( band >= bands ); } From b3a6a20a805366e0bc7044d1402d04c53f9c1660 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 14 Apr 2024 15:37:57 -0400 Subject: [PATCH 03/60] [smooth] Switch to vertical bisections. With horizontal bisections, the smallest section is a whole single scanline. Almost horizontal lines or other complex scanlines can easily overflow the rendering pool. Switching to vertical bisections splits the scanlines and should rule out the overflows. Fixes #1269. * src/smooth/ftgrays.c (gray_convert_glyph): Bisect vertically. --- src/smooth/ftgrays.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 3345e7991..f011e9f8d 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -1892,18 +1892,17 @@ typedef ptrdiff_t FT_PtrDist; height = ( height + n - 1 ) / n; } - ras.min_ex = ras.cbox.xMin; - ras.max_ex = ras.cbox.xMax; - for ( y = ras.cbox.yMin; y < ras.cbox.yMax; ) { ras.min_ey = y; y += height; ras.max_ey = FT_MIN( y, ras.cbox.yMax ); + ras.count_ey = ras.max_ey - ras.min_ey; + band = bands; - band[1] = ras.min_ey; - band[0] = ras.max_ey; + band[1] = ras.cbox.xMin; + band[0] = ras.cbox.xMax; do { @@ -1911,10 +1910,8 @@ typedef ptrdiff_t FT_PtrDist; int error; - ras.min_ey = band[1]; - ras.max_ey = band[0]; - - ras.count_ey = ras.max_ey - ras.min_ey; + ras.min_ex = band[1]; + ras.max_ex = band[0]; /* memory management: zero out and skip ycells */ for ( i = 0; i < ras.count_ey; ++i ) From d091bca546fa15928db36c8447e126ee43ddb5f4 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 17 Apr 2024 00:33:14 -0400 Subject: [PATCH 04/60] [cache] Fix error handling. Manipulate the cache after a face is requested or a size is looked up successfully. Fixes #1270. * src/cache/ftcmanag.c (ftc_size_node_init, ftc_size_node_reset, ftc_face_node_init): Check for errors before accepting a change. * src/cache/ftcmru.c (FTC_MruList_New): Do nothing if reset fails. --- src/cache/ftcmanag.c | 38 +++++++++++++++++++++++++++----------- src/cache/ftcmru.c | 8 +++++--- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index dd9bb6190..6b8b80e33 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -118,14 +118,21 @@ FT_Pointer ftcscaler, FT_Pointer ftcmanager ) { + FT_Error error; + FT_Size size; FTC_SizeNode node = (FTC_SizeNode)ftcnode; FTC_Scaler scaler = (FTC_Scaler)ftcscaler; FTC_Manager manager = (FTC_Manager)ftcmanager; - node->scaler = scaler[0]; + error = ftc_scaler_lookup_size( manager, scaler, &size ); + if ( !error ) + { + node->size = size; + node->scaler = scaler[0]; + } - return ftc_scaler_lookup_size( manager, scaler, &node->size ); + return error; } @@ -134,16 +141,23 @@ FT_Pointer ftcscaler, FT_Pointer ftcmanager ) { + FT_Error error; + FT_Size size; FTC_SizeNode node = (FTC_SizeNode)ftcnode; FTC_Scaler scaler = (FTC_Scaler)ftcscaler; FTC_Manager manager = (FTC_Manager)ftcmanager; - FT_Done_Size( node->size ); + error = ftc_scaler_lookup_size( manager, scaler, &size ); + if ( !error ) + { + FT_Done_Size( node->size ); - node->scaler = scaler[0]; + node->size = size; + node->scaler = scaler[0]; + } - return ftc_scaler_lookup_size( manager, scaler, &node->size ); + return error; } @@ -231,23 +245,25 @@ FT_Pointer ftcface_id, FT_Pointer ftcmanager ) { + FT_Error error; + FT_Face face; FTC_FaceNode node = (FTC_FaceNode)ftcnode; FTC_FaceID face_id = (FTC_FaceID)ftcface_id; FTC_Manager manager = (FTC_Manager)ftcmanager; - FT_Error error; - node->face_id = face_id; - error = manager->request_face( face_id, manager->library, manager->request_data, - &node->face ); + &face ); if ( !error ) { /* destroy initial size object; it will be re-created later */ - if ( node->face->size ) - FT_Done_Size( node->face->size ); + if ( face->size ) + FT_Done_Size( face->size ); + + node->face = face; + node->face_id = face_id; } return error; diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c index 7171d4d20..dd23d31a3 100644 --- a/src/cache/ftcmru.c +++ b/src/cache/ftcmru.c @@ -249,11 +249,13 @@ if ( list->clazz.node_reset ) { - FTC_MruNode_Up( &list->nodes, node ); - error = list->clazz.node_reset( node, key, list->data ); if ( !error ) - goto Exit; + FTC_MruNode_Up( &list->nodes, node ); + else + node = NULL; + + goto Exit; } FTC_MruNode_Remove( &list->nodes, node ); From 12adfc212bd2f7560e1e175e66458124f9bd554b Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 17 Apr 2024 15:07:23 +0000 Subject: [PATCH 05/60] [cache] Improve MRU list management. * src/cache/ftcmru.c (FTC_MruList_Remove): Cosmetic. (FTC_MruList_New): Accept only valid changes. * src/cache/ftcmanag.c (ftc_size_node_done): Simplify. --- src/cache/ftcmanag.c | 4 +-- src/cache/ftcmru.c | 64 ++++++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index 6b8b80e33..881b460a8 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -86,12 +86,10 @@ FT_Pointer data ) { FTC_SizeNode node = (FTC_SizeNode)ftcnode; - FT_Size size = node->size; FT_UNUSED( data ); - if ( size ) - FT_Done_Size( size ); + FT_Done_Size( node->size ); } diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c index dd23d31a3..a767fa408 100644 --- a/src/cache/ftcmru.c +++ b/src/cache/ftcmru.c @@ -238,54 +238,62 @@ { FT_Error error; FTC_MruNode node = NULL; + FTC_MruNode prev = NULL; FT_Memory memory = list->memory; - if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 ) + if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes ) { - node = list->nodes->prev; + prev = list->nodes->prev; - FT_ASSERT( node ); + FT_ASSERT( prev ); + /* try fast reset when available */ if ( list->clazz.node_reset ) { - error = list->clazz.node_reset( node, key, list->data ); + error = list->clazz.node_reset( prev, key, list->data ); if ( !error ) + { + node = prev; + FTC_MruNode_Up( &list->nodes, node ); - else - node = NULL; + } goto Exit; } - - FTC_MruNode_Remove( &list->nodes, node ); - list->num_nodes--; - - if ( list->clazz.node_done ) - list->clazz.node_done( node, list->data ); } /* zero new node in case of node_init failure */ - else if ( FT_ALLOC( node, list->clazz.node_size ) ) + if ( FT_ALLOC( node, list->clazz.node_size ) ) goto Exit; error = list->clazz.node_init( node, key, list->data ); if ( error ) - goto Fail; + { + prev = node; + node = NULL; + + goto Clean; + } FTC_MruNode_Prepend( &list->nodes, node ); list->num_nodes++; + if ( !prev ) + goto Exit; + + FTC_MruNode_Remove( &list->nodes, prev ); + list->num_nodes--; + + Clean: + if ( list->clazz.node_done ) + list->clazz.node_done( prev, list->data ); + + FT_FREE( prev ); + Exit: *anode = node; return error; - - Fail: - if ( list->clazz.node_done ) - list->clazz.node_done( node, list->data ); - - FT_FREE( node ); - goto Exit; } @@ -311,18 +319,16 @@ FTC_MruList_Remove( FTC_MruList list, FTC_MruNode node ) { + FT_Memory memory = list->memory; + + FTC_MruNode_Remove( &list->nodes, node ); list->num_nodes--; - { - FT_Memory memory = list->memory; + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); - - if ( list->clazz.node_done ) - list->clazz.node_done( node, list->data ); - - FT_FREE( node ); - } + FT_FREE( node ); } From db83e9c0ec8b4ec8d7fa3bb3383d5160d1cfa719 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Thu, 18 Apr 2024 23:23:13 -0400 Subject: [PATCH 06/60] * src/cache/ftcglyph.c [!FTC_INLINE]: Fix compilation. --- src/cache/ftcglyph.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cache/ftcglyph.c b/src/cache/ftcglyph.c index cf7820abd..5e7856378 100644 --- a/src/cache/ftcglyph.c +++ b/src/cache/ftcglyph.c @@ -180,7 +180,7 @@ query->gindex = gindex; - FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error ); + FTC_MRULIST_LOOKUP( &gcache->families, query, query->family, error ); if ( !error ) { FTC_Family family = query->family; @@ -193,7 +193,7 @@ error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode ); if ( --family->num_nodes == 0 ) - FTC_FAMILY_FREE( family, cache ); + FTC_FAMILY_FREE( family, FTC_CACHE( gcache ) ); } return error; } From dbdcd758895647028bbc56baf862a1cff07409ff Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 19 Apr 2024 14:02:43 -0400 Subject: [PATCH 07/60] [cache] Tweak headers. * src/cache/ftccback.h: Include less and move `ftc_node_destroy`... * src/cache/ftccache.h: ... to here. * src/cache/ftcmanag.c: Include less. --- src/cache/ftccache.h | 4 ++++ src/cache/ftccback.h | 10 +--------- src/cache/ftcmanag.c | 1 - 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h index ccbf97980..85d321c12 100644 --- a/src/cache/ftccache.h +++ b/src/cache/ftccache.h @@ -87,6 +87,10 @@ FT_BEGIN_HEADER ftc_get_top_node_for_hash( ( cache ), ( hash ) ) #endif + FT_LOCAL( void ) + ftc_node_destroy( FTC_Node node, + FTC_Manager manager ); + /*************************************************************************/ /*************************************************************************/ diff --git a/src/cache/ftccback.h b/src/cache/ftccback.h index 79ba44ab9..a1d76baa7 100644 --- a/src/cache/ftccback.h +++ b/src/cache/ftccback.h @@ -19,11 +19,7 @@ #define FTCCBACK_H_ #include -#include "ftcmru.h" -#include "ftcimage.h" -#include "ftcmanag.h" -#include "ftcglyph.h" -#include "ftcsbits.h" +#include "ftccache.h" FT_BEGIN_HEADER @@ -81,10 +77,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) ftc_cache_done( FTC_Cache cache ); - FT_LOCAL( void ) - ftc_node_destroy( FTC_Node node, - FTC_Manager manager ); - FT_END_HEADER #endif /* FTCCBACK_H_ */ diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index 881b460a8..c73601400 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -22,7 +22,6 @@ #include #include -#include "ftccback.h" #include "ftcerror.h" From 9a2d6d97b2d8a5d22d02948b783df12b764afa2d Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 19 Apr 2024 14:45:39 -0400 Subject: [PATCH 08/60] * src/cache/{ftcbasic.c,ftccmap.c}: Use FTC_INLINE. --- src/cache/ftcbasic.c | 4 ++-- src/cache/ftccmap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c index b6e13fd7b..742d93515 100644 --- a/src/cache/ftcbasic.c +++ b/src/cache/ftcbasic.c @@ -334,7 +334,7 @@ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; -#if 1 /* inlining is about 50% faster! */ +#ifdef FTC_INLINE /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, ftc_gnode_compare, @@ -534,7 +534,7 @@ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex / FTC_SBIT_ITEMS_PER_NODE; -#if 1 /* inlining is about 50% faster! */ +#ifdef FTC_INLINE /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, ftc_snode_compare, diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c index 43c507361..b5c61e816 100644 --- a/src/cache/ftccmap.c +++ b/src/cache/ftccmap.c @@ -264,7 +264,7 @@ hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code ); -#if 1 +#ifdef FTC_INLINE FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query, node, error ); #else From 23e1d6455662a7e9eaf021331e502e7f48003a98 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 20 Apr 2024 12:01:58 -0400 Subject: [PATCH 09/60] [cache] Reduce type mismatches. * src/cache/ftcbasic.c (FTC_BasicAttrRec): Match type of `load_flags` to its main purpose in `FT_Load_Glyph`. (FTC_ImageCache_Lookup{,Scaler},FTC_SBitCache_Lookup{,Scaler}): Updated. --- src/cache/ftcbasic.c | 63 ++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 46 deletions(-) diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c index 742d93515..10c7b6c41 100644 --- a/src/cache/ftcbasic.c +++ b/src/cache/ftcbasic.c @@ -37,7 +37,7 @@ typedef struct FTC_BasicAttrRec_ { FTC_ScalerRec scaler; - FT_UInt load_flags; + FT_Int32 load_flags; } FTC_BasicAttrRec, *FTC_BasicAttrs; @@ -143,10 +143,9 @@ FT_Face face = size->face; - error = FT_Load_Glyph( - face, - gindex, - (FT_Int)family->attrs.load_flags | FT_LOAD_RENDER ); + error = FT_Load_Glyph( face, + gindex, + family->attrs.load_flags | FT_LOAD_RENDER ); if ( !error ) *aface = face; } @@ -176,9 +175,7 @@ { face = size->face; - error = FT_Load_Glyph( face, - gindex, - (FT_Int)family->attrs.load_flags ); + error = FT_Load_Glyph( face, gindex, family->attrs.load_flags ); if ( !error ) { if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || @@ -310,23 +307,10 @@ if ( anode ) *anode = NULL; - /* - * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', - * but public `FT_ImageType->flags' is of type `FT_Int32'. - * - * On 16bit systems, higher bits of type->flags cannot be handled. - */ -#if 0xFFFFFFFFUL > FT_UINT_MAX - if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) - FT_TRACE1(( "FTC_ImageCache_Lookup:" - " higher bits in load_flags 0x%lx are dropped\n", - (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); -#endif - query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; query.attrs.scaler.height = type->height; - query.attrs.load_flags = (FT_UInt)type->flags; + query.attrs.load_flags = type->flags; query.attrs.scaler.pixel = 1; query.attrs.scaler.x_res = 0; /* make compilers happy */ @@ -392,20 +376,20 @@ *anode = NULL; /* - * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', + * Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32', * but public `FT_Face->face_flags' is of type `FT_Long'. * * On long > int systems, higher bits of load_flags cannot be handled. */ -#if FT_ULONG_MAX > FT_UINT_MAX - if ( load_flags > FT_UINT_MAX ) +#if FT_ULONG_MAX > 0xFFFFFFFFUL + if ( load_flags > 0xFFFFFFFFUL ) FT_TRACE1(( "FTC_ImageCache_LookupScaler:" " higher bits in load_flags 0x%lx are dropped\n", - load_flags & ~((FT_ULong)FT_UINT_MAX) )); + load_flags & ~0xFFFFFFFFUL )); #endif query.attrs.scaler = scaler[0]; - query.attrs.load_flags = (FT_UInt)load_flags; + query.attrs.load_flags = (FT_Int32)load_flags; hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; @@ -508,23 +492,10 @@ *ansbit = NULL; - /* - * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', - * but public `FT_ImageType->flags' is of type `FT_Int32'. - * - * On 16bit systems, higher bits of type->flags cannot be handled. - */ -#if 0xFFFFFFFFUL > FT_UINT_MAX - if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) - FT_TRACE1(( "FTC_ImageCache_Lookup:" - " higher bits in load_flags 0x%lx are dropped\n", - (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); -#endif - query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; query.attrs.scaler.height = type->height; - query.attrs.load_flags = (FT_UInt)type->flags; + query.attrs.load_flags = type->flags; query.attrs.scaler.pixel = 1; query.attrs.scaler.x_res = 0; /* make compilers happy */ @@ -592,20 +563,20 @@ *ansbit = NULL; /* - * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', + * Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32', * but public `FT_Face->face_flags' is of type `FT_Long'. * * On long > int systems, higher bits of load_flags cannot be handled. */ -#if FT_ULONG_MAX > FT_UINT_MAX - if ( load_flags > FT_UINT_MAX ) +#if FT_ULONG_MAX > 0xFFFFFFFFUL + if ( load_flags > 0xFFFFFFFFUL ) FT_TRACE1(( "FTC_ImageCache_LookupScaler:" " higher bits in load_flags 0x%lx are dropped\n", - load_flags & ~((FT_ULong)FT_UINT_MAX) )); + load_flags & ~0xFFFFFFFFUL )); #endif query.attrs.scaler = scaler[0]; - query.attrs.load_flags = (FT_UInt)load_flags; + query.attrs.load_flags = (FT_Int32)load_flags; /* beware, the hash must be the same for all glyph ranges! */ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + From 5a3bfa92d9d23efaf20319cd1dd13857108b55d8 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 20 Apr 2024 23:28:17 -0400 Subject: [PATCH 10/60] * src/cache/ftcbasic.c: Cosmetic harmonization. --- src/cache/ftcbasic.c | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c index 10c7b6c41..953b96ebe 100644 --- a/src/cache/ftcbasic.c +++ b/src/cache/ftcbasic.c @@ -290,22 +290,19 @@ FT_Glyph *aglyph, FTC_Node *anode ) { - FTC_BasicQueryRec query; - FTC_Node node = 0; /* make compiler happy */ FT_Error error; + FTC_BasicQueryRec query; + FTC_Node node = NULL; /* make compiler happy */ FT_Offset hash; - /* some argument checks are delayed to `FTC_Cache_Lookup' */ + /* other argument checks delayed to `FTC_Cache_Lookup' */ if ( !aglyph ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } + return FT_THROW( Invalid_Argument ); *aglyph = NULL; if ( anode ) - *anode = NULL; + *anode = NULL; query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; @@ -343,7 +340,6 @@ } } - Exit: return error; } @@ -358,22 +354,19 @@ FT_Glyph *aglyph, FTC_Node *anode ) { - FTC_BasicQueryRec query; - FTC_Node node = 0; /* make compiler happy */ FT_Error error; + FTC_BasicQueryRec query; + FTC_Node node = NULL; /* make compiler happy */ FT_Offset hash; - /* some argument checks are delayed to `FTC_Cache_Lookup' */ + /* other argument checks delayed to `FTC_Cache_Lookup' */ if ( !aglyph || !scaler ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } + return FT_THROW( Invalid_Argument ); *aglyph = NULL; if ( anode ) - *anode = NULL; + *anode = NULL; /* * Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32', @@ -411,7 +404,6 @@ } } - Exit: return error; } @@ -479,18 +471,17 @@ { FT_Error error; FTC_BasicQueryRec query; - FTC_Node node = 0; /* make compiler happy */ + FTC_Node node = NULL; /* make compiler happy */ FT_Offset hash; - if ( anode ) - *anode = NULL; - /* other argument checks delayed to `FTC_Cache_Lookup' */ if ( !ansbit ) return FT_THROW( Invalid_Argument ); *ansbit = NULL; + if ( anode ) + *anode = NULL; query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; @@ -549,18 +540,17 @@ { FT_Error error; FTC_BasicQueryRec query; - FTC_Node node = 0; /* make compiler happy */ + FTC_Node node = NULL; /* make compiler happy */ FT_Offset hash; - if ( anode ) - *anode = NULL; - /* other argument checks delayed to `FTC_Cache_Lookup' */ if ( !ansbit || !scaler ) - return FT_THROW( Invalid_Argument ); + return FT_THROW( Invalid_Argument ); *ansbit = NULL; + if ( anode ) + *anode = NULL; /* * Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32', From 982bc83849966554f850fbc91405883a2a0de895 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 21 Apr 2024 15:53:05 -0400 Subject: [PATCH 11/60] [cache] Minor tweaks. * src/cache/ftcimage.c (ftc_inode_free): Remove unnecessary check. * src/cache/ftcmanag.c (FTC_Manager_Done): Do not zero before freeing. --- src/cache/ftcimage.c | 6 +----- src/cache/ftcmanag.c | 5 ----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/cache/ftcimage.c b/src/cache/ftcimage.c index 56ff80915..c142dcc8d 100644 --- a/src/cache/ftcimage.c +++ b/src/cache/ftcimage.c @@ -34,11 +34,7 @@ FT_Memory memory = cache->memory; - if ( inode->glyph ) - { - FT_Done_Glyph( inode->glyph ); - inode->glyph = NULL; - } + FT_Done_Glyph( inode->glyph ); FTC_GNode_Done( FTC_GNODE( inode ), cache ); FT_FREE( inode ); diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index c73601400..29a95baa1 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -448,18 +448,13 @@ { cache->clazz.cache_done( cache ); FT_FREE( cache ); - manager->caches[idx] = NULL; } } - manager->num_caches = 0; /* discard faces and sizes */ FTC_MruList_Done( &manager->sizes ); FTC_MruList_Done( &manager->faces ); - manager->library = NULL; - manager->memory = NULL; - FT_FREE( manager ); } From ec46a50dac57845b1ab505275f26025706b9405d Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 22 Apr 2024 21:21:12 -0400 Subject: [PATCH 12/60] Improve SDF documentation. --- include/freetype/freetype.h | 81 +++---------------------------------- include/freetype/ftdriver.h | 73 +++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 75 deletions(-) diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index e3a0435ba..b88ccc608 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -3771,87 +3771,18 @@ FT_BEGIN_HEADER * pixels and use the @FT_PIXEL_MODE_LCD_V mode. * * FT_RENDER_MODE_SDF :: - * This mode corresponds to 8-bit, single-channel signed distance field - * (SDF) bitmaps. Each pixel in the SDF grid is the value from the - * pixel's position to the nearest glyph's outline. The distances are - * calculated from the center of the pixel and are positive if they are - * filled by the outline (i.e., inside the outline) and negative - * otherwise. Check the note below on how to convert the output values - * to usable data. + * The positive (unsigned) 8-bit bitmap values can be converted to the + * single-channel signed distance field (SDF) by subtracting 128, with + * the positive and negative results corresponding to the inside and + * the outside of a glyph contour, respectively. The distance units are + * arbitrarily determined by an adjustable @spread property. * * @note: - * The selected render mode only affects vector glyphs of a font. + * The selected render mode only affects scalable vector glyphs of a font. * Embedded bitmaps often have a different pixel mode like * @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform them * into 8-bit pixmaps. * - * For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized - * distances that are packed into unsigned 8-bit values. To get pixel - * values in floating point representation use the following pseudo-C - * code for the conversion. - * - * ``` - * // Load glyph and render using FT_RENDER_MODE_SDF, - * // then use the output buffer as follows. - * - * ... - * FT_Byte buffer = glyph->bitmap->buffer; - * - * - * for pixel in buffer - * { - * // `sd` is the signed distance and `spread` is the current spread; - * // the default spread is 2 and can be changed. - * - * float sd = (float)pixel - 128.0f; - * - * - * // Convert to pixel values. - * sd = ( sd / 128.0f ) * spread; - * - * // Store `sd` in a buffer or use as required. - * } - * - * ``` - * - * FreeType has two rasterizers for generating SDF, namely: - * - * 1. `sdf` for generating SDF directly from glyph's outline, and - * - * 2. `bsdf` for generating SDF from rasterized bitmaps. - * - * Depending on the glyph type (i.e., outline or bitmap), one of the two - * rasterizers is chosen at runtime and used for generating SDFs. To - * force the use of `bsdf` you should render the glyph with any of the - * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and - * then re-render with `FT_RENDER_MODE_SDF`. - * - * There are some issues with stability and possible failures of the SDF - * renderers (specifically `sdf`). - * - * 1. The `sdf` rasterizer is sensitive to really small features (e.g., - * sharp turns that are less than 1~pixel) and imperfections in the - * glyph's outline, causing artifacts in the final output. - * - * 2. The `sdf` rasterizer has limited support for handling intersecting - * contours and *cannot* handle self-intersecting contours whatsoever. - * Self-intersection happens when a single connected contour - * intersects itself at some point; having these in your font - * definitely poses a problem to the rasterizer and cause artifacts, - * too. - * - * 3. Generating SDF for really small glyphs may result in undesirable - * output; the pixel grid (which stores distance information) becomes - * too coarse. - * - * 4. Since the output buffer is normalized, precision at smaller spreads - * is greater than precision at larger spread values because the - * output range of [0..255] gets mapped to a smaller SDF range. A - * spread of~2 should be sufficient in most cases. - * - * Points (1) and (2) can be avoided by using the `bsdf` rasterizer, - * which is more stable than the `sdf` rasterizer in general. - * */ typedef enum FT_Render_Mode_ { diff --git a/include/freetype/ftdriver.h b/include/freetype/ftdriver.h index baf15a460..b91affc9b 100644 --- a/include/freetype/ftdriver.h +++ b/include/freetype/ftdriver.h @@ -817,6 +817,79 @@ FT_BEGIN_HEADER * 2.5 */ + + /************************************************************************** + * + * @property: + * spread + * + * @description: + * This property of the 'sdf' and 'bsdf' renderers defines how the signed + * distance field (SDF) is represented in the output bitmap. The output + * values are calculated as follows, '128 * ( SDF / spread + 1 )', with + * the result truncated to the 8-bit range [0..255]. Therefore, 'spread' + * is also the maximum euclidean distance from the edge after which the + * values are truncated. The spread is specified in pixels with the + * default value of 8. + * + * @example: + * The following example code demonstrates how to set the SDF spread + * (omitting the error handling). + * + * ``` + * FT_Library library; + * FT_UInt spread = 2; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "sdf", "spread", &spread ); + * ``` + * + * @note + * FreeType has two rasterizers for generating SDF, namely: + * + * 1. `sdf` for generating SDF directly from glyph's outline, and + * + * 2. `bsdf` for generating SDF from rasterized bitmaps. + * + * Depending on the glyph type (i.e., outline or bitmap), one of the two + * rasterizers is chosen at runtime and used for generating SDFs. To + * force the use of `bsdf` you should render the glyph with any of the + * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and + * then re-render with `FT_RENDER_MODE_SDF`. + * + * There are some issues with stability and possible failures of the SDF + * renderers (specifically `sdf`). + * + * 1. The `sdf` rasterizer is sensitive to really small features (e.g., + * sharp turns that are less than 1~pixel) and imperfections in the + * glyph's outline, causing artifacts in the final output. + * + * 2. The `sdf` rasterizer has limited support for handling intersecting + * contours and *cannot* handle self-intersecting contours whatsoever. + * Self-intersection happens when a single connected contour + * intersects itself at some point; having these in your font + * definitely poses a problem to the rasterizer and cause artifacts, + * too. + * + * 3. Generating SDF for really small glyphs may result in undesirable + * output; the pixel grid (which stores distance information) becomes + * too coarse. + * + * 4. Since the output buffer is normalized, precision at smaller spreads + * is greater than precision at larger spread values because the + * output range of [0..255] gets mapped to a smaller SDF range. A + * spread of~2 should be sufficient in most cases. + * + * Points (1) and (2) can be avoided by using the `bsdf` rasterizer, + * which is more stable than the `sdf` rasterizer in general. + * + * @since: + * 2.11 + */ + + /************************************************************************** * * @property: From e2bcca40ca0d82ae64ba25e5c5e252dc0d083162 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 22 Apr 2024 22:43:41 -0400 Subject: [PATCH 13/60] * include/freetype/ftdriver.h: s/truncated/clamped/. --- include/freetype/ftdriver.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/freetype/ftdriver.h b/include/freetype/ftdriver.h index b91affc9b..4c83f7396 100644 --- a/include/freetype/ftdriver.h +++ b/include/freetype/ftdriver.h @@ -827,9 +827,9 @@ FT_BEGIN_HEADER * This property of the 'sdf' and 'bsdf' renderers defines how the signed * distance field (SDF) is represented in the output bitmap. The output * values are calculated as follows, '128 * ( SDF / spread + 1 )', with - * the result truncated to the 8-bit range [0..255]. Therefore, 'spread' + * the result clamped to the 8-bit range [0..255]. Therefore, 'spread' * is also the maximum euclidean distance from the edge after which the - * values are truncated. The spread is specified in pixels with the + * values are clamped. The spread is specified in pixels with the * default value of 8. * * @example: @@ -838,7 +838,7 @@ FT_BEGIN_HEADER * * ``` * FT_Library library; - * FT_UInt spread = 2; + * FT_Int spread = 2; * * * FT_Init_FreeType( &library ); From 4e079f635747433801a02f3bca208e6bd8819381 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 27 Apr 2024 20:07:36 -0400 Subject: [PATCH 14/60] Document the SDF spread further. --- include/freetype/ftdriver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/freetype/ftdriver.h b/include/freetype/ftdriver.h index 4c83f7396..dd31626b0 100644 --- a/include/freetype/ftdriver.h +++ b/include/freetype/ftdriver.h @@ -830,7 +830,8 @@ FT_BEGIN_HEADER * the result clamped to the 8-bit range [0..255]. Therefore, 'spread' * is also the maximum euclidean distance from the edge after which the * values are clamped. The spread is specified in pixels with the - * default value of 8. + * default value of 8. For accurate SDF texture mapping (interpolation), + * the spread should be large enough to accommodate the target grid unit. * * @example: * The following example code demonstrates how to set the SDF spread From 1168b1b5b0774b09a7484b150d2d49c682e46e91 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 27 Apr 2024 20:44:01 -0400 Subject: [PATCH 15/60] * src/cache/ftcimage.c (ftc_inode_weight): Formatting. --- src/cache/ftcimage.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cache/ftcimage.c b/src/cache/ftcimage.c index c142dcc8d..146306405 100644 --- a/src/cache/ftcimage.c +++ b/src/cache/ftcimage.c @@ -115,10 +115,9 @@ { case FT_GLYPH_FORMAT_BITMAP: { - FT_BitmapGlyph bitg; + FT_BitmapGlyph bitg = (FT_BitmapGlyph)glyph; - bitg = (FT_BitmapGlyph)glyph; size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) + sizeof ( *bitg ); } @@ -126,10 +125,9 @@ case FT_GLYPH_FORMAT_OUTLINE: { - FT_OutlineGlyph outg; + FT_OutlineGlyph outg = (FT_OutlineGlyph)glyph; - outg = (FT_OutlineGlyph)glyph; size = (FT_Offset)outg->outline.n_points * ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) + (FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) + From f8f0d1a1d919bbaec89dbc44e7704cdf8ebd6662 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 29 Apr 2024 16:58:59 -0400 Subject: [PATCH 16/60] * src/cache/ftcmru.c (FTC_MruList_New): Do not reset nodes. Resetting of the size nodes can crash, if a parent face purge happens simultaneously and destroys the node. It is safer to create a new node. Fixes #1270, reopened with a separate issue. --- src/cache/ftcmru.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c index a767fa408..f908eb25a 100644 --- a/src/cache/ftcmru.c +++ b/src/cache/ftcmru.c @@ -242,27 +242,6 @@ FT_Memory memory = list->memory; - if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes ) - { - prev = list->nodes->prev; - - FT_ASSERT( prev ); - - /* try fast reset when available */ - if ( list->clazz.node_reset ) - { - error = list->clazz.node_reset( prev, key, list->data ); - if ( !error ) - { - node = prev; - - FTC_MruNode_Up( &list->nodes, node ); - } - - goto Exit; - } - } - /* zero new node in case of node_init failure */ if ( FT_ALLOC( node, list->clazz.node_size ) ) goto Exit; @@ -275,6 +254,8 @@ goto Clean; } + else if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes ) + prev = list->nodes->prev; FTC_MruNode_Prepend( &list->nodes, node ); list->num_nodes++; From a209e1adcd7d8d4fffe2c8412a02ecb8846d0171 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 29 Apr 2024 17:54:30 -0400 Subject: [PATCH 17/60] [cache] Remove unused `node_reset`. * src/cache/ftcmru.h (FTC_MruListClassRec): Remove `node_reset` field. * src/cache/ftcbasic.c (ftc_basic_{image,sbit}_family_class): Ditto. * src/cache/ftcmanag.c (ftc_face_list_class): Ditto. (ftc_size_node_reset): Remove function. * src/cache/ftcglyph.h: Fix comment. --- src/cache/ftcbasic.c | 2 -- src/cache/ftcglyph.h | 1 - src/cache/ftcmanag.c | 27 --------------------------- src/cache/ftcmru.h | 6 ------ 4 files changed, 36 deletions(-) diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c index 953b96ebe..04f664fad 100644 --- a/src/cache/ftcbasic.c +++ b/src/cache/ftcbasic.c @@ -243,7 +243,6 @@ ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */ ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */ - NULL, /* FTC_MruNode_ResetFunc node_reset */ NULL /* FTC_MruNode_DoneFunc node_done */ }, @@ -421,7 +420,6 @@ sizeof ( FTC_BasicFamilyRec ), ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */ ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */ - NULL, /* FTC_MruNode_ResetFunc node_reset */ NULL /* FTC_MruNode_DoneFunc node_done */ }, diff --git a/src/cache/ftcglyph.h b/src/cache/ftcglyph.h index 66a1bc77e..b1a96da8e 100644 --- a/src/cache/ftcglyph.h +++ b/src/cache/ftcglyph.h @@ -65,7 +65,6 @@ * - FTC_Family sub-class, e.g. MyFamily, with relevant methods: * my_family_compare * my_family_init - * my_family_reset (optional) * my_family_done * * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index 29a95baa1..c0a48a53b 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -133,31 +133,6 @@ } - FT_CALLBACK_DEF( FT_Error ) - ftc_size_node_reset( FTC_MruNode ftcnode, - FT_Pointer ftcscaler, - FT_Pointer ftcmanager ) - { - FT_Error error; - FT_Size size; - FTC_SizeNode node = (FTC_SizeNode)ftcnode; - FTC_Scaler scaler = (FTC_Scaler)ftcscaler; - FTC_Manager manager = (FTC_Manager)ftcmanager; - - - error = ftc_scaler_lookup_size( manager, scaler, &size ); - if ( !error ) - { - FT_Done_Size( node->size ); - - node->size = size; - node->scaler = scaler[0]; - } - - return error; - } - - static const FTC_MruListClassRec ftc_size_list_class = { @@ -165,7 +140,6 @@ ftc_size_node_compare, /* FTC_MruNode_CompareFunc node_compare */ ftc_size_node_init, /* FTC_MruNode_InitFunc node_init */ - ftc_size_node_reset, /* FTC_MruNode_ResetFunc node_reset */ ftc_size_node_done /* FTC_MruNode_DoneFunc node_done */ }; @@ -307,7 +281,6 @@ ftc_face_node_compare, /* FTC_MruNode_CompareFunc node_compare */ ftc_face_node_init, /* FTC_MruNode_InitFunc node_init */ - NULL, /* FTC_MruNode_ResetFunc node_reset */ ftc_face_node_done /* FTC_MruNode_DoneFunc node_done */ }; diff --git a/src/cache/ftcmru.h b/src/cache/ftcmru.h index abafea3ae..68faab984 100644 --- a/src/cache/ftcmru.h +++ b/src/cache/ftcmru.h @@ -95,11 +95,6 @@ FT_BEGIN_HEADER FT_Pointer key, FT_Pointer data ); - typedef FT_Error - (*FTC_MruNode_ResetFunc)( FTC_MruNode node, - FT_Pointer key, - FT_Pointer data ); - typedef void (*FTC_MruNode_DoneFunc)( FTC_MruNode node, FT_Pointer data ); @@ -111,7 +106,6 @@ FT_BEGIN_HEADER FTC_MruNode_CompareFunc node_compare; FTC_MruNode_InitFunc node_init; - FTC_MruNode_ResetFunc node_reset; FTC_MruNode_DoneFunc node_done; } FTC_MruListClassRec; From 5962d3c1b928fa49980e795590c2263f949b8a07 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 29 Apr 2024 22:34:09 -0400 Subject: [PATCH 18/60] * src/cache/ftccache.c (FTC_Cache_RemoveFaceID): Remove nodes instantly. --- src/cache/ftccache.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c index 33a03486d..8a3d887f9 100644 --- a/src/cache/ftccache.c +++ b/src/cache/ftccache.c @@ -544,7 +544,6 @@ FTC_FaceID face_id ) { FTC_Manager manager = cache->manager; - FTC_Node frees = NULL; FT_UFast count = cache->p; FT_UFast i; @@ -557,41 +556,27 @@ for (;;) { FTC_Node node = *pnode; - FT_Bool list_changed = FALSE; if ( !node ) break; - if ( cache->clazz.node_remove_faceid( node, face_id, - cache, &list_changed ) ) + if ( cache->clazz.node_remove_faceid( node, face_id, cache, NULL ) ) { - *pnode = node->link; - node->link = frees; - frees = node; + *pnode = node->link; + + manager->cur_weight -= cache->clazz.node_weight( node, cache ); + ftc_node_mru_unlink( node, manager ); + + cache->clazz.node_free( node, cache ); + + cache->slack++; } else pnode = &node->link; } } - /* remove all nodes in the free list */ - while ( frees ) - { - FTC_Node node; - - - node = frees; - frees = node->link; - - manager->cur_weight -= cache->clazz.node_weight( node, cache ); - ftc_node_mru_unlink( node, manager ); - - cache->clazz.node_free( node, cache ); - - cache->slack++; - } - ftc_cache_resize( cache ); } From 2c9691e7c176be180114cd2889ed0b5147e7c6e1 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 30 Apr 2024 12:59:52 +0000 Subject: [PATCH 19/60] * docs/CHANGES: Updated. --- docs/CHANGES | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGES b/docs/CHANGES index cbf3cc93a..555c8ac7c 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -1,7 +1,9 @@ -CHANGES BETWEEN 2.13.2 and 2.13.3 (202Y-Mmm-DD) +CHANGES BETWEEN 2.13.2 and 2.13.3 (2024-Mmm-DD) I. IMPORTANT BUG FIXES + - Rare double-free crashes in the cache subsystem have been fixed. + - Excessive stack allocation in the autohinter has been fixed. From 13da9042676e6ff824c725f490b7559194f7dc9c Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 1 May 2024 00:34:21 -0400 Subject: [PATCH 20/60] * src/sfnt/sfwoff2.c (compute_ULong_sum): Clean up. --- src/sfnt/sfwoff2.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index f3c9e2854..1ddbb247e 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -289,7 +289,6 @@ FT_ULong checksum = 0; FT_ULong aligned_size = size & ~3UL; FT_ULong i; - FT_ULong v; for ( i = 0; i < aligned_size; i += 4 ) @@ -298,14 +297,9 @@ ( (FT_ULong)buf[i + 2] << 8 ) | ( (FT_ULong)buf[i + 3] << 0 ); - /* If size is not aligned to 4, treat as if it is padded with 0s. */ - if ( size != aligned_size ) - { - v = 0; - for ( i = aligned_size ; i < size; ++i ) - v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) ); - checksum += v; - } + /* remaining bytes can be shifted and added one at a time */ + for ( ; i < size; ++i ) + checksum += (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) ); return checksum; } From 4d504684789dc6f8f452aaa4df04f96f31082345 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 1 May 2024 23:19:31 -0400 Subject: [PATCH 21/60] [sfnt] Use faster macros in checksums. * src/truetype/ttobjs.c (tt_synth_sfnt_checksum): Use FT_NEXT_XXX. * src/sfnt/sfwoff2.c (compute_ULong_sum): Use macros. --- src/sfnt/sfwoff2.c | 10 ++++------ src/truetype/ttobjs.c | 13 ++++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index 1ddbb247e..3df4d2664 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -289,17 +289,15 @@ FT_ULong checksum = 0; FT_ULong aligned_size = size & ~3UL; FT_ULong i; + FT_Int shift; for ( i = 0; i < aligned_size; i += 4 ) - checksum += ( (FT_ULong)buf[i ] << 24 ) | - ( (FT_ULong)buf[i + 1] << 16 ) | - ( (FT_ULong)buf[i + 2] << 8 ) | - ( (FT_ULong)buf[i + 3] << 0 ); + checksum += FT_NEXT_ULONG( buf ); /* remaining bytes can be shifted and added one at a time */ - for ( ; i < size; ++i ) - checksum += (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) ); + for ( shift = 24; i < size; i++, shift -= 8 ) + checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift; return checksum; } diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index 3cdbfff1b..05489d732 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -256,17 +256,20 @@ { FT_Error error; FT_UInt32 checksum = 0; - FT_UInt i; + FT_Byte* p; + FT_Int shift; if ( FT_FRAME_ENTER( length ) ) return 0; - for ( ; length > 3; length -= 4 ) - checksum += (FT_UInt32)FT_GET_ULONG(); + p = (FT_Byte*)stream->cursor; - for ( i = 3; length > 0; length--, i-- ) - checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 ); + for ( ; length > 3; length -= 4 ) + checksum += FT_NEXT_ULONG( p ); + + for ( shift = 24; length > 0; length--, shift -=8 ) + checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift; FT_FRAME_EXIT(); From 13d1180f4542d19557e146cc0124e51891733b0c Mon Sep 17 00:00:00 2001 From: Ben Wanger Date: Thu, 2 May 2024 13:16:46 -0400 Subject: [PATCH 22/60] [woff2] Disallow zero table font entries The existing code already disallows zero table woff2 overall, but still allows for individual CollectionFontEntry to create font instances with zero tables. Such fonts are not useful so error early. This also fixes an MSAN discovered issue where if a CollectionFontEntry numTables is zero then the sfnt_header was not fully initialized. * src/sfnt/sfwoff2.c (woff2_open_font): error on zero tables, always initalize sfnt_header Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=68384 --- src/sfnt/sfwoff2.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index 3df4d2664..0e272fc99 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -1791,7 +1791,6 @@ FT_Byte* sfnt = NULL; FT_Stream sfnt_stream = NULL; - FT_Byte* sfnt_header; FT_ULong sfnt_size; FT_Byte* uncompressed_buf = NULL; @@ -2135,6 +2134,13 @@ WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index; + if ( ttc_font->num_tables == 0 ) + { + FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + /* Create a temporary array. */ if ( FT_QNEW_ARRAY( temp_indices, ttc_font->num_tables ) ) @@ -2190,13 +2196,9 @@ FT_NEW( sfnt_stream ) ) goto Exit; - sfnt_header = sfnt; - - WRITE_ULONG( sfnt_header, woff2.flavor ); - - if ( woff2.num_tables ) { - FT_UInt searchRange, entrySelector, rangeShift, x; + FT_UInt searchRange, entrySelector, rangeShift, x; + FT_Byte* sfnt_header = sfnt; x = woff2.num_tables; @@ -2211,6 +2213,7 @@ searchRange = ( 1 << entrySelector ) * 16; rangeShift = ( woff2.num_tables * 16 ) - searchRange; + WRITE_ULONG( sfnt_header, woff2.flavor ); WRITE_USHORT( sfnt_header, woff2.num_tables ); WRITE_USHORT( sfnt_header, searchRange ); WRITE_USHORT( sfnt_header, entrySelector ); From 3f28a6b6afed06a7eeaeefb7e319e6c23bdd3eb8 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 3 May 2024 15:44:57 +0000 Subject: [PATCH 23/60] [woff,woff2] Limit the number of tables and use FT_MSB. The upper limit of 4095 is implied by the SFNT header format where the multiplication by 16 would overflow without it. * src/sfnt/sfwoff.c (woff_open_font): Updated. * src/sfnt/sfwoff2.c (woff2_open_font): Ditto. --- src/sfnt/sfwoff.c | 18 +++++------------- src/sfnt/sfwoff2.c | 21 +++++++-------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/sfnt/sfwoff.c b/src/sfnt/sfwoff.c index 8d33b7133..14514bf95 100644 --- a/src/sfnt/sfwoff.c +++ b/src/sfnt/sfwoff.c @@ -18,6 +18,7 @@ #include "sfwoff.h" #include +#include #include #include #include @@ -149,6 +150,7 @@ /* Miscellaneous checks. */ if ( woff.length != stream->size || woff.num_tables == 0 || + woff.num_tables > 0xFFFU || 44 + woff.num_tables * 20UL >= woff.length || 12 + woff.num_tables * 16UL >= woff.totalSfntSize || ( woff.totalSfntSize & 3 ) != 0 || @@ -169,21 +171,11 @@ /* Write sfnt header. */ { - FT_UInt searchRange, entrySelector, rangeShift, x; + FT_Int entrySelector = FT_MSB( woff.num_tables ); + FT_Int searchRange = ( 1 << entrySelector ) * 16; + FT_Int rangeShift = woff.num_tables * 16 - searchRange; - x = woff.num_tables; - entrySelector = 0; - while ( x ) - { - x >>= 1; - entrySelector += 1; - } - entrySelector--; - - searchRange = ( 1 << entrySelector ) * 16; - rangeShift = woff.num_tables * 16 - searchRange; - WRITE_ULONG ( sfnt_header, woff.flavor ); WRITE_USHORT( sfnt_header, woff.num_tables ); WRITE_USHORT( sfnt_header, searchRange ); diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index 0e272fc99..bc7a55d79 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -18,6 +18,7 @@ #include "sfwoff2.h" #include "woff2tags.h" #include +#include #include #include @@ -1844,6 +1845,7 @@ /* Miscellaneous checks. */ if ( woff2.length != stream->size || woff2.num_tables == 0 || + woff2.num_tables > 0xFFFU || 48 + woff2.num_tables * 20UL >= woff2.length || ( woff2.metaOffset == 0 && ( woff2.metaLength != 0 || woff2.metaOrigLength != 0 ) ) || @@ -2134,7 +2136,7 @@ WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index; - if ( ttc_font->num_tables == 0 ) + if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU ) { FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" )); error = FT_THROW( Invalid_Table ); @@ -2197,23 +2199,14 @@ goto Exit; { - FT_UInt searchRange, entrySelector, rangeShift, x; FT_Byte* sfnt_header = sfnt; + FT_Int entrySelector = FT_MSB( woff.num_tables ); + FT_Int searchRange = ( 1 << entrySelector ) * 16; + FT_Int rangeShift = woff.num_tables * 16 - searchRange; - x = woff2.num_tables; - entrySelector = 0; - while ( x ) - { - x >>= 1; - entrySelector += 1; - } - entrySelector--; - searchRange = ( 1 << entrySelector ) * 16; - rangeShift = ( woff2.num_tables * 16 ) - searchRange; - - WRITE_ULONG( sfnt_header, woff2.flavor ); + WRITE_ULONG ( sfnt_header, woff2.flavor ); WRITE_USHORT( sfnt_header, woff2.num_tables ); WRITE_USHORT( sfnt_header, searchRange ); WRITE_USHORT( sfnt_header, entrySelector ); From 7bd887f177b765165ecf7c443b8d0bab88034df0 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 3 May 2024 16:04:35 +0000 Subject: [PATCH 24/60] * src/sfnt/sfwoff2.c (woff2_open_font): Fix copy-paste typo. --- src/sfnt/sfwoff2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index bc7a55d79..589b3e0c6 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -2201,9 +2201,9 @@ { FT_Byte* sfnt_header = sfnt; - FT_Int entrySelector = FT_MSB( woff.num_tables ); + FT_Int entrySelector = FT_MSB( woff2.num_tables ); FT_Int searchRange = ( 1 << entrySelector ) * 16; - FT_Int rangeShift = woff.num_tables * 16 - searchRange; + FT_Int rangeShift = woff2.num_tables * 16 - searchRange; WRITE_ULONG ( sfnt_header, woff2.flavor ); From 2edfd7e1687c311e695b1645b0e7f6df6e2b5406 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 4 May 2024 16:42:47 -0400 Subject: [PATCH 25/60] * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Remove FT_ABS. See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=68679 --- src/autofit/aflatin.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 316e7c676..89287f7ea 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -1263,10 +1263,9 @@ max_height = FT_MAX( max_height, -Axis->blues[nn].descender ); } - dist = FT_ABS( FT_MulFix( max_height, new_scale - scale ) ); - dist &= ~127; + dist = FT_MulFix( max_height, new_scale - scale ); - if ( dist == 0 ) + if ( -128 < dist && dist < 128 ) { FT_TRACE5(( "af_latin_metrics_scale_dim:" " x height alignment (style `%s'):\n", From d0e3239f32a0fe71c234cf2c1ce7a90cb11b64bb Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 6 May 2024 13:39:06 +0000 Subject: [PATCH 26/60] [sdf, bsdf] Use shared FT_SqrtFixed. FT_SqrtFixed (95b0fe2a6dff) is faster and does not overflow. * src/sdf/ftsdfcommin.h (square_root): Replace with a macro. * src/sdf/ftsdfcommin.c (square_root): Remove function. --- src/sdf/ftsdfcommon.c | 43 ------------------------------------------- src/sdf/ftsdfcommon.h | 3 +-- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/src/sdf/ftsdfcommon.c b/src/sdf/ftsdfcommon.c index 5841ded21..6b2cf7dfe 100644 --- a/src/sdf/ftsdfcommon.c +++ b/src/sdf/ftsdfcommon.c @@ -22,49 +22,6 @@ #include "ftsdfcommon.h" - /************************************************************************** - * - * common functions - * - */ - - /* - * Original algorithm: - * - * https://github.com/chmike/fpsqrt - * - * Use this to compute the square root of a 16.16 fixed-point number. - */ - FT_LOCAL_DEF( FT_16D16 ) - square_root( FT_16D16 val ) - { - FT_ULong t, q, b, r; - - - r = (FT_ULong)val; - b = 0x40000000L; - q = 0; - - while ( b > 0x40L ) - { - t = q + b; - - if ( r >= t ) - { - r -= t; - q = t + b; - } - - r <<= 1; - b >>= 1; - } - - q >>= 8; - - return (FT_16D16)q; - } - - /************************************************************************** * * format and sign manipulating functions diff --git a/src/sdf/ftsdfcommon.h b/src/sdf/ftsdfcommon.h index 44274e349..d0f623f9f 100644 --- a/src/sdf/ftsdfcommon.h +++ b/src/sdf/ftsdfcommon.h @@ -122,8 +122,7 @@ FT_BEGIN_HEADER typedef FT_BBox FT_CBox; /* control box of a curve */ - FT_LOCAL( FT_16D16 ) - square_root( FT_16D16 val ); +#define square_root( x ) (FT_16D16)FT_SqrtFixed( (FT_UInt32)( x ) ) FT_LOCAL( FT_SDFFormat ) map_fixed_to_sdf( FT_16D16 dist, From 2240e21cf5073e69442ae42519f5486014bd7d5d Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Mon, 6 May 2024 21:53:24 +0200 Subject: [PATCH 27/60] .mailmap: Fix entry for Ben Wagner. --- .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 9c7d08f88..31d2a4766 100644 --- a/.mailmap +++ b/.mailmap @@ -19,7 +19,7 @@ Anurag Thakur (अनुराग ठाकुर) David Turner David Turner Anuj Verma (अनुज वर्मा) -Ben Wagner Bungeman +Ben Wagner Ben Wagner Ben Wagner Nikolaus Waxweiler From 5858fa16cace81fb7b3de7600cb765a820348bed Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Tue, 7 May 2024 18:19:58 -0400 Subject: [PATCH 28/60] [colr] Avoid overflow in range checks In 32 bit builds `FT_ULong` is 32 bits and can silently overflow when a large number is read into one and then it is summed or multiplied with another number. Checks for range overflow must be written so that they themselves do not overflow. Also ensure that the table_size is always the first part of the range check and consistently use `<` or `<=`. * src/sfnt/ttcolr.c (tt_face_load_colr): Avoid overflow. (find_base_glyph_v1_record): Remove old work-around. Bug: https://issues.chromium.org/issues/41495455 Bug: https://issues.chromium.org/issues/40945818 --- src/sfnt/ttcolr.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c index 1c3fd70d0..b37658dde 100644 --- a/src/sfnt/ttcolr.c +++ b/src/sfnt/ttcolr.c @@ -208,18 +208,19 @@ colr->num_base_glyphs = FT_NEXT_USHORT( p ); base_glyph_offset = FT_NEXT_ULONG( p ); - if ( base_glyph_offset >= table_size ) + if ( table_size <= base_glyph_offset ) goto InvalidTable; - if ( colr->num_base_glyphs * BASE_GLYPH_SIZE > - table_size - base_glyph_offset ) + if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE + < colr->num_base_glyphs ) goto InvalidTable; layer_offset = FT_NEXT_ULONG( p ); colr->num_layers = FT_NEXT_USHORT( p ); - if ( layer_offset >= table_size ) + if ( table_size <= layer_offset ) goto InvalidTable; - if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset ) + if ( ( table_size - layer_offset ) / LAYER_SIZE + < colr->num_layers ) goto InvalidTable; if ( colr->version == 1 ) @@ -229,14 +230,14 @@ base_glyphs_offset_v1 = FT_NEXT_ULONG( p ); - if ( base_glyphs_offset_v1 >= table_size - 4 ) + if ( table_size - 4 <= base_glyphs_offset_v1 ) goto InvalidTable; p1 = (FT_Byte*)( table + base_glyphs_offset_v1 ); num_base_glyphs_v1 = FT_PEEK_ULONG( p1 ); - if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE > - table_size - base_glyphs_offset_v1 ) + if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE + < num_base_glyphs_v1 ) goto InvalidTable; colr->num_base_glyphs_v1 = num_base_glyphs_v1; @@ -244,19 +245,19 @@ layer_offset_v1 = FT_NEXT_ULONG( p ); - if ( layer_offset_v1 >= table_size ) + if ( table_size <= layer_offset_v1 ) goto InvalidTable; if ( layer_offset_v1 ) { - if ( layer_offset_v1 >= table_size - 4 ) + if ( table_size - 4 <= layer_offset_v1 ) goto InvalidTable; p1 = (FT_Byte*)( table + layer_offset_v1 ); num_layers_v1 = FT_PEEK_ULONG( p1 ); - if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE > - table_size - layer_offset_v1 ) + if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE + < num_layers_v1 ) goto InvalidTable; colr->num_layers_v1 = num_layers_v1; @@ -279,7 +280,7 @@ clip_list_offset = FT_NEXT_ULONG( p ); - if ( clip_list_offset >= table_size ) + if ( table_size <= clip_list_offset ) goto InvalidTable; if ( clip_list_offset ) @@ -311,7 +312,7 @@ goto InvalidTable; var_store_offset = FT_NEXT_ULONG( p ); - if ( var_store_offset >= table_size ) + if ( table_size <= var_store_offset ) goto InvalidTable; if ( var_store_offset ) @@ -1270,7 +1271,6 @@ static FT_Bool find_base_glyph_v1_record( FT_Byte * base_glyph_begin, FT_UInt num_base_glyph, - FT_Byte * end_colr, FT_UInt glyph_id, BaseGlyphV1Record *record ) { @@ -1290,14 +1290,6 @@ */ FT_Byte *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE; - - /* We need to be able to read 2 bytes (FT_NEXT_USHORT) for the glyph */ - /* ID, then 4 bytes (FT_NEXT_ULONG) for the paint offset. If that's */ - /* not available before the end of the table, something's wrong with */ - /* the font and we can't find a COLRv1 glyph. */ - if ( p > end_colr - 2 - 4 ) - return 0; - gid = FT_NEXT_USHORT( p ); if ( gid < glyph_id ) @@ -1338,7 +1330,6 @@ if ( !find_base_glyph_v1_record( colr->base_glyphs_v1, colr->num_base_glyphs_v1, - (FT_Byte*)colr->table + colr->table_size, base_glyph, &base_glyph_v1_record ) ) return 0; From 1264b84c08a31d11303fe3781444f6f026ea60b8 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 7 May 2024 23:35:59 -0400 Subject: [PATCH 29/60] * include/freetype/internal/psaux.h: Fix g++ warning. Reported by Hin-Tak Leung. --- include/freetype/internal/psaux.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h index 41f481d5a..fffa103ca 100644 --- a/include/freetype/internal/psaux.h +++ b/include/freetype/internal/psaux.h @@ -225,6 +225,7 @@ FT_BEGIN_HEADER typedef enum T1_FieldLocation_ { + T1_FIELD_LOCATION_NONE = 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_LOCATION_FONT_DICT, T1_FIELD_LOCATION_FONT_EXTRA, @@ -359,7 +360,12 @@ FT_BEGIN_HEADER #define T1_FIELD_CALLBACK( _ident, _name, _dict ) \ T1_NEW_CALLBACK_FIELD( _ident, _name, _dict ) -#define T1_FIELD_ZERO { 0, NULL, 0, 0, NULL, 0, 0, 0, 0, 0 } +#define T1_FIELD_ZERO \ + { \ + 0, \ + NULL, T1_FIELD_TYPE_NONE, T1_FIELD_LOCATION_NONE, \ + NULL, 0, 0, 0, 0, 0 \ + } /*************************************************************************/ From a46424228f0998a72c715f32e18dca8a7a764c1f Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Wed, 8 May 2024 11:33:47 -0400 Subject: [PATCH 30/60] [psaux] Fix location and type order in initializer `T1_FIELD_ZERO` is used to zero initialize a `T1_FieldRec`. `T1_FIELD_ZERO` is currently initilizing `T1_FieldRec::location` with a `T1_FieldType` and `T1_FieldRec::type` with a `T1_FieldLocation`. This was detected with `-Wenum-conversion`. * include/freetype/internal/psaux.h (T1_FIELD_ZERO): correct order of initalizers --- include/freetype/internal/psaux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h index fffa103ca..745d2cb56 100644 --- a/include/freetype/internal/psaux.h +++ b/include/freetype/internal/psaux.h @@ -363,7 +363,7 @@ FT_BEGIN_HEADER #define T1_FIELD_ZERO \ { \ 0, \ - NULL, T1_FIELD_TYPE_NONE, T1_FIELD_LOCATION_NONE, \ + NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \ NULL, 0, 0, 0, 0, 0 \ } From b875924a6fc176d46fc9f82c616db631fc4d665c Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 10 May 2024 23:01:23 -0400 Subject: [PATCH 31/60] * src/pshinter/pshrec.c (ps_hints_stem): Correct argument. --- src/pshinter/pshrec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c index b10c70ec9..0b2b549fc 100644 --- a/src/pshinter/pshrec.c +++ b/src/pshinter/pshrec.c @@ -806,7 +806,7 @@ ps_hints_stem( PS_Hints hints, FT_UInt dimension, FT_Int count, - FT_Long* stems ) + FT_Pos* stems ) { PS_Dimension dim; From 4a85db7e3181f23126af6c4473b245e48f6b1902 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 11 May 2024 22:19:25 -0400 Subject: [PATCH 32/60] [type1/MM] Tighten headers. * include/freetype/internal/t1types.h: Host PS_DesignMap and PS_Blend. * include/freetype/ftmm.h: Host and document TT_MAX_MM_XXX. * include/freetype/t1tables.h: Remove them from here. --- include/freetype/ftmm.h | 27 ++++++++++++-- include/freetype/internal/t1types.h | 50 ++++++++++++++++++++++++- include/freetype/t1tables.h | 58 ----------------------------- 3 files changed, 73 insertions(+), 62 deletions(-) diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h index a6e3e34fb..a85d0be43 100644 --- a/include/freetype/ftmm.h +++ b/include/freetype/ftmm.h @@ -20,9 +20,6 @@ #define FTMM_H_ -#include - - FT_BEGIN_HEADER @@ -53,6 +50,30 @@ FT_BEGIN_HEADER */ + /************************************************************************** + * + * @enum: + * T1_MAX_MM_XXX + * + * @description: + * Multiple Masters limits as defined in their specifications. + * + * @values: + * T1_MAX_MM_AXIS :: + * The maximum number of Multiple Masters axes. + * + * T1_MAX_MM_DESIGNS :: + * The maximum number of Multiple Masters designs. + * + * T1_MAX_MM_MAP_POINTS :: + * The maximum number of elements in a design map. + * + */ +#define T1_MAX_MM_AXIS 4 +#define T1_MAX_MM_DESIGNS 16 +#define T1_MAX_MM_MAP_POINTS 20 + + /************************************************************************** * * @struct: diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h index be63e4dcf..1821ae5cc 100644 --- a/include/freetype/internal/t1types.h +++ b/include/freetype/internal/t1types.h @@ -21,7 +21,7 @@ #define T1TYPES_H_ -#include +#include #include #include #include @@ -137,6 +137,54 @@ FT_BEGIN_HEADER } CID_SubrsRec, *CID_Subrs; + /* this structure is used to store the BlendDesignMap entry for an axis */ + typedef struct PS_DesignMap_ + { + FT_Byte num_points; + FT_Long* design_points; + FT_Fixed* blend_points; + + } PS_DesignMapRec, *PS_DesignMap; + + /* backward compatible definition */ + typedef PS_DesignMapRec T1_DesignMap; + + + typedef struct PS_BlendRec_ + { + FT_UInt num_designs; + FT_UInt num_axis; + + FT_String* axis_names[T1_MAX_MM_AXIS]; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; + PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; + + FT_Fixed* weight_vector; + FT_Fixed* default_weight_vector; + + PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; + PS_Private privates [T1_MAX_MM_DESIGNS + 1]; + + FT_ULong blend_bitflags; + + FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; + + /* since 2.3.0 */ + + /* undocumented, optional: the default design instance; */ + /* corresponds to default_weight_vector -- */ + /* num_default_design_vector == 0 means it is not present */ + /* in the font and associated metrics files */ + FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; + FT_UInt num_default_design_vector; + + } PS_BlendRec, *PS_Blend; + + + /* backward compatible definition */ + typedef PS_BlendRec T1_Blend; + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ diff --git a/include/freetype/t1tables.h b/include/freetype/t1tables.h index 8a1b10593..fbd558aa3 100644 --- a/include/freetype/t1tables.h +++ b/include/freetype/t1tables.h @@ -269,64 +269,6 @@ FT_BEGIN_HEADER /* */ - /* maximum number of Multiple Masters designs, as defined in the spec */ -#define T1_MAX_MM_DESIGNS 16 - - /* maximum number of Multiple Masters axes, as defined in the spec */ -#define T1_MAX_MM_AXIS 4 - - /* maximum number of elements in a design map */ -#define T1_MAX_MM_MAP_POINTS 20 - - - /* this structure is used to store the BlendDesignMap entry for an axis */ - typedef struct PS_DesignMap_ - { - FT_Byte num_points; - FT_Long* design_points; - FT_Fixed* blend_points; - - } PS_DesignMapRec, *PS_DesignMap; - - /* backward compatible definition */ - typedef PS_DesignMapRec T1_DesignMap; - - - typedef struct PS_BlendRec_ - { - FT_UInt num_designs; - FT_UInt num_axis; - - FT_String* axis_names[T1_MAX_MM_AXIS]; - FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; - PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; - - FT_Fixed* weight_vector; - FT_Fixed* default_weight_vector; - - PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; - PS_Private privates [T1_MAX_MM_DESIGNS + 1]; - - FT_ULong blend_bitflags; - - FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; - - /* since 2.3.0 */ - - /* undocumented, optional: the default design instance; */ - /* corresponds to default_weight_vector -- */ - /* num_default_design_vector == 0 means it is not present */ - /* in the font and associated metrics files */ - FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; - FT_UInt num_default_design_vector; - - } PS_BlendRec, *PS_Blend; - - - /* backward compatible definition */ - typedef PS_BlendRec T1_Blend; - - /************************************************************************** * * @struct: From e834786b34673d553d3e757b4210dd5b48b71d40 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 11 May 2024 23:25:37 -0400 Subject: [PATCH 33/60] * docs/CHANGES: Mention the last commit. --- docs/CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/CHANGES b/docs/CHANGES index 555c8ac7c..fc18eb10a 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -23,6 +23,10 @@ CHANGES BETWEEN 2.13.2 and 2.13.3 (2024-Mmm-DD) Code contributed by David Saltzman . + - The internal structures `PS_DesignMap` and `PS_Blend` related to + parsing of old Multiple Masters fonts have been removed from the + public header file `t1tables.h`. + ====================================================================== From 5b1cde804da66ce0074be7a96dd7732a47972e4a Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 11 May 2024 23:27:34 -0400 Subject: [PATCH 34/60] * src/type1/t1load.c (parse_blend_design_map): Add risky cast. --- src/type1/t1load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type1/t1load.c b/src/type1/t1load.c index 7f63898fc..c41348c78 100644 --- a/src/type1/t1load.c +++ b/src/type1/t1load.c @@ -1045,7 +1045,7 @@ /* allocate design map data */ if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) ) goto Exit; - map->blend_points = map->design_points + num_points; + map->blend_points = (FT_Fixed*)(map->design_points + num_points); map->num_points = (FT_Byte)num_points; for ( p = 0; p < num_points; p++ ) From b8db819768b16ac4e529a4e4c34b2c5fa83cc389 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 12 May 2024 22:38:38 -0400 Subject: [PATCH 35/60] [type1/MM] Safer handle arrays of different types. * src/type1/t1load.c (parse_blend_design_map): Separately allocate... (T1_Done_Blend): ... and free `design_points` and `blend_points`. --- src/type1/t1load.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/type1/t1load.c b/src/type1/t1load.c index c41348c78..1704d1375 100644 --- a/src/type1/t1load.c +++ b/src/type1/t1load.c @@ -751,6 +751,7 @@ PS_DesignMap dmap = blend->design_map + n; + FT_FREE( dmap->blend_points ); FT_FREE( dmap->design_points ); dmap->num_points = 0; } @@ -1043,9 +1044,9 @@ } /* allocate design map data */ - if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) ) + if ( FT_QNEW_ARRAY( map->design_points, num_points ) || + FT_QNEW_ARRAY( map->blend_points, num_points ) ) goto Exit; - map->blend_points = (FT_Fixed*)(map->design_points + num_points); map->num_points = (FT_Byte)num_points; for ( p = 0; p < num_points; p++ ) From 68399b4244d85a1acc18ce669176b531b2eb7e32 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 13 May 2024 16:57:35 +0000 Subject: [PATCH 36/60] * include/freetype/ftmm.h: Include `freetype.h`. Reported by Ben Wagner, see !326. --- include/freetype/ftmm.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h index a85d0be43..35ed039c8 100644 --- a/include/freetype/ftmm.h +++ b/include/freetype/ftmm.h @@ -19,6 +19,14 @@ #ifndef FTMM_H_ #define FTMM_H_ +#include + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + FT_BEGIN_HEADER From cdd3572e52aba43823b93b7ba08076e90e7a7576 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 17 May 2024 22:25:00 -0400 Subject: [PATCH 37/60] * builds/windows/ftsystem.c: Use _WINRT_DLL to check for UWP. Fixes compilation using Windows GDK, reported by Erin Melucci. --- builds/windows/ftsystem.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/builds/windows/ftsystem.c b/builds/windows/ftsystem.c index 3a56834f6..477cad71f 100644 --- a/builds/windows/ftsystem.c +++ b/builds/windows/ftsystem.c @@ -196,8 +196,8 @@ } - /* non-desktop Universal Windows Platform */ -#if defined( WINAPI_FAMILY ) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP + /* support for Universal Windows Platform UWP, formerly WinRT */ +#ifdef _WINRT_DLL #define PACK_DWORD64( hi, lo ) ( ( (DWORD64)(hi) << 32 ) | (DWORD)(lo) ) @@ -248,10 +248,11 @@ dwCreationDisposition, &createExParams ); } -#endif +#endif /* _WINRT_DLL */ -#if defined( _WIN32_WCE ) + /* support for Windows CE */ +#ifdef _WIN32_WCE /* malloc.h provides implementation of alloca()/_alloca() */ #include @@ -291,9 +292,9 @@ dwFlagsAndAttributes, hTemplateFile ); } -#endif - +#endif /* _WIN32_WCE */ + /* support for really old Windows */ #if defined( _WIN32_WCE ) || defined ( _WIN32_WINDOWS ) || \ !defined( _WIN32_WINNT ) || _WIN32_WINNT <= 0x0400 @@ -311,7 +312,7 @@ return TRUE; } -#endif +#endif /* _WIN32_WCE || _WIN32_WINDOWS || _WIN32_WINNT <= 0x0400 */ /* documentation is in ftobjs.h */ From d7cf931ac699f6bc0d9d681d78c7a9a488c74449 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 19 May 2024 22:48:13 -0400 Subject: [PATCH 38/60] [truetype, type1] Use FT_DUP to duplicate data. * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Use concise FT_DUP. * src/truetype/ttgxvar.c (TT_Get_MM_Var): Ditto. * src/type1/t1load.c (parse_subrs): Ditto. --- src/truetype/ttgload.c | 4 +--- src/truetype/ttgxvar.c | 3 +-- src/type1/t1load.c | 6 ++---- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index df803a0f3..b7d8e1d66 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -418,11 +418,9 @@ /* and thus allocate the bytecode array size by ourselves */ if ( n_ins ) { - if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ) + if ( FT_DUP( exec->glyphIns, p, n_ins ) ) return error; - FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins ); - exec->glyphSize = n_ins; } } diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 7b33b8e52..99a9d4db0 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -2722,9 +2722,8 @@ FT_UInt n; - if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) + if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) ) goto Exit; - FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ); axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); diff --git a/src/type1/t1load.c b/src/type1/t1load.c index 1704d1375..ee7fb42a5 100644 --- a/src/type1/t1load.c +++ b/src/type1/t1load.c @@ -1877,9 +1877,8 @@ } /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_QALLOC( temp, size ) ) + if ( FT_DUP( temp, base, size ) ) goto Fail; - FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); size -= (FT_ULong)t1face->type1.private_dict.lenIV; error = T1_Add_Table( table, @@ -2091,9 +2090,8 @@ } /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_QALLOC( temp, size ) ) + if ( FT_DUP( temp, base, size ) ) goto Fail; - FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); size -= (FT_ULong)t1face->type1.private_dict.lenIV; error = T1_Add_Table( code_table, From 026fd5d4f032845eae070b0899d64a6acc51018f Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 19 May 2024 22:54:57 -0400 Subject: [PATCH 39/60] [cache] Use FT_DUP to duplicate data. * src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): Use concise FT_MEM_DUP. --- src/cache/ftcsbits.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c index c8548744b..19f3ef04d 100644 --- a/src/cache/ftcsbits.c +++ b/src/cache/ftcsbits.c @@ -53,8 +53,7 @@ size = (FT_ULong)pitch * bitmap->rows; - if ( !FT_QALLOC( sbit->buffer, size ) ) - FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); + FT_MEM_DUP( sbit->buffer, bitmap->buffer, size ); return error; } From b25265fe553c3420148bfa42bed4e2832558df85 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 19 May 2024 22:58:23 -0400 Subject: [PATCH 40/60] [bdf] Use concise macros. * src/bdf/bdflib.c (bdf_create_property): Use FT_STRDUP. (bdf_parse_glyphs_, bdf_parse_start_): Use FT_DUP for brevity. --- src/bdf/bdflib.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c index 0fa7e0a8c..813a4d839 100644 --- a/src/bdf/bdflib.c +++ b/src/bdf/bdflib.c @@ -864,15 +864,9 @@ p = font->user_props + font->nuser_props; - n = ft_strlen( name ) + 1; - if ( n > FT_LONG_MAX ) - return FT_THROW( Invalid_Argument ); - - if ( FT_QALLOC( p->name, n ) ) + if ( FT_STRDUP( p->name, name ) ) goto Exit; - FT_MEM_COPY( (char *)p->name, name, n ); - p->format = format; p->builtin = 0; p->value.atom = NULL; /* nothing is ever stored here */ @@ -1442,11 +1436,9 @@ goto Exit; } - if ( FT_QALLOC( p->glyph_name, slen + 1 ) ) + if ( FT_DUP( p->glyph_name, s, slen + 1 ) ) goto Exit; - FT_MEM_COPY( p->glyph_name, s, slen + 1 ); - p->flags |= BDF_GLYPH_; FT_TRACE4(( DBGMSG1, lineno, s )); @@ -2051,9 +2043,8 @@ /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */ FT_FREE( p->font->name ); - if ( FT_QALLOC( p->font->name, slen + 1 ) ) + if ( FT_DUP( p->font->name, s, slen + 1 ) ) goto Exit; - FT_MEM_COPY( p->font->name, s, slen + 1 ); /* If the font name is an XLFD name, set the spacing to the one in */ /* the font name. If there is no spacing fall back on the default. */ From 4ccdc9f98291fe40c2e32cc9914e327810d845ec Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 20 May 2024 18:53:57 -0400 Subject: [PATCH 41/60] [cff] Optimize the blend vector computations. * src/cff/cffload.c (cff_blend_build_vector): Use FT_MulDiv and skip multiplying by 1. --- src/cff/cffload.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/cff/cffload.c b/src/cff/cffload.c index a23fa4d12..d4f1ef5ff 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1495,44 +1495,41 @@ for ( j = 0; j < lenNDV; j++ ) { CFF_AxisCoords* axis = &varRegion->axisList[j]; - FT_Fixed axisScalar; /* compute the scalar contribution of this axis; */ /* ignore invalid ranges */ if ( axis->startCoord > axis->peakCoord || axis->peakCoord > axis->endCoord ) - axisScalar = FT_FIXED_ONE; + continue; else if ( axis->startCoord < 0 && axis->endCoord > 0 && axis->peakCoord != 0 ) - axisScalar = FT_FIXED_ONE; + continue; /* peak of 0 means ignore this axis */ else if ( axis->peakCoord == 0 ) - axisScalar = FT_FIXED_ONE; + continue; /* ignore this region if coords are out of range */ else if ( NDV[j] < axis->startCoord || NDV[j] > axis->endCoord ) - axisScalar = 0; - - /* calculate a proportional factor */ - else { - if ( NDV[j] == axis->peakCoord ) - axisScalar = FT_FIXED_ONE; - else if ( NDV[j] < axis->peakCoord ) - axisScalar = FT_DivFix( NDV[j] - axis->startCoord, - axis->peakCoord - axis->startCoord ); - else - axisScalar = FT_DivFix( axis->endCoord - NDV[j], - axis->endCoord - axis->peakCoord ); + blend->BV[master] = 0; + break; } - /* take product of all the axis scalars */ - blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar ); + /* adjust proportionally */ + else if ( NDV[j] < axis->peakCoord ) + blend->BV[master] = FT_MulDiv( blend->BV[master], + NDV[j] - axis->startCoord, + axis->peakCoord - axis->startCoord ); + + else if ( NDV[j] > axis->peakCoord ) + blend->BV[master] = FT_MulDiv( blend->BV[master], + axis->endCoord - NDV[j], + axis->endCoord - axis->peakCoord ); } FT_TRACE4(( ", %f ", From 39f2fbf80c5ab9ad7b380080395c987f4922a038 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 20 May 2024 22:47:14 -0400 Subject: [PATCH 42/60] * src/truetype/ttgxvar.c (tt_var_get_item_delta): Minor refactoring. --- src/truetype/ttgxvar.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 99a9d4db0..a2715860e 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1074,6 +1074,9 @@ /* inner loop steps through axes in this region */ for ( j = 0; j < itemStore->axisCount; j++, axis++ ) { + FT_Fixed ncv = ttface->blend->normalizedcoords[j]; + + /* compute the scalar contribution of this axis; */ /* ignore invalid ranges */ if ( axis->startCoord > axis->peakCoord || @@ -1089,28 +1092,23 @@ else if ( axis->peakCoord == 0 ) continue; - else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord ) - continue; - /* ignore this region if coords are out of range */ - else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord || - ttface->blend->normalizedcoords[j] >= axis->endCoord ) + else if ( ncv <= axis->startCoord || + ncv >= axis->endCoord ) { scalar = 0; break; } /* cumulative product of all the axis scalars */ - else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord ) - scalar = - FT_MulDiv( scalar, - ttface->blend->normalizedcoords[j] - axis->startCoord, - axis->peakCoord - axis->startCoord ); - else - scalar = - FT_MulDiv( scalar, - axis->endCoord - ttface->blend->normalizedcoords[j], - axis->endCoord - axis->peakCoord ); + else if ( ncv < axis->peakCoord ) + scalar = FT_MulDiv( scalar, + ncv - axis->startCoord, + axis->peakCoord - axis->startCoord ); + else if ( ncv > axis->peakCoord ) + scalar = FT_MulDiv( scalar, + axis->endCoord - ncv, + axis->endCoord - axis->peakCoord ); } /* per-axis loop */ From 347276c1f6dcbc0eed3f0880b3695167a91c205d Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 21 May 2024 13:12:45 +0000 Subject: [PATCH 43/60] * src/truetype/ttgxvar.c (tt_var_get_item_delta): Align with specs. --- src/truetype/ttgxvar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index a2715860e..886a90546 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1093,8 +1093,8 @@ continue; /* ignore this region if coords are out of range */ - else if ( ncv <= axis->startCoord || - ncv >= axis->endCoord ) + else if ( ncv < axis->startCoord || + ncv > axis->endCoord ) { scalar = 0; break; From 99be2b315425f51184f23fde2a3c12b528c6a612 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 21 May 2024 18:26:09 +0000 Subject: [PATCH 44/60] [cff, truetype] Rearrange variation range checks. This should achieve quicker results for common cases. * src/cff/cffload.c (cff_blend_build_vector): Rearrange conditionals. * src/truetype/ttgxvar.c (tt_var_get_item_delta): Ditto. --- src/cff/cffload.c | 22 ++++++++++------------ src/truetype/ttgxvar.c | 21 ++++++++++----------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/cff/cffload.c b/src/cff/cffload.c index d4f1ef5ff..01d78770b 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1497,24 +1497,23 @@ CFF_AxisCoords* axis = &varRegion->axisList[j]; - /* compute the scalar contribution of this axis; */ - /* ignore invalid ranges */ - if ( axis->startCoord > axis->peakCoord || - axis->peakCoord > axis->endCoord ) + /* compute the scalar contribution of this axis */ + /* while running mandatory range checks */ + if ( axis->peakCoord == NDV[j] || + axis->peakCoord == 0 ) continue; else if ( axis->startCoord < 0 && - axis->endCoord > 0 && - axis->peakCoord != 0 ) + axis->endCoord > 0 ) continue; - /* peak of 0 means ignore this axis */ - else if ( axis->peakCoord == 0 ) + else if ( axis->startCoord > axis->peakCoord || + axis->peakCoord > axis->endCoord ) continue; /* ignore this region if coords are out of range */ - else if ( NDV[j] < axis->startCoord || - NDV[j] > axis->endCoord ) + else if ( NDV[j] <= axis->startCoord || + NDV[j] >= axis->endCoord ) { blend->BV[master] = 0; break; @@ -1525,8 +1524,7 @@ blend->BV[master] = FT_MulDiv( blend->BV[master], NDV[j] - axis->startCoord, axis->peakCoord - axis->startCoord ); - - else if ( NDV[j] > axis->peakCoord ) + else /* NDV[j] > axis->peakCoord ) */ blend->BV[master] = FT_MulDiv( blend->BV[master], axis->endCoord - NDV[j], axis->endCoord - axis->peakCoord ); diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 886a90546..2e0cc7539 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1077,24 +1077,23 @@ FT_Fixed ncv = ttface->blend->normalizedcoords[j]; - /* compute the scalar contribution of this axis; */ - /* ignore invalid ranges */ - if ( axis->startCoord > axis->peakCoord || - axis->peakCoord > axis->endCoord ) + /* compute the scalar contribution of this axis */ + /* while running mandatory range checks */ + if ( axis->peakCoord == ncv || + axis->peakCoord == 0 ) continue; else if ( axis->startCoord < 0 && - axis->endCoord > 0 && - axis->peakCoord != 0 ) + axis->endCoord > 0 ) continue; - /* peak of 0 means ignore this axis */ - else if ( axis->peakCoord == 0 ) + else if ( axis->startCoord > axis->peakCoord || + axis->peakCoord > axis->endCoord ) continue; /* ignore this region if coords are out of range */ - else if ( ncv < axis->startCoord || - ncv > axis->endCoord ) + else if ( ncv <= axis->startCoord || + ncv >= axis->endCoord ) { scalar = 0; break; @@ -1105,7 +1104,7 @@ scalar = FT_MulDiv( scalar, ncv - axis->startCoord, axis->peakCoord - axis->startCoord ); - else if ( ncv > axis->peakCoord ) + else /* ncv > axis->peakCoord */ scalar = FT_MulDiv( scalar, axis->endCoord - ncv, axis->endCoord - axis->peakCoord ); From 5f131cfd20135ac5a1609854a1c2bde425741d3e Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 21 May 2024 16:24:43 -0400 Subject: [PATCH 45/60] [cff, truetype] Validate variation axes immediately. Instead of validating variation axes in every access, OpenType specs suggest that peak = 0 be used to tag invalid ranges. This implements just that once during loading. * src/cff/cffload.c (cff_blend_build_vector): Move the range checks... (cff_vstore_load): ... here. * src/truetype/ttgxvar.c (tt_var_get_item_delta): Ditto... (tt_var_load_item_variation_store): ... ditto. --- src/cff/cffload.c | 28 ++++++++++++---------------- src/truetype/ttgxvar.c | 16 ++++++---------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/cff/cffload.c b/src/cff/cffload.c index 01d78770b..979fd45f6 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1202,17 +1202,21 @@ { CFF_AxisCoords* axis = ®ion->axisList[j]; - FT_Int16 start14, peak14, end14; + FT_Int start, peak, end; - if ( FT_READ_SHORT( start14 ) || - FT_READ_SHORT( peak14 ) || - FT_READ_SHORT( end14 ) ) + if ( FT_READ_SHORT( start ) || + FT_READ_SHORT( peak ) || + FT_READ_SHORT( end ) ) goto Exit; - axis->startCoord = FT_fdot14ToFixed( start14 ); - axis->peakCoord = FT_fdot14ToFixed( peak14 ); - axis->endCoord = FT_fdot14ToFixed( end14 ); + /* immediately tag invalid ranges with special peak = 0 */ + if ( ( start < 0 && end > 0 ) || start > peak || peak > end ) + peak = 0; + + axis->startCoord = FT_fdot14ToFixed( start ); + axis->peakCoord = FT_fdot14ToFixed( peak ); + axis->endCoord = FT_fdot14ToFixed( end ); } } @@ -1498,19 +1502,11 @@ /* compute the scalar contribution of this axis */ - /* while running mandatory range checks */ + /* with peak of 0 used for invalid axes */ if ( axis->peakCoord == NDV[j] || axis->peakCoord == 0 ) continue; - else if ( axis->startCoord < 0 && - axis->endCoord > 0 ) - continue; - - else if ( axis->startCoord > axis->peakCoord || - axis->peakCoord > axis->endCoord ) - continue; - /* ignore this region if coords are out of range */ else if ( NDV[j] <= axis->startCoord || NDV[j] >= axis->endCoord ) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 2e0cc7539..205310d13 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -596,7 +596,7 @@ for ( j = 0; j < itemStore->axisCount; j++ ) { - FT_Short start, peak, end; + FT_Int start, peak, end; if ( FT_READ_SHORT( start ) || @@ -604,6 +604,10 @@ FT_READ_SHORT( end ) ) goto Exit; + /* immediately tag invalid ranges with special peak = 0 */ + if ( ( start < 0 && end > 0 ) || start > peak || peak > end ) + peak = 0; + axisCoords[j].startCoord = FT_fdot14ToFixed( start ); axisCoords[j].peakCoord = FT_fdot14ToFixed( peak ); axisCoords[j].endCoord = FT_fdot14ToFixed( end ); @@ -1078,19 +1082,11 @@ /* compute the scalar contribution of this axis */ - /* while running mandatory range checks */ + /* with peak of 0 used for invalid axes */ if ( axis->peakCoord == ncv || axis->peakCoord == 0 ) continue; - else if ( axis->startCoord < 0 && - axis->endCoord > 0 ) - continue; - - else if ( axis->startCoord > axis->peakCoord || - axis->peakCoord > axis->endCoord ) - continue; - /* ignore this region if coords are out of range */ else if ( ncv <= axis->startCoord || ncv >= axis->endCoord ) From 42d406ab04e7f8e626eaac26ea515a795891c3b3 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 22 May 2024 21:08:34 -0400 Subject: [PATCH 46/60] * include/freetype/internal/ftmemory.h (FT_MEM_DUP): Fix g++ error. --- include/freetype/internal/ftmemory.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/freetype/internal/ftmemory.h b/include/freetype/internal/ftmemory.h index 202cd0a7f..4e05a29f1 100644 --- a/include/freetype/internal/ftmemory.h +++ b/include/freetype/internal/ftmemory.h @@ -371,8 +371,11 @@ extern "C++" #define FT_STRDUP( dst, str ) \ FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) ) -#define FT_MEM_DUP( dst, address, size ) \ - (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error ) +#define FT_MEM_DUP( dst, address, size ) \ + FT_ASSIGNP_INNER( dst, ft_mem_dup( memory, \ + (address), \ + (FT_ULong)(size), \ + &error ) ) #define FT_DUP( dst, address, size ) \ FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) ) From a498873652fd5a36a18b8b692ea7f87b47d06e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexei=20Podtelezhnikov=20=28=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=B4=D1=82=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B6=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=29?= Date: Wed, 22 May 2024 22:17:50 -0400 Subject: [PATCH 47/60] * .gitlab-ci.yml: Disable UWP compilation. --- .gitlab-ci.yml | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index faa0cd48a..3592724e1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,17 +54,7 @@ variables: # Make sure meson is up to date so we don't need to rebuild the image # with each release. - pip3 install -U 'meson==0.59.*' - - pip3 install --upgrade certifi - pip3 install -U ninja - - # Generate a UWP cross-file in case it's used - - $PSDefaultParameterValues['Out-File:Encoding'] = 'ASCII' - - echo "[binaries]" > uwp-crossfile.meson - - echo "c = 'cl'" >> uwp-crossfile.meson - - echo "strip = ['true']" >> uwp-crossfile.meson - - echo "[built-in options]" >> uwp-crossfile.meson - - echo "c_args = ['-DWINAPI_FAMILY=WINAPI_FAMILY_APP', '-DUNICODE', '-D_WIN32_WINNT=0x0A00', '-we4013']" >> uwp-crossfile.meson - - echo "c_winlibs = ['windowsapp.lib']" >> uwp-crossfile.meson script: # For some reason, options are separated by newlines instead of spaces, # so we have to replace them first. @@ -75,10 +65,12 @@ variables: # script. Environment variables substitutions is done by PowerShell # before calling `cmd.exe`, that's why we use `$env:FOO` instead of # `%FOO%`. - - cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=$env:ARCH $env:VS_UWP && - meson setup build $env:MESON_ARGS_WINDOWS $env:MESON_ARGS_UWP && - meson compile --verbose -C build - $env:MESON_WINDOWS_TESTS" + - cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=$env:ARCH && + meson setup build $env:MESON_ARGS_WINDOWS && + meson compile --verbose -C build && + meson test -C build && + meson test -C build --benchmark" + .build windows msbuild: extends: '.build windows common' @@ -106,20 +98,11 @@ windows meson vs2019 amd64: extends: '.build windows meson' variables: ARCH: 'amd64' - MESON_WINDOWS_TESTS: '&& meson test -C build && meson test -C build --benchmark' windows meson vs2019 x86: extends: '.build windows meson' variables: ARCH: 'x86' - MESON_WINDOWS_TESTS: '&& meson test -C build && meson test -C build --benchmark' - -windows meson vs2019 amd64 uwp: - extends: '.build windows meson' - variables: - ARCH: 'amd64' - VS_UWP: '-app_platform=UWP' - MESON_ARGS_UWP: '--cross-file uwp-crossfile.meson -Dc_winlibs="windowsapp.lib"' windows msbuild vs2019 amd64: extends: '.build windows msbuild' From 9ff4153cbfd60491f11bb56905ce6e20e94d23c7 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 22 May 2024 23:38:34 -0400 Subject: [PATCH 48/60] [truetype] Reduce allocation scope. * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Reduce scope of `points_org` and 'points_out`. --- src/truetype/ttgxvar.c | 45 +++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 205310d13..0ca6cd678 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -4079,10 +4079,6 @@ FT_UInt glyph_index = loader->glyph_index; FT_UInt n_points = (FT_UInt)outline->n_points + 4; - FT_Vector* points_org = NULL; /* coordinates in 16.16 format */ - FT_Vector* points_out = NULL; /* coordinates in 16.16 format */ - FT_Bool* has_delta = NULL; - FT_ULong glyph_start; FT_UInt tupleCount; @@ -4129,17 +4125,12 @@ return FT_Err_Ok; } - if ( FT_NEW_ARRAY( points_org, n_points ) || - FT_NEW_ARRAY( points_out, n_points ) || - FT_NEW_ARRAY( has_delta, n_points ) ) - goto Fail1; - dataSize = blend->glyphoffsets[glyph_index + 1] - blend->glyphoffsets[glyph_index]; if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || FT_FRAME_ENTER( dataSize ) ) - goto Fail1; + return error; glyph_start = FT_Stream_FTell( stream ); @@ -4189,12 +4180,6 @@ FT_NEW_ARRAY( point_deltas_y, n_points ) ) goto Fail3; - for ( j = 0; j < n_points; j++ ) - { - points_org[j].x = FT_intToFixed( outline->points[j].x ); - points_org[j].y = FT_intToFixed( outline->points[j].y ); - } - for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) { FT_UInt tupleDataSize; @@ -4324,19 +4309,30 @@ else { + FT_Vector* points_org = NULL; /* coordinates in 16.16 format */ + FT_Vector* points_out = NULL; /* coordinates in 16.16 format */ + FT_Bool* has_delta = NULL; + #ifdef FT_DEBUG_LEVEL_TRACE int count = 0; #endif - /* we have to interpolate the missing deltas similar to the */ - /* IUP bytecode instruction */ + /* note that `has_delta` is set to FALSE, zeroed out */ + if ( FT_QNEW_ARRAY( points_org, n_points ) || + FT_QNEW_ARRAY( points_out, n_points ) || + FT_NEW_ARRAY( has_delta, n_points ) ) + goto Fail4; + for ( j = 0; j < n_points; j++ ) { - has_delta[j] = FALSE; - points_out[j] = points_org[j]; + points_org[j].x = FT_intToFixed( outline->points[j].x ); + points_org[j].y = FT_intToFixed( outline->points[j].y ); } + FT_ARRAY_COPY( points_out, points_org, n_points ); + /* we have to interpolate the missing deltas similar to the */ + /* IUP bytecode instruction */ for ( j = 0; j < point_count; j++ ) { FT_UShort idx = points[j]; @@ -4394,6 +4390,10 @@ if ( !count ) FT_TRACE7(( " none\n" )); #endif + Fail4: + FT_FREE( points_org ); + FT_FREE( points_out ); + FT_FREE( has_delta ); } if ( localpoints != ALL_POINTS ) @@ -4466,11 +4466,6 @@ FT_FRAME_EXIT(); - Fail1: - FT_FREE( points_org ); - FT_FREE( points_out ); - FT_FREE( has_delta ); - return error; } From 70299c924fc6782edf0249bd28ca234dcc9d7c2c Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Thu, 23 May 2024 22:50:32 -0400 Subject: [PATCH 49/60] Revert "[truetype] Reduce allocation scope." This reverts commit 9ff4153cbfd60491f11bb56905ce6e20e94d23c7. --- src/truetype/ttgxvar.c | 49 +++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 0ca6cd678..205310d13 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -4079,6 +4079,10 @@ FT_UInt glyph_index = loader->glyph_index; FT_UInt n_points = (FT_UInt)outline->n_points + 4; + FT_Vector* points_org = NULL; /* coordinates in 16.16 format */ + FT_Vector* points_out = NULL; /* coordinates in 16.16 format */ + FT_Bool* has_delta = NULL; + FT_ULong glyph_start; FT_UInt tupleCount; @@ -4125,12 +4129,17 @@ return FT_Err_Ok; } + if ( FT_NEW_ARRAY( points_org, n_points ) || + FT_NEW_ARRAY( points_out, n_points ) || + FT_NEW_ARRAY( has_delta, n_points ) ) + goto Fail1; + dataSize = blend->glyphoffsets[glyph_index + 1] - blend->glyphoffsets[glyph_index]; if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || FT_FRAME_ENTER( dataSize ) ) - return error; + goto Fail1; glyph_start = FT_Stream_FTell( stream ); @@ -4180,6 +4189,12 @@ FT_NEW_ARRAY( point_deltas_y, n_points ) ) goto Fail3; + for ( j = 0; j < n_points; j++ ) + { + points_org[j].x = FT_intToFixed( outline->points[j].x ); + points_org[j].y = FT_intToFixed( outline->points[j].y ); + } + for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) { FT_UInt tupleDataSize; @@ -4309,30 +4324,19 @@ else { - FT_Vector* points_org = NULL; /* coordinates in 16.16 format */ - FT_Vector* points_out = NULL; /* coordinates in 16.16 format */ - FT_Bool* has_delta = NULL; - #ifdef FT_DEBUG_LEVEL_TRACE int count = 0; #endif - /* note that `has_delta` is set to FALSE, zeroed out */ - if ( FT_QNEW_ARRAY( points_org, n_points ) || - FT_QNEW_ARRAY( points_out, n_points ) || - FT_NEW_ARRAY( has_delta, n_points ) ) - goto Fail4; - - for ( j = 0; j < n_points; j++ ) - { - points_org[j].x = FT_intToFixed( outline->points[j].x ); - points_org[j].y = FT_intToFixed( outline->points[j].y ); - } - FT_ARRAY_COPY( points_out, points_org, n_points ); - /* we have to interpolate the missing deltas similar to the */ /* IUP bytecode instruction */ + for ( j = 0; j < n_points; j++ ) + { + has_delta[j] = FALSE; + points_out[j] = points_org[j]; + } + for ( j = 0; j < point_count; j++ ) { FT_UShort idx = points[j]; @@ -4390,10 +4394,6 @@ if ( !count ) FT_TRACE7(( " none\n" )); #endif - Fail4: - FT_FREE( points_org ); - FT_FREE( points_out ); - FT_FREE( has_delta ); } if ( localpoints != ALL_POINTS ) @@ -4466,6 +4466,11 @@ FT_FRAME_EXIT(); + Fail1: + FT_FREE( points_org ); + FT_FREE( points_out ); + FT_FREE( has_delta ); + return error; } From b6dbbd963097afd9f90cc02f1c6c6d2b98ca4fd4 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 24 May 2024 17:38:14 +0000 Subject: [PATCH 50/60] * src/truetype/ttgxvar.c (ft_var_apply_tuple): Reduce checks. --- src/truetype/ttgxvar.c | 63 +++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 205310d13..8f2a9b807 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1913,60 +1913,55 @@ for ( i = 0; i < blend->num_axis; i++ ) { - FT_TRACE6(( " axis %d coordinate %.5f:\n", - i, (double)blend->normalizedcoords[i] / 65536 )); + FT_Fixed ncv = blend->normalizedcoords[i]; + + + FT_TRACE6(( " axis %d coordinate %.5f:\n", i, (double)ncv / 65536 )); /* It's not clear why (for intermediate tuples) we don't need */ /* to check against start/end -- the documentation says we don't. */ /* Similarly, it's unclear why we don't need to scale along the */ /* axis. */ - if ( tuple_coords[i] == 0 ) - { - FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); - continue; - } - - if ( blend->normalizedcoords[i] == 0 ) - { - FT_TRACE6(( " axis coordinate is zero, stop\n" )); - apply = 0; - break; - } - - if ( blend->normalizedcoords[i] == tuple_coords[i] ) - { + if ( tuple_coords[i] == ncv ) + { FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n", (double)tuple_coords[i] / 65536 )); /* `apply' does not change */ continue; } - if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) - { - /* not an intermediate tuple */ + if ( tuple_coords[i] == 0 ) + { + FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); + continue; + } - if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) || - blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) ) + if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) + { + /* not an intermediate tuple */ + + if ( ( tuple_coords[i] > ncv && ncv > 0 ) || + ( tuple_coords[i] < ncv && ncv < 0 ) ) + { + FT_TRACE6(( " tuple coordinate %.5f fits\n", + (double)tuple_coords[i] / 65536 )); + apply = FT_MulDiv( apply, ncv, tuple_coords[i] ); + } + else { FT_TRACE6(( " tuple coordinate %.5f is exceeded, stop\n", (double)tuple_coords[i] / 65536 )); apply = 0; break; } - - FT_TRACE6(( " tuple coordinate %.5f fits\n", - (double)tuple_coords[i] / 65536 )); - apply = FT_MulDiv( apply, - blend->normalizedcoords[i], - tuple_coords[i] ); } else { /* intermediate tuple */ - if ( blend->normalizedcoords[i] <= im_start_coords[i] || - blend->normalizedcoords[i] >= im_end_coords[i] ) + if ( ncv <= im_start_coords[i] || + ncv >= im_end_coords[i] ) { FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ is exceeded," " stop\n", @@ -1979,13 +1974,13 @@ FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ fits\n", (double)im_start_coords[i] / 65536, (double)im_end_coords[i] / 65536 )); - if ( blend->normalizedcoords[i] < tuple_coords[i] ) + if ( ncv < tuple_coords[i] ) apply = FT_MulDiv( apply, - blend->normalizedcoords[i] - im_start_coords[i], + ncv - im_start_coords[i], tuple_coords[i] - im_start_coords[i] ); - else + else /* ncv > tuple_coords[i] */ apply = FT_MulDiv( apply, - im_end_coords[i] - blend->normalizedcoords[i], + im_end_coords[i] - ncv, im_end_coords[i] - tuple_coords[i] ); } } From 3416ac16d09dcc20478906bd222b73d5375e4db1 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 26 May 2024 08:10:21 -0400 Subject: [PATCH 51/60] Whitespace. --- src/truetype/ttgxvar.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 8f2a9b807..a73dc719a 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1924,7 +1924,7 @@ /* axis. */ if ( tuple_coords[i] == ncv ) - { + { FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n", (double)tuple_coords[i] / 65536 )); /* `apply' does not change */ @@ -1932,18 +1932,18 @@ } if ( tuple_coords[i] == 0 ) - { + { FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); continue; } if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) - { + { /* not an intermediate tuple */ - + if ( ( tuple_coords[i] > ncv && ncv > 0 ) || ( tuple_coords[i] < ncv && ncv < 0 ) ) - { + { FT_TRACE6(( " tuple coordinate %.5f fits\n", (double)tuple_coords[i] / 65536 )); apply = FT_MulDiv( apply, ncv, tuple_coords[i] ); From 7ff43d3e9f981991048a459303e431bf0c617a36 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sun, 26 May 2024 19:40:20 -0400 Subject: [PATCH 52/60] [truetype/GX] Consolidate memory allocations. * src/truetype/ttgxvar.c (tt_face_vary_cvt, TT_Vary_Apply_Glyph_Deltas): Allocate and split bigger memory blocks, avoid unnecessary zeroing, do not copy shared tuples, revise error exit paths. --- src/truetype/ttgxvar.c | 151 +++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 90 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index a73dc719a..6ee667144 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -3521,9 +3521,10 @@ FT_ULong here; FT_UInt i, j; - FT_Fixed* tuple_coords = NULL; - FT_Fixed* im_start_coords = NULL; - FT_Fixed* im_end_coords = NULL; + FT_Fixed* peak_coords = NULL; + FT_Fixed* tuple_coords; + FT_Fixed* im_start_coords; + FT_Fixed* im_end_coords; GX_Blend blend = face->blend; @@ -3544,16 +3545,16 @@ { FT_TRACE2(( "\n" )); FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" )); - error = FT_Err_Ok; - goto Exit; + + return FT_Err_Ok; } if ( !face->cvt ) { FT_TRACE2(( "\n" )); FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" )); - error = FT_Err_Ok; - goto Exit; + + return FT_Err_Ok; } error = face->goto_table( face, TTAG_cvar, stream, &table_len ); @@ -3561,15 +3562,11 @@ { FT_TRACE2(( "is missing\n" )); - error = FT_Err_Ok; - goto Exit; + return FT_Err_Ok; } if ( FT_FRAME_ENTER( table_len ) ) - { - error = FT_Err_Ok; - goto Exit; - } + return FT_Err_Ok; table_start = FT_Stream_FTell( stream ); if ( FT_GET_LONG() != 0x00010000L ) @@ -3582,11 +3579,6 @@ FT_TRACE2(( "loaded\n" )); - if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) - goto FExit; - tupleCount = FT_GET_USHORT(); offsetToData = FT_GET_USHORT(); @@ -3622,8 +3614,12 @@ tupleCount & GX_TC_TUPLE_COUNT_MASK, ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); - if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) ) - goto FExit; + if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) || + FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) ) + goto Exit; + + im_start_coords = peak_coords + blend->num_axis; + im_end_coords = im_start_coords + blend->num_axis; for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) { @@ -3640,32 +3636,19 @@ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) { for ( j = 0; j < blend->num_axis; j++ ) - tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + tuple_coords = peak_coords; } - else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) + else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount ) + tuple_coords = blend->tuplecoords + + ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis; + else { FT_TRACE2(( "tt_face_vary_cvt:" " invalid tuple index\n" )); error = FT_THROW( Invalid_Table ); - goto FExit; - } - else - { - if ( !blend->tuplecoords ) - { - FT_TRACE2(( "tt_face_vary_cvt:" - " no valid tuple coordinates available\n" )); - - error = FT_THROW( Invalid_Table ); - goto FExit; - } - - FT_MEM_COPY( - tuple_coords, - blend->tuplecoords + - ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis, - blend->num_axis * sizeof ( FT_Fixed ) ); + goto Exit; } if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) @@ -3808,23 +3791,21 @@ for ( i = 0; i < face->cvt_size; i++ ) face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] ); - FExit: - FT_FRAME_EXIT(); - - Exit: - if ( sharedpoints != ALL_POINTS ) - FT_FREE( sharedpoints ); - FT_FREE( tuple_coords ); - FT_FREE( im_start_coords ); - FT_FREE( im_end_coords ); - FT_FREE( cvt_deltas ); - /* iterate over all FT_Size objects and set `cvt_ready' to -1 */ /* to trigger rescaling of all CVT values */ FT_List_Iterate( &root->sizes_list, tt_cvt_ready_iterator, NULL ); + Exit: + if ( sharedpoints != ALL_POINTS ) + FT_FREE( sharedpoints ); + FT_FREE( cvt_deltas ); + FT_FREE( peak_coords ); + + FExit: + FT_FRAME_EXIT(); + return error; #else /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ @@ -4087,9 +4068,10 @@ FT_ULong here; FT_UInt i, j; - FT_Fixed* tuple_coords = NULL; - FT_Fixed* im_start_coords = NULL; - FT_Fixed* im_end_coords = NULL; + FT_Fixed* peak_coords = NULL; + FT_Fixed* tuple_coords; + FT_Fixed* im_start_coords; + FT_Fixed* im_end_coords; GX_Blend blend = face->blend; @@ -4124,27 +4106,17 @@ return FT_Err_Ok; } - if ( FT_NEW_ARRAY( points_org, n_points ) || - FT_NEW_ARRAY( points_out, n_points ) || - FT_NEW_ARRAY( has_delta, n_points ) ) - goto Fail1; - dataSize = blend->glyphoffsets[glyph_index + 1] - blend->glyphoffsets[glyph_index]; if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || FT_FRAME_ENTER( dataSize ) ) - goto Fail1; + return error; glyph_start = FT_Stream_FTell( stream ); /* each set of glyph variation data is formatted similarly to `cvar' */ - if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) - goto Fail2; - tupleCount = FT_GET_USHORT(); offsetToData = FT_GET_USHORT(); @@ -4156,7 +4128,7 @@ " invalid glyph variation array header\n" )); error = FT_THROW( Invalid_Table ); - goto Fail2; + goto FExit; } offsetToData += glyph_start; @@ -4180,9 +4152,16 @@ tupleCount & GX_TC_TUPLE_COUNT_MASK, ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); - if ( FT_NEW_ARRAY( point_deltas_x, n_points ) || - FT_NEW_ARRAY( point_deltas_y, n_points ) ) - goto Fail3; + if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) || + FT_NEW_ARRAY( point_deltas_x, 2 * n_points ) || + FT_QNEW_ARRAY( points_org, n_points ) || + FT_QNEW_ARRAY( points_out, n_points ) || + FT_QNEW_ARRAY( has_delta, n_points ) ) + goto Exit; + + im_start_coords = peak_coords + blend->num_axis; + im_end_coords = im_start_coords + blend->num_axis; + point_deltas_y = point_deltas_x + n_points; for ( j = 0; j < n_points; j++ ) { @@ -4205,22 +4184,20 @@ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) { for ( j = 0; j < blend->num_axis; j++ ) - tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + tuple_coords = peak_coords; } - else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) + else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount ) + tuple_coords = blend->tuplecoords + + ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis; + else { FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" " invalid tuple index\n" )); error = FT_THROW( Invalid_Table ); - goto Fail3; + goto Exit; } - else - FT_MEM_COPY( - tuple_coords, - blend->tuplecoords + - ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis, - blend->num_axis * sizeof ( FT_Fixed ) ); if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) { @@ -4448,23 +4425,17 @@ unrounded[n_points - 2].y ) / 64; } - Fail3: - FT_FREE( point_deltas_x ); - FT_FREE( point_deltas_y ); - - Fail2: + Exit: if ( sharedpoints != ALL_POINTS ) FT_FREE( sharedpoints ); - FT_FREE( tuple_coords ); - FT_FREE( im_start_coords ); - FT_FREE( im_end_coords ); - - FT_FRAME_EXIT(); - - Fail1: FT_FREE( points_org ); FT_FREE( points_out ); FT_FREE( has_delta ); + FT_FREE( peak_coords ); + FT_FREE( point_deltas_x ); + + FExit: + FT_FRAME_EXIT(); return error; } From d41a855aab6d8ce131c465ce01f0f536e0fb2269 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Wed, 29 May 2024 17:01:29 -0400 Subject: [PATCH 53/60] [ttgxvar] Replace tabs with spaces Also clarify comments around conversion and clamping. * src/truetype/ttgxvar.c (ft_var_to_normalized): doit --- src/truetype/ttgxvar.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 6ee667144..7d67d5f8d 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -2129,12 +2129,12 @@ outerIndex, innerIndex ); - /* Convert to 16.16 format before adding. */ - v += MUL_INT( delta, 4 ); + /* Convert delta in F2DOT14 to 16.16 before adding. */ + v += MUL_INT( delta, 4 ); - /* Clamp value range. */ - v = v >= 0x10000L ? 0x10000 : v; - v = v <= -0x10000L ? -0x10000 : v; + /* Clamp value range [-1, 1]. */ + v = v >= 0x10000L ? 0x10000 : v; + v = v <= -0x10000L ? -0x10000 : v; new_normalized[i] = v; } From deba7feb579ff8122f15fa2eedc89348ae79922d Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 18 Jun 2024 14:01:58 +0000 Subject: [PATCH 54/60] * include/freetype/ftimage.h: Explain standard types. --- include/freetype/ftimage.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h index 9d7f6b77d..7d4a99f38 100644 --- a/include/freetype/ftimage.h +++ b/include/freetype/ftimage.h @@ -21,6 +21,10 @@ * Note: A 'raster' is simply a scan-line converter, used to render * `FT_Outline`s into `FT_Bitmap`s. * + * Note: This file can be used for STANDALONE_ compilation of raster (B/W) + * and smooth (anti-aliased) renderers. Therefore, it must rely on + * standard variable types only rather than aliases in fttypes.h. + * */ From 93a067e31240058103ce04057dd76dcf98c18d15 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 18 Jun 2024 17:48:41 +0000 Subject: [PATCH 55/60] [base, autofit, psaux] Remove unnecessary casting. * src/autofit/afhints.c (af_glyph_hints_reload): Remove (short) casting. * src/base/ftgloadr.c (FT_GlyphLoader_Add): Ditto. * src/psaux/psobjs.c ({t1,cff,ps}_builder_{add,close}_contour): Ditto. --- src/autofit/afhints.c | 4 ++-- src/base/ftgloadr.c | 22 ++++++---------------- src/psaux/psobjs.c | 18 ++++++------------ 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index 27d7bc1a9..099a5f82a 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -1049,13 +1049,13 @@ AF_Point* contour = hints->contours; AF_Point* contour_limit = contour + hints->num_contours; short* end = outline->contours; - short idx = 0; + FT_Int idx = 0; for ( ; contour < contour_limit; contour++, end++ ) { contour[0] = points + idx; - idx = (short)( end[0] + 1 ); + idx = *end + 1; } } diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c index e0c107f47..4d94c3d5d 100644 --- a/src/base/ftgloadr.c +++ b/src/base/ftgloadr.c @@ -357,9 +357,6 @@ { FT_GlyphLoad base; FT_GlyphLoad current; - - FT_Int n_curr_contours; - FT_Int n_base_points; FT_Int n; @@ -369,20 +366,13 @@ base = &loader->base; current = &loader->current; - n_curr_contours = current->outline.n_contours; - n_base_points = base->outline.n_points; - - base->outline.n_points = - (short)( base->outline.n_points + current->outline.n_points ); - base->outline.n_contours = - (short)( base->outline.n_contours + current->outline.n_contours ); - - base->num_subglyphs += current->num_subglyphs; - /* adjust contours count in newest outline */ - for ( n = 0; n < n_curr_contours; n++ ) - current->outline.contours[n] = - (short)( current->outline.contours[n] + n_base_points ); + for ( n = 0; n < current->outline.n_contours; n++ ) + current->outline.contours[n] += base->outline.n_points; + + base->outline.n_points += current->outline.n_points; + base->outline.n_contours += current->outline.n_contours; + base->num_subglyphs += current->num_subglyphs; /* prepare for another new glyph image */ FT_GlyphLoader_Prepare( loader ); diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c index b251b3596..d3a61fd64 100644 --- a/src/psaux/psobjs.c +++ b/src/psaux/psobjs.c @@ -1677,8 +1677,7 @@ if ( !error ) { if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } @@ -1760,8 +1759,7 @@ outline->n_points--; } else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; } } @@ -1959,8 +1957,7 @@ if ( !error ) { if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } @@ -2039,8 +2036,7 @@ outline->n_points--; } else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; } } @@ -2267,8 +2263,7 @@ if ( !error ) { if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } @@ -2347,8 +2342,7 @@ outline->n_points--; } else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; } } From 7a753c9653d91dbf57d96935811e164a963b0669 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 18 Jun 2024 21:14:58 -0400 Subject: [PATCH 56/60] * src/base/ftgloadr.c (FT_GlyphLoader_Prepare): Minor refactoring. --- src/base/ftgloadr.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c index 4d94c3d5d..484d98f17 100644 --- a/src/base/ftgloadr.c +++ b/src/base/ftgloadr.c @@ -355,24 +355,25 @@ FT_BASE_DEF( void ) FT_GlyphLoader_Add( FT_GlyphLoader loader ) { - FT_GlyphLoad base; - FT_GlyphLoad current; - FT_Int n; + FT_Outline* base; + FT_Outline* current; + FT_Int n; if ( !loader ) return; - base = &loader->base; - current = &loader->current; + base = &loader->base.outline; + current = &loader->current.outline; /* adjust contours count in newest outline */ - for ( n = 0; n < current->outline.n_contours; n++ ) - current->outline.contours[n] += base->outline.n_points; + for ( n = 0; n < current->n_contours; n++ ) + current->contours[n] += base->n_points; - base->outline.n_points += current->outline.n_points; - base->outline.n_contours += current->outline.n_contours; - base->num_subglyphs += current->num_subglyphs; + base->n_points += current->n_points; + base->n_contours += current->n_contours; + + loader->base.num_subglyphs += loader->current.num_subglyphs; /* prepare for another new glyph image */ FT_GlyphLoader_Prepare( loader ); From 2b9fdec5fafd16fba93a9947563260ab9feb9029 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 19 Jun 2024 21:38:58 -0400 Subject: [PATCH 57/60] * src/pfr/pfrgload.c (pfr_glyph_curve_to): Avoid casting. --- src/pfr/pfrgload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pfr/pfrgload.c b/src/pfr/pfrgload.c index 6216cf169..8ad65ec9d 100644 --- a/src/pfr/pfrgload.c +++ b/src/pfr/pfrgload.c @@ -189,7 +189,7 @@ tag[1] = FT_CURVE_TAG_CUBIC; tag[2] = FT_CURVE_TAG_ON; - outline->n_points = (FT_Short)( outline->n_points + 3 ); + outline->n_points += 3; } Exit: From 2a7bb4596f566a34fd53932af0ef53b956459d25 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Thu, 20 Jun 2024 20:49:56 -0400 Subject: [PATCH 58/60] Use unsigned point and contour indexing in `FT_Outline`. This doubles the number or allowed points, see https://github.com/harfbuzz/harfbuzz/issues/4752 Although it is hardly practical to use more than 32767 points, other font engines seem to support it. * docs/CHANGES: Announce it. * include/freetype/ftimage.h (FT_Outline): Do it and update limits. * src/*: Update `FT_Outline` users. --- docs/CHANGES | 12 ++++++++++-- include/freetype/ftimage.h | 16 ++++++++-------- include/freetype/internal/tttypes.h | 4 ++-- src/autofit/afhints.c | 10 +++++----- src/base/ftbbox.c | 2 +- src/base/ftoutln.c | 8 +++++--- src/base/ftstroke.c | 10 +++++----- src/pfr/pfrgload.c | 2 +- src/pshinter/pshalgo.c | 6 +++--- src/raster/ftraster.c | 2 +- src/sdf/ftsdf.c | 2 +- src/smooth/ftgrays.c | 2 +- src/truetype/ttgload.c | 29 ++++++++++++++--------------- src/truetype/ttinterp.c | 14 ++++++-------- src/truetype/ttobjs.c | 2 +- src/truetype/ttobjs.h | 2 +- 16 files changed, 65 insertions(+), 58 deletions(-) diff --git a/docs/CHANGES b/docs/CHANGES index fc18eb10a..4c98128f8 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -1,13 +1,21 @@ CHANGES BETWEEN 2.13.2 and 2.13.3 (2024-Mmm-DD) - I. IMPORTANT BUG FIXES + I. IMPORTANT CHANGES + + - Some fields in the `FT_Outline` structure have been changed + from signed to unsigned type, which better reflects the actual + usage. It is also an additional means to protect against + malformed input. + + + II. IMPORTANT BUG FIXES - Rare double-free crashes in the cache subsystem have been fixed. - Excessive stack allocation in the autohinter has been fixed. - II. MISCELLANEOUS + III. MISCELLANEOUS - The B/W rasterizer has received a major upkeep that resulted in large performance improvement. The rendering speed has increased diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h index 7d4a99f38..6795a8ed0 100644 --- a/include/freetype/ftimage.h +++ b/include/freetype/ftimage.h @@ -345,14 +345,14 @@ FT_BEGIN_HEADER */ typedef struct FT_Outline_ { - short n_contours; /* number of contours in glyph */ - short n_points; /* number of points in the glyph */ + unsigned short n_contours; /* number of contours in glyph */ + unsigned short n_points; /* number of points in the glyph */ - FT_Vector* points; /* the outline's points */ - char* tags; /* the points flags */ - short* contours; /* the contour end points */ + FT_Vector* points; /* the outline's points */ + char* tags; /* the points flags */ + unsigned short* contours; /* the contour end points */ - int flags; /* outline masks */ + int flags; /* outline masks */ } FT_Outline; @@ -360,8 +360,8 @@ FT_BEGIN_HEADER /* Following limits must be consistent with */ /* FT_Outline.{n_contours,n_points} */ -#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX -#define FT_OUTLINE_POINTS_MAX SHRT_MAX +#define FT_OUTLINE_CONTOURS_MAX USHRT_MAX +#define FT_OUTLINE_POINTS_MAX USHRT_MAX /************************************************************************** diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 44a0165cc..7053e656a 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -1655,9 +1655,9 @@ FT_BEGIN_HEADER { FT_Memory memory; FT_UShort max_points; - FT_Short max_contours; + FT_UShort max_contours; FT_UShort n_points; /* number of points in zone */ - FT_Short n_contours; /* number of contours */ + FT_UShort n_contours; /* number of contours */ FT_Vector* org; /* original point coordinates */ FT_Vector* cur; /* current point coordinates */ diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index 099a5f82a..6b48bc598 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -980,7 +980,7 @@ { FT_Vector* vec = outline->points; char* tag = outline->tags; - FT_Short endpoint = outline->contours[0]; + FT_UShort endpoint = outline->contours[0]; AF_Point end = points + endpoint; AF_Point prev = end; FT_Int contour_index = 0; @@ -1046,10 +1046,10 @@ /* set up the contours array */ { - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - short* end = outline->contours; - FT_Int idx = 0; + AF_Point* contour = hints->contours; + AF_Point* contour_limit = contour + hints->num_contours; + FT_UShort* end = outline->contours; + FT_Int idx = 0; for ( ; contour < contour_limit; contour++, end++ ) diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c index e98c29fc7..d6aa5d56d 100644 --- a/src/base/ftbbox.c +++ b/src/base/ftbbox.c @@ -489,7 +489,7 @@ return FT_THROW( Invalid_Outline ); /* if outline is empty, return (0,0,0,0) */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) { abbox->xMin = abbox->xMax = 0; abbox->yMin = abbox->yMax = 0; diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index c7564dbd3..dc242e3f8 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -332,8 +332,8 @@ FT_NEW_ARRAY( anoutline->contours, numContours ) ) goto Fail; - anoutline->n_points = (FT_Short)numPoints; - anoutline->n_contours = (FT_Short)numContours; + anoutline->n_points = (FT_UShort)numPoints; + anoutline->n_contours = (FT_UShort)numContours; anoutline->flags |= FT_OUTLINE_OWNER; return FT_Err_Ok; @@ -359,12 +359,14 @@ FT_Int n; + FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n", + n_contours, n_points )); /* empty glyph? */ if ( n_points == 0 && n_contours == 0 ) return FT_Err_Ok; /* check point and contour counts */ - if ( n_points <= 0 || n_contours <= 0 ) + if ( n_points == 0 || n_contours == 0 ) goto Bad; end0 = -1; diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c index 443b48aaf..21fa0d425 100644 --- a/src/base/ftstroke.c +++ b/src/base/ftstroke.c @@ -727,10 +727,10 @@ /* copy contours */ { - FT_UInt count = border->num_points; - FT_Byte* tags = border->tags; - FT_Short* write = outline->contours + outline->n_contours; - FT_Short idx = (FT_Short)outline->n_points; + FT_UInt count = border->num_points; + FT_Byte* tags = border->tags; + FT_UShort* write = outline->contours + outline->n_contours; + FT_UShort idx = outline->n_points; for ( ; count > 0; count--, tags++, idx++ ) @@ -743,7 +743,7 @@ } } - outline->n_points += (short)border->num_points; + outline->n_points += (FT_UShort)border->num_points; FT_ASSERT( FT_Outline_Check( outline ) == 0 ); } diff --git a/src/pfr/pfrgload.c b/src/pfr/pfrgload.c index 8ad65ec9d..ec0a87893 100644 --- a/src/pfr/pfrgload.c +++ b/src/pfr/pfrgload.c @@ -108,7 +108,7 @@ /* don't add empty contours */ if ( last >= first ) - outline->contours[outline->n_contours++] = (short)last; + outline->contours[outline->n_contours++] = (FT_UShort)last; glyph->path_begun = 0; } diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c index 2d7b9c227..18695936c 100644 --- a/src/pshinter/pshalgo.c +++ b/src/pshinter/pshalgo.c @@ -1171,8 +1171,8 @@ FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) ) goto Exit; - glyph->num_points = (FT_UInt)outline->n_points; - glyph->num_contours = (FT_UInt)outline->n_contours; + glyph->num_points = outline->n_points; + glyph->num_contours = outline->n_contours; { FT_UInt first = 0, next, n; @@ -1186,7 +1186,7 @@ PSH_Point point; - next = (FT_UInt)outline->contours[n] + 1; + next = outline->contours[n] + 1; count = next - first; contour->start = points + first; diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c index 51ad66b60..02c2d63ec 100644 --- a/src/raster/ftraster.c +++ b/src/raster/ftraster.c @@ -2683,7 +2683,7 @@ return FT_THROW( Invalid_Outline ); /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) return Raster_Err_Ok; if ( !outline->contours || !outline->points ) diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c index 4394001e2..dc55d4263 100644 --- a/src/sdf/ftsdf.c +++ b/src/sdf/ftsdf.c @@ -3837,7 +3837,7 @@ } /* if the outline is empty, return */ - if ( outline->n_points <= 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) goto Exit; /* check whether the outline has valid fields */ diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index f011e9f8d..b7c0632a6 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -1981,7 +1981,7 @@ typedef ptrdiff_t FT_PtrDist; return FT_THROW( Invalid_Outline ); /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) return Smooth_Err_Ok; if ( !outline->contours || !outline->points ) diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index b7d8e1d66..e6806b0cb 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -353,7 +353,8 @@ FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x, y; - FT_Short *cont, *cont_limit, last; + FT_UShort *cont, *cont_limit; + FT_Int last; /* check that we can add the contours to the glyph */ @@ -372,7 +373,7 @@ last = -1; for ( ; cont < cont_limit; cont++ ) { - *cont = FT_NEXT_SHORT( p ); + *cont = FT_NEXT_USHORT( p ); if ( *cont <= last ) goto Invalid_Outline; @@ -530,8 +531,8 @@ *flag = (FT_Byte)( f & ON_CURVE_POINT ); } - outline->n_points = (FT_Short)n_points; - outline->n_contours = (FT_Short)n_contours; + outline->n_points = (FT_UShort)n_points; + outline->n_contours = (FT_UShort)n_contours; load->cursor = p; @@ -752,10 +753,8 @@ FT_UInt start_point, FT_UInt start_contour ) { - zone->n_points = (FT_UShort)load->outline.n_points + 4 - - (FT_UShort)start_point; - zone->n_contours = load->outline.n_contours - - (FT_Short)start_contour; + zone->n_points = load->outline.n_points + 4 - (FT_UShort)start_point; + zone->n_contours = load->outline.n_contours - (FT_UShort)start_contour; zone->org = load->extra_points + start_point; zone->cur = load->outline.points + start_point; zone->orus = load->extra_points2 + start_point; @@ -1044,7 +1043,7 @@ current.points = gloader->base.outline.points + num_base_points; current.n_points = gloader->base.outline.n_points - - (short)num_base_points; + (FT_UShort)num_base_points; have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | WE_HAVE_AN_XY_SCALE | @@ -1057,7 +1056,7 @@ /* get offset */ if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) { - FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points; + FT_UInt num_points = gloader->base.outline.n_points; FT_UInt k = (FT_UInt)subglyph->arg1; FT_UInt l = (FT_UInt)subglyph->arg2; FT_Vector* p1; @@ -1719,8 +1718,8 @@ FT_List_Add( &loader->composites, node ); } - start_point = (FT_UInt)gloader->base.outline.n_points; - start_contour = (FT_UInt)gloader->base.outline.n_contours; + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; /* for each subglyph, read composite header */ error = face->read_composite_glyph( loader ); @@ -1872,7 +1871,7 @@ linear_hadvance = loader->linear; linear_vadvance = loader->vadvance; - num_base_points = (FT_UInt)gloader->base.outline.n_points; + num_base_points = gloader->base.outline.n_points; error = load_truetype_glyph( loader, (FT_UInt)subglyph->index, @@ -1896,7 +1895,7 @@ loader->vadvance = linear_vadvance; } - num_points = (FT_UInt)gloader->base.outline.n_points; + num_points = gloader->base.outline.n_points; if ( num_points == num_base_points ) continue; @@ -2717,7 +2716,7 @@ size->metrics->y_ppem < 24 ) glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - FT_TRACE1(( " subglyphs = %u, contours = %hd, points = %hd," + FT_TRACE1(( " subglyphs = %u, contours = %hu, points = %hu," " flags = 0x%.3x\n", loader.gloader->base.num_subglyphs, glyph->outline.n_contours, diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 0889c6151..951891dbf 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -5270,11 +5270,11 @@ FT_UShort refp; FT_F26Dot6 dx, dy; - FT_Short contour, bounds; + FT_UShort contour, bounds; FT_UShort start, limit, i; - contour = (FT_Short)args[0]; + contour = (FT_UShort)args[0]; bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours; if ( BOUNDS( contour, bounds ) ) @@ -5290,15 +5290,13 @@ if ( contour == 0 ) start = 0; else - start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 - - exc->zp2.first_point ); + start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point; /* we use the number of points if in the twilight zone */ if ( exc->GS.gep2 == 0 ) limit = exc->zp2.n_points; else - limit = (FT_UShort)( exc->zp2.contours[contour] - - exc->zp2.first_point + 1 ); + limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point; for ( i = start; i < limit; i++ ) { @@ -5341,9 +5339,9 @@ /* Normal zone's `n_points' includes phantoms, so must */ /* use end of last contour. */ if ( exc->GS.gep2 == 0 ) - limit = (FT_UShort)exc->zp2.n_points; + limit = exc->zp2.n_points; else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 ) - limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 ); + limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1; else limit = 0; diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index 05489d732..08aee62a8 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -115,7 +115,7 @@ FT_LOCAL_DEF( FT_Error ) tt_glyphzone_new( FT_Memory memory, FT_UShort maxPoints, - FT_Short maxContours, + FT_UShort maxContours, TT_GlyphZone zone ) { FT_Error error; diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h index 0a63e6729..9c36ca783 100644 --- a/src/truetype/ttobjs.h +++ b/src/truetype/ttobjs.h @@ -105,7 +105,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) tt_glyphzone_new( FT_Memory memory, FT_UShort maxPoints, - FT_Short maxContours, + FT_UShort maxContours, TT_GlyphZone zone ); #endif /* TT_USE_BYTECODE_INTERPRETER */ From b1cbcb20454e3b465b0d3ea4d5457975cfa747e7 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Thu, 20 Jun 2024 15:00:20 -0400 Subject: [PATCH 59/60] [ttgxvar] Avoid "applying zero offset to null pointer" In C it is undefined behavior to do arithmetic on a null pointer, including adding zero. When using NotoSansKhmer[wdth,wght].ttf UBSAN produces a report like ttgxvar.c:1052:31: runtime error: applying zero offset to null pointer when adding zero to `varData->deltaSet` (which is null) to produce `bytes`. Protect against all the potential issues of this kind by returning early if `varData->regionIdxCount == 0`. * src/truetype/ttgxvar.c (tt_var_get_item_delta): early return on no regions --- src/truetype/ttgxvar.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 7d67d5f8d..095a72055 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1028,6 +1028,9 @@ if ( innerIndex >= varData->itemCount ) return 0; /* Out of range. */ + if ( varData->regionIdxCount == 0 ) + return 0; /* Avoid "applying zero offset to null pointer". */ + if ( varData->regionIdxCount < 16 ) { deltaSet = deltaSetStack; From 044d142be7b6a93b6940367a1bc5847451ff4775 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Thu, 20 Jun 2024 22:16:51 -0400 Subject: [PATCH 60/60] Use unsigned tags `FT_Outline`. This change comes along with 2a7bb4596f56 ans is only meant to reduce pointer casting in the code. * include/freetype/ftimage.h (FT_Outline): Do it. * src/*: Update `FT_Outline` users. --- include/freetype/ftimage.h | 2 +- src/autofit/afhints.c | 4 ++-- src/base/ftoutln.c | 8 ++++---- src/base/ftstroke.c | 4 ++-- src/pfr/pfrgload.c | 4 ++-- src/psaux/psobjs.c | 12 ++++++------ src/pshinter/pshalgo.c | 2 +- src/raster/ftraster.c | 2 +- src/truetype/ttgload.c | 10 +++++----- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h index 6795a8ed0..6c7085f61 100644 --- a/include/freetype/ftimage.h +++ b/include/freetype/ftimage.h @@ -349,7 +349,7 @@ FT_BEGIN_HEADER unsigned short n_points; /* number of points in the glyph */ FT_Vector* points; /* the outline's points */ - char* tags; /* the points flags */ + unsigned char* tags; /* the points flags */ unsigned short* contours; /* the contour end points */ int flags; /* outline masks */ diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index 6b48bc598..96ffe343a 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -979,7 +979,7 @@ /* compute coordinates & Bezier flags, next and prev */ { FT_Vector* vec = outline->points; - char* tag = outline->tags; + FT_Byte* tag = outline->tags; FT_UShort endpoint = outline->contours[0]; AF_Point end = points + endpoint; AF_Point prev = end; @@ -1292,7 +1292,7 @@ AF_Point point = hints->points; AF_Point limit = point + hints->num_points; FT_Vector* vec = outline->points; - char* tag = outline->tags; + FT_Byte* tag = outline->tags; for ( ; point < limit; point++, vec++, tag++ ) diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index dc242e3f8..ef699b3c7 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -53,7 +53,7 @@ FT_Vector* point; FT_Vector* limit; - char* tags; + FT_Byte* tags; FT_Error error; @@ -578,13 +578,13 @@ /* reverse tags table */ { - char* p = outline->tags + first; - char* q = outline->tags + last; + FT_Byte* p = outline->tags + first; + FT_Byte* q = outline->tags + last; while ( p < q ) { - char swap; + FT_Byte swap; swap = *p; diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c index 21fa0d425..64f46ce43 100644 --- a/src/base/ftstroke.c +++ b/src/base/ftstroke.c @@ -711,7 +711,7 @@ { FT_UInt count = border->num_points; FT_Byte* read = border->tags; - FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* write = outline->tags + outline->n_points; for ( ; count > 0; count--, read++, write++ ) @@ -2050,7 +2050,7 @@ FT_Vector* point; FT_Vector* limit; - char* tags; + FT_Byte* tags; FT_Error error; diff --git a/src/pfr/pfrgload.c b/src/pfr/pfrgload.c index ec0a87893..e85007552 100644 --- a/src/pfr/pfrgload.c +++ b/src/pfr/pfrgload.c @@ -178,8 +178,8 @@ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 ); if ( !error ) { - FT_Vector* vec = outline->points + outline->n_points; - FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points; + FT_Vector* vec = outline->points + outline->n_points; + FT_Byte* tag = outline->tags + outline->n_points; vec[0] = *control1; diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c index d3a61fd64..b361d7077 100644 --- a/src/psaux/psobjs.c +++ b/src/psaux/psobjs.c @@ -1624,7 +1624,7 @@ if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* control = outline->tags + outline->n_points; point->x = FIXED_TO_INT( x ); @@ -1739,7 +1739,7 @@ { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + FT_Byte* control = outline->tags + outline->n_points - 1; /* `delete' last point only if it coincides with the first */ @@ -1897,7 +1897,7 @@ if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* control = outline->tags + outline->n_points; #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); @@ -2016,7 +2016,7 @@ { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + FT_Byte* control = outline->tags + outline->n_points - 1; /* `delete' last point only if it coincides with the first */ @@ -2184,7 +2184,7 @@ if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* control = outline->tags + outline->n_points; #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); @@ -2322,7 +2322,7 @@ { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + FT_Byte* control = outline->tags + outline->n_points - 1; /* `delete' last point only if it coincides with the first */ diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c index 18695936c..967767b34 100644 --- a/src/pshinter/pshalgo.c +++ b/src/pshinter/pshalgo.c @@ -1118,7 +1118,7 @@ FT_UInt n; PSH_Point point = glyph->points; FT_Vector* vec = glyph->outline->points; - char* tags = glyph->outline->tags; + FT_Byte* tags = glyph->outline->tags; for ( n = 0; n < glyph->num_points; n++ ) diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c index 02c2d63ec..e4b7b937d 100644 --- a/src/raster/ftraster.c +++ b/src/raster/ftraster.c @@ -1598,7 +1598,7 @@ FT_Vector* points; FT_Vector* point; FT_Vector* limit; - char* tags; + FT_Byte* tags; UInt tag; /* current point's state */ diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index e6806b0cb..8cddc394c 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -431,7 +431,7 @@ p += n_ins; /* reading the point tags */ - flag = (FT_Byte*)outline->tags; + flag = outline->tags; flag_limit = flag + n_points; FT_ASSERT( flag ); @@ -464,7 +464,7 @@ vec = outline->points; vec_limit = vec + n_points; - flag = (FT_Byte*)outline->tags; + flag = outline->tags; x = 0; for ( ; vec < vec_limit; vec++, flag++ ) @@ -498,7 +498,7 @@ vec = outline->points; vec_limit = vec + n_points; - flag = (FT_Byte*)outline->tags; + flag = outline->tags; y = 0; for ( ; vec < vec_limit; vec++, flag++ ) @@ -758,8 +758,8 @@ zone->org = load->extra_points + start_point; zone->cur = load->outline.points + start_point; zone->orus = load->extra_points2 + start_point; - zone->tags = (FT_Byte*)load->outline.tags + start_point; - zone->contours = (FT_UShort*)load->outline.contours + start_contour; + zone->tags = load->outline.tags + start_point; + zone->contours = load->outline.contours + start_contour; zone->first_point = (FT_UShort)start_point; }