From 811c19939bf16c3a83aba2628ad72655d2f27911 Mon Sep 17 00:00:00 2001 From: halx99 Date: Wed, 13 May 2026 16:52:47 +0800 Subject: [PATCH] Update freetype to 2.14.3-c39ca391 for resolve hvfload issue --- 3rdparty/README.md | 3 +- 3rdparty/freetype/devel/ftoption.h | 6 +- .../include/freetype/config/ftoption.h | 6 +- 3rdparty/freetype/include/freetype/ftmoderr.h | 1 + 3rdparty/freetype/include/freetype/fttypes.h | 2 - 3rdparty/freetype/src/base/ftbitmap.c | 261 ++++++++---------- 3rdparty/freetype/src/base/ftobjs.c | 169 ++++++------ 3rdparty/freetype/src/hvf/hvfload.c | 149 ++++++---- 3rdparty/freetype/src/hvf/hvfobjs.c | 6 +- 3rdparty/freetype/src/hvf/hvfobjs.h | 2 - 3rdparty/freetype/src/psaux/psintrp.c | 23 +- 3rdparty/freetype/src/psaux/psstack.c | 13 +- 3rdparty/freetype/src/raster/ftraster.c | 38 ++- 3rdparty/freetype/src/sfnt/ttsbit.c | 14 +- 3rdparty/freetype/src/smooth/ftgrays.c | 168 ++++++----- 3rdparty/freetype/src/truetype/ttgload.c | 17 +- 3rdparty/freetype/src/truetype/ttgxvar.c | 44 ++- 3rdparty/freetype/src/truetype/ttinterp.c | 192 ++++++------- 18 files changed, 566 insertions(+), 548 deletions(-) diff --git a/3rdparty/README.md b/3rdparty/README.md index 6f83085d2b6b..864507b3b1ae 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -67,9 +67,8 @@ ## FreeType - [![Upstream](https://img.shields.io/gitlab/v/tag/freetype/freetype?label=Upstream)](https://gitlab.freedesktop.org/freetype/freetype) -- Version: 2.14.3-a6d4860 (Until Apr 12, 2026), with modifications: +- Version: 2.14.3-c39ca391 (Until May 13, 2026), with modifications: - ftsystem.c: Use UTF-8 instead ACP for Windows paths - - hvfload.c: Fix glyph->metrics.height too-small(=4) issue - License: BSD-style (The FreeType Project) ## Glad diff --git a/3rdparty/freetype/devel/ftoption.h b/3rdparty/freetype/devel/ftoption.h index c5f6bd472286..876c173b5786 100644 --- a/3rdparty/freetype/devel/ftoption.h +++ b/3rdparty/freetype/devel/ftoption.h @@ -439,8 +439,10 @@ FT_BEGIN_HEADER /************************************************************************** * - * The size in bytes of the render pool used by the scan-line converter to - * do all of its work. + * The size in bytes of the stack render pool used by the scan-line + * converters. Use this option to limit the stack usage. The memory + * requirements are proportional to size and complexity of a given glyph. + * FreeType's rasterizers switch to dynamic allocations when necessary. */ #define FT_RENDER_POOL_SIZE 16384L diff --git a/3rdparty/freetype/include/freetype/config/ftoption.h b/3rdparty/freetype/include/freetype/config/ftoption.h index 073a507c073c..aa604b9a540a 100644 --- a/3rdparty/freetype/include/freetype/config/ftoption.h +++ b/3rdparty/freetype/include/freetype/config/ftoption.h @@ -439,8 +439,10 @@ FT_BEGIN_HEADER /************************************************************************** * - * The size in bytes of the render pool used by the scan-line converter to - * do all of its work. + * The size in bytes of the stack render pool used by the scan-line + * converters. Use this option to limit the stack usage. The memory + * requirements are proportional to size and complexity of a given glyph. + * FreeType's rasterizers switch to dynamic allocations when necessary. */ #define FT_RENDER_POOL_SIZE 16384L diff --git a/3rdparty/freetype/include/freetype/ftmoderr.h b/3rdparty/freetype/include/freetype/ftmoderr.h index 7c1b1fd3c040..9010c9fc489a 100644 --- a/3rdparty/freetype/include/freetype/ftmoderr.h +++ b/3rdparty/freetype/include/freetype/ftmoderr.h @@ -172,6 +172,7 @@ FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" ) FT_MODERRDEF( GXvalid, 0x1600, "GX validation module" ) FT_MODERRDEF( Sdf, 0x1700, "Signed distance field raster module" ) + FT_MODERRDEF( HVF, 0x1800, "HVF module" ) #ifdef FT_MODERR_END_LIST diff --git a/3rdparty/freetype/include/freetype/fttypes.h b/3rdparty/freetype/include/freetype/fttypes.h index 97ddcde65aa6..2f3ca05955a0 100644 --- a/3rdparty/freetype/include/freetype/fttypes.h +++ b/3rdparty/freetype/include/freetype/fttypes.h @@ -25,8 +25,6 @@ #include #include -#include - FT_BEGIN_HEADER diff --git a/3rdparty/freetype/src/base/ftbitmap.c b/3rdparty/freetype/src/base/ftbitmap.c index f88cbc11e636..1606cbfa0905 100644 --- a/3rdparty/freetype/src/base/ftbitmap.c +++ b/3rdparty/freetype/src/base/ftbitmap.c @@ -776,18 +776,12 @@ FT_Bitmap source_bitmap; const FT_Bitmap* source; - FT_Vector source_offset; - FT_Vector target_offset; - FT_Bool free_source_bitmap = 0; FT_Bool free_target_bitmap_on_error = 0; - FT_Pos source_llx, source_lly, source_urx, source_ury; - FT_Pos target_llx, target_lly, target_urx, target_ury; - FT_Pos final_llx, final_lly, final_urx, final_ury; + FT_BBox sbx, tbx, fbx; unsigned int final_rows, final_width; - long x, y; if ( !library || !target || !source_ || !atarget_offset ) @@ -811,110 +805,32 @@ if ( !( source_->width && source_->rows ) ) return FT_Err_Ok; /* nothing to do */ - /* assure integer pixel offsets */ - source_offset.x = FT_PIX_FLOOR( source_offset_.x ); - source_offset.y = FT_PIX_FLOOR( source_offset_.y ); - target_offset.x = FT_PIX_FLOOR( atarget_offset->x ); - target_offset.y = FT_PIX_FLOOR( atarget_offset->y ); + /* get source bitmap dimensions assuming integer offsets */ + sbx.xMin = ( source_offset_.x >> 6 ); + sbx.yMin = ( source_offset_.y >> 6 ) - source_->rows; + sbx.xMax = ( source_offset_.x >> 6 ) + source_->width; + sbx.yMax = ( source_offset_.y >> 6 ); - /* get source bitmap dimensions */ - source_llx = source_offset.x; - if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y ) - { - FT_TRACE5(( - "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" )); - return FT_THROW( Invalid_Argument ); - } - source_lly = source_offset.y - ( source_->rows << 6 ); + FT_TRACE5(( "FT_Bitmap_Blend:\n" )); + FT_TRACE5(( " source bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", + sbx.xMin, sbx.yMin, sbx.xMax, sbx.yMax, + source_->width, source_->rows )); - if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx ) + /* sanity check */ + if ( sbx.xMin > sbx.xMax || sbx.yMin > sbx.yMax || + source_->width > 0x7FFFU || source_->rows > 0x7FFFU ) { - FT_TRACE5(( - "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" )); + FT_TRACE5(( "FT_Bitmap_Blend: source dimension overflow\n" )); return FT_THROW( Invalid_Argument ); } - source_urx = source_llx + ( source_->width << 6 ); - source_ury = source_offset.y; - /* get target bitmap dimensions */ - if ( target->width && target->rows ) - { - target_llx = target_offset.x; - if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y ) - { - FT_TRACE5(( - "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" )); - return FT_THROW( Invalid_Argument ); - } - target_lly = target_offset.y - ( target->rows << 6 ); - - if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx ) - { - FT_TRACE5(( - "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" )); - return FT_THROW( Invalid_Argument ); - } - target_urx = target_llx + ( target->width << 6 ); - target_ury = target_offset.y; - } - else + if ( !target->width || !target->rows ) { - target_llx = FT_LONG_MAX; - target_lly = FT_LONG_MAX; - target_urx = FT_LONG_MIN; - target_ury = FT_LONG_MIN; - } - - /* compute final bitmap dimensions */ - final_llx = FT_MIN( source_llx, target_llx ); - final_lly = FT_MIN( source_lly, target_lly ); - final_urx = FT_MAX( source_urx, target_urx ); - final_ury = FT_MAX( source_ury, target_ury ); - - final_width = ( final_urx - final_llx ) >> 6; - final_rows = ( final_ury - final_lly ) >> 6; - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( "FT_Bitmap_Blend:\n" )); - FT_TRACE5(( " source bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", - source_llx / 64, source_lly / 64, - source_urx / 64, source_ury / 64, - source_->width, source_->rows )); - - if ( target->width && target->rows ) - FT_TRACE5(( " target bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", - target_llx / 64, target_lly / 64, - target_urx / 64, target_ury / 64, - target->width, target->rows )); - else FT_TRACE5(( " target bitmap: empty\n" )); - if ( final_width && final_rows ) - FT_TRACE5(( " final bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", - final_llx / 64, final_lly / 64, - final_urx / 64, final_ury / 64, - final_width, final_rows )); - else - FT_TRACE5(( " final bitmap: empty\n" )); -#endif /* FT_DEBUG_LEVEL_TRACE */ - - if ( !( final_width && final_rows ) ) - return FT_Err_Ok; /* nothing to do */ - - /* for blending, set offset vector of final bitmap */ - /* temporarily to (0,0) */ - source_llx -= final_llx; - source_lly -= final_lly; - - if ( target->width && target->rows ) - { - target_llx -= final_llx; - target_lly -= final_lly; - } + final_width = source_->width; + final_rows = source_->rows; - /* set up target bitmap */ - if ( target->pixel_mode == FT_PIXEL_MODE_NONE ) - { /* create new empty bitmap */ target->width = final_width; target->rows = final_rows; @@ -926,72 +842,116 @@ return error; free_target_bitmap_on_error = 1; + + fbx = sbx; } - else if ( target->width != final_width || - target->rows != final_rows ) + else { - /* adjust old bitmap to enlarged size */ - int pitch, new_pitch; + /* get target bitmap dimensions assuming integer offsets */ + tbx.xMin = ( atarget_offset->x >> 6 ); + tbx.yMin = ( atarget_offset->y >> 6 ) - target->rows; + tbx.xMax = ( atarget_offset->x >> 6 ) + target->width; + tbx.yMax = ( atarget_offset->y >> 6 ); - unsigned char* buffer = NULL; + FT_TRACE5(( " target bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", + tbx.xMin, tbx.yMin, tbx.xMax, tbx.yMax, + target->width, target->rows )); + /* sanity check */ + if ( tbx.xMin > tbx.xMax || tbx.yMin > tbx.yMax ) + { + FT_TRACE5(( "FT_Bitmap_Blend: targget dimension overflow\n" )); + return FT_THROW( Invalid_Argument ); + } - pitch = target->pitch; + /* compute final bitmap dimensions */ + fbx.xMin = FT_MIN( sbx.xMin, tbx.xMin ); + fbx.yMin = FT_MIN( sbx.yMin, tbx.yMin ); + fbx.xMax = FT_MAX( sbx.xMax, tbx.xMax ); + fbx.yMax = FT_MAX( sbx.yMax, tbx.yMax ); - if ( pitch < 0 ) - pitch = -pitch; + /* sanity check */ + if ( fbx.xMin < -0x10000 || fbx.xMax >= 0x10000 || + fbx.yMin < -0x10000 || fbx.yMax >= 0x10000 ) + { + FT_TRACE5(( "FT_Bitmap_Blend: final dimension overflow\n" )); + return FT_THROW( Invalid_Argument ); + } - new_pitch = (int)final_width * 4; + final_width = fbx.xMax - fbx.xMin; + final_rows = fbx.yMax - fbx.yMin; - /* TODO: provide an in-buffer solution for large bitmaps */ - /* to avoid allocation of a new buffer */ - if ( FT_ALLOC_MULT( buffer, final_rows, new_pitch ) ) - goto Error; + /* adjust target bitmap to enlarged size */ + if ( target->width < final_width || + target->rows < final_rows ) + { + int pitch, new_pitch; - /* copy data to new buffer */ - x = target_llx >> 6; - y = target_lly >> 6; + unsigned char* buffer = NULL; - /* the bitmap flow is from top to bottom, */ - /* but y is measured from bottom to top */ - if ( target->pitch < 0 ) - { - /* XXX */ - } - else - { - unsigned char* p = - target->buffer; - unsigned char* q = - buffer + - ( final_rows - y - target->rows ) * new_pitch + - x * 4; - unsigned char* limit_p = - p + pitch * (int)target->rows; + pitch = target->pitch; + + if ( pitch < 0 ) + pitch = -pitch; + + new_pitch = (int)final_width * 4; + + /* TODO: provide an in-buffer solution for large bitmaps */ + /* to avoid allocation of a new buffer */ + if ( FT_ALLOC_MULT( buffer, final_rows, new_pitch ) ) + goto Error; + + /* copy data to new buffer */ - while ( p < limit_p ) + /* the bitmap flow is from top to bottom, */ + /* but y is measured from bottom to top */ + if ( target->pitch < 0 ) { - FT_MEM_COPY( q, p, pitch ); + /* XXX */ + } + else + { + FT_Pos x = tbx.xMin - fbx.xMin; + FT_Pos y = tbx.yMin - fbx.yMin; + + unsigned char* p = + target->buffer; + unsigned char* q = + buffer + + ( final_rows - y - target->rows ) * new_pitch + + x * 4; + unsigned char* limit_p = + p + pitch * (int)target->rows; + - p += pitch; - q += new_pitch; + while ( p < limit_p ) + { + FT_MEM_COPY( q, p, pitch ); + + p += pitch; + q += new_pitch; + } } - } - FT_FREE( target->buffer ); + FT_FREE( target->buffer ); - target->width = final_width; - target->rows = final_rows; + target->width = final_width; + target->rows = final_rows; - if ( target->pitch < 0 ) - target->pitch = -new_pitch; - else - target->pitch = new_pitch; + if ( target->pitch < 0 ) + target->pitch = -new_pitch; + else + target->pitch = new_pitch; - target->buffer = buffer; + target->buffer = buffer; + } } + FT_TRACE5(( " final bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", + fbx.xMin, fbx.yMin, fbx.xMax, fbx.yMax, + final_width, final_rows )); + /* adjust source bitmap if necessary */ if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY ) { @@ -1008,8 +968,6 @@ /* do blending; the code below returns pre-multiplied channels, */ /* similar to what FreeType gets from `CBDT' tables */ - x = source_llx >> 6; - y = source_lly >> 6; /* the bitmap flow is from top to bottom, */ /* but y is measured from bottom to top */ @@ -1019,6 +977,9 @@ } else { + FT_Pos x = sbx.xMin - fbx.xMin; + FT_Pos y = sbx.yMin - fbx.yMin; + unsigned char* p = source->buffer; unsigned char* q = @@ -1064,8 +1025,8 @@ } } - atarget_offset->x = final_llx; - atarget_offset->y = final_lly + ( final_rows << 6 ); + atarget_offset->x = fbx.xMin * 64; + atarget_offset->y = fbx.yMax * 64; Error: if ( error && free_target_bitmap_on_error ) diff --git a/3rdparty/freetype/src/base/ftobjs.c b/3rdparty/freetype/src/base/ftobjs.c index f9f64c40fec3..fb19052a570d 100644 --- a/3rdparty/freetype/src/base/ftobjs.c +++ b/3rdparty/freetype/src/base/ftobjs.c @@ -4737,121 +4737,114 @@ FT_Error error = FT_Err_Ok; FT_Face face = slot->face; FT_Renderer renderer; + FT_ListNode node = NULL; - switch ( slot->format ) + /* try to render colored glyph layers as a special case */ + if ( slot->internal->load_flags & FT_LOAD_COLOR && + slot->format == FT_GLYPH_FORMAT_OUTLINE ) { - default: - if ( slot->internal->load_flags & FT_LOAD_COLOR ) - { - FT_LayerIterator iterator; + FT_LayerIterator iterator; - FT_UInt base_glyph = slot->glyph_index; + FT_UInt base_glyph = slot->glyph_index; - FT_Bool have_layers; - FT_UInt glyph_index; - FT_UInt color_index; + FT_Bool have_layers; + FT_UInt glyph_index; + FT_UInt color_index; - /* check whether we have colored glyph layers */ - iterator.p = NULL; - have_layers = FT_Get_Color_Glyph_Layer( face, - base_glyph, - &glyph_index, - &color_index, - &iterator ); - if ( have_layers ) + iterator.p = NULL; + have_layers = FT_Get_Color_Glyph_Layer( face, + base_glyph, + &glyph_index, + &color_index, + &iterator ); + if ( have_layers ) + { + error = FT_New_GlyphSlot( face, NULL ); + if ( !error ) { - error = FT_New_GlyphSlot( face, NULL ); - if ( !error ) - { - TT_Face ttface = (TT_Face)face; - SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; - + TT_Face ttface = (TT_Face)face; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; - do - { - FT_Int32 load_flags = slot->internal->load_flags; + do + { + FT_Int32 load_flags = slot->internal->load_flags; - /* disable the `FT_LOAD_COLOR' flag to avoid recursion */ - /* right here in this function */ - load_flags &= ~FT_LOAD_COLOR; - - /* render into the new `face->glyph' glyph slot */ - load_flags |= FT_LOAD_RENDER; - error = FT_Load_Glyph( face, glyph_index, load_flags ); - if ( error ) - break; + /* disable the `FT_LOAD_COLOR' flag to avoid recursion */ + /* right here in this function */ + load_flags &= ~FT_LOAD_COLOR; - /* blend new `face->glyph' into old `slot'; */ - /* at the first call, `slot' is still empty */ - error = sfnt->colr_blend( ttface, - color_index, - slot, - face->glyph ); - if ( error ) - break; + /* render into the new `face->glyph' glyph slot */ + load_flags |= FT_LOAD_RENDER | FT_LOAD_NO_BITMAP; - } while ( FT_Get_Color_Glyph_Layer( face, - base_glyph, - &glyph_index, - &color_index, - &iterator ) ); + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if ( error ) + break; - if ( !error ) - slot->format = FT_GLYPH_FORMAT_BITMAP; + /* blend new `face->glyph' into old `slot'; */ + /* at the first call, `slot' is still empty */ + error = sfnt->colr_blend( ttface, + color_index, + slot, + face->glyph ); + if ( error ) + break; - /* this call also restores `slot' as the glyph slot */ - FT_Done_GlyphSlot( face->glyph ); - } + } while ( FT_Get_Color_Glyph_Layer( face, + base_glyph, + &glyph_index, + &color_index, + &iterator ) ); if ( !error ) - return error; + slot->format = FT_GLYPH_FORMAT_BITMAP; - /* Failed to do the colored layer. Draw outline instead. */ - slot->format = FT_GLYPH_FORMAT_OUTLINE; + /* this call also restores `slot' as the glyph slot */ + FT_Done_GlyphSlot( face->glyph ); } - } - { - FT_ListNode node = NULL; + if ( !error ) + return error; + /* Failed to do the colored layer. Draw outline instead. */ + slot->format = FT_GLYPH_FORMAT_OUTLINE; + } + } - /* small shortcut for the very common case */ - if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - { - renderer = library->cur_renderer; - node = library->renderers.head; - } - else - renderer = FT_Lookup_Renderer( library, slot->format, &node ); + /* small shortcut for the very common case */ + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) + { + renderer = library->cur_renderer; + node = library->renderers.head; + } + else + renderer = FT_Lookup_Renderer( library, slot->format, &node ); - error = FT_ERR( Cannot_Render_Glyph ); - while ( renderer ) - { - error = renderer->render( renderer, slot, render_mode, NULL ); - if ( !error || - FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) - break; - - /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ - /* is unsupported by the current renderer for this glyph image */ - /* format. */ - - /* now, look for another renderer that supports the same */ - /* format. */ - renderer = FT_Lookup_Renderer( library, slot->format, &node ); - } + error = FT_ERR( Cannot_Render_Glyph ); + while ( renderer ) + { + error = renderer->render( renderer, slot, render_mode, NULL ); + if ( !error || + FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) + break; - /* it is not an error if we cannot render a bitmap glyph */ - if ( FT_ERR_EQ( error, Cannot_Render_Glyph ) && - slot->format == FT_GLYPH_FORMAT_BITMAP ) - error = FT_Err_Ok; - } + /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ + /* is unsupported by the current renderer for this glyph image */ + /* format. */ + + /* now, look for another renderer that supports the same */ + /* format. */ + renderer = FT_Lookup_Renderer( library, slot->format, &node ); } + /* it is not an error if we cannot render a bitmap glyph */ + if ( FT_ERR_EQ( error, Cannot_Render_Glyph ) && + slot->format == FT_GLYPH_FORMAT_BITMAP ) + error = FT_Err_Ok; + #ifdef FT_DEBUG_LEVEL_TRACE #undef FT_COMPONENT diff --git a/3rdparty/freetype/src/hvf/hvfload.c b/3rdparty/freetype/src/hvf/hvfload.c index 88dbe468ae6b..a02d363c1da6 100644 --- a/3rdparty/freetype/src/hvf/hvfload.c +++ b/3rdparty/freetype/src/hvf/hvfload.c @@ -184,9 +184,7 @@ /* Move-to or line-to point with pre-calculated scaling factors. */ - error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, - ctx->outline->n_points + 1, - ctx->outline->n_contours ); + error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 1, 0 ); if ( error ) return HVFPartRenderActionStop; @@ -211,9 +209,7 @@ /* Quadratic curve with pre-calculated scaling factors. */ - error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, - ctx->outline->n_points + 2, - ctx->outline->n_contours ); + error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 2, 0 ); if ( error ) return HVFPartRenderActionStop; @@ -249,9 +245,7 @@ /* Cubic curve with pre-calculated scaling factors. */ - error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, - ctx->outline->n_points + 3, - ctx->outline->n_contours ); + error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 3, 0 ); if ( error ) return HVFPartRenderActionStop; @@ -295,9 +289,7 @@ if ( ctx->path_begun && ctx->outline->n_points > 0 ) { /* Check space for contour. */ - error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, - ctx->outline->n_points, - ctx->outline->n_contours + 1 ); + error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 0, 1 ); if ( error ) return HVFPartRenderActionStop; @@ -380,7 +372,6 @@ return FT_THROW( Invalid_Glyph_Index ); /* Initialize render context. */ - context.face = face; context.loader = loader; context.path_begun = 0; @@ -431,6 +422,7 @@ " hvf_set_variation_axes failed (error %d)\n", error )); } #endif + error = FT_Err_Ok; /* axis failure is non-fatal */ /* Render the glyph using HVF. */ hvf_result = HVF_render_current_part( (HVFPartRenderer*)face->renderer, @@ -453,9 +445,7 @@ if ( context.path_begun && context.outline->n_points > 0 ) { /* Check space for contour. */ - error = FT_GLYPHLOADER_CHECK_POINTS( loader, - context.outline->n_points, - context.outline->n_contours + 1 ); + error = FT_GLYPHLOADER_CHECK_POINTS( loader, 0, 1 ); if ( !error ) { context.outline->contours[context.outline->n_contours++] = @@ -474,49 +464,104 @@ /* since it is a stroke-based format */ glyph->outline.flags |= FT_OUTLINE_OVERLAP; - /* Set glyph metrics - prefer TrueType metrics but derive height/box - from the rendered outline bbox when available (fixes HVF bbox=too-small). */ + /* Set glyph metrics - get from TrueType infrastructure when possible. */ { - FT_UShort advance_width = 0; - FT_Short left_bearing = 0; - FT_BBox bbox; - TT_Face tt_face = (TT_Face)face; - SFNT_Service sfnt = (SFNT_Service)tt_face->sfnt; - - /* Get metrics from TrueType tables if available for advance/left bearing. */ + FT_BBox bbox; + FT_UShort advance_width = 0; + FT_Short left_bearing = 0; + + TT_Face tt_face = (TT_Face)face; + SFNT_Service sfnt = (SFNT_Service)tt_face->sfnt; + + FT_Bool has_vertical_info; + FT_Pos top; /* vertical top side bearing */ + FT_Pos advance; /* vertical advance height */ + + + /* Get horizontal metrics from TrueType tables if available. */ if ( sfnt && glyph_index < (FT_UInt)face->root.root.num_glyphs ) - sfnt->get_metrics( tt_face, 0, glyph_index, &left_bearing, &advance_width ); + sfnt->get_metrics( tt_face, 0, glyph_index, + &left_bearing, &advance_width ); else { - /* Fallback to reasonable defaults. */ - advance_width = (FT_UShort)( size->metrics.x_ppem ); + /* Fallback to reasonable defaults. */ + advance_width = (FT_UShort)( size->metrics.x_ppem ); + left_bearing = 0; } - - FT_Outline_Get_CBox( &loader->base.outline, &bbox ); - - /* Use bbox to set width/height/horiBearingY if bbox is non-empty. - bbox values are in 26.6 fixed units, which matches glyph->metrics. */ - glyph->metrics.width = bbox.xMax - bbox.xMin; - glyph->metrics.height = bbox.yMax - bbox.yMin; - - glyph->metrics.horiBearingX = bbox.xMin; // left_bearing; - glyph->metrics.horiBearingY = bbox.yMax; - - glyph->metrics.horiAdvance = advance_width; - glyph->metrics.vertBearingX = glyph->metrics.width / 2; - glyph->metrics.vertBearingY = 0; - glyph->metrics.vertAdvance = glyph->metrics.height; - } - /* Apply scaling only to values not derived from the scaled outline bbox if scaling was applied. */ - if ( apply_scaling ) - { - FT_Size_Metrics* metrics = &size->metrics; + glyph->metrics.horiAdvance = advance_width; + glyph->linearHoriAdvance = advance_width; + + /* Get vertical metrics from vmtx table or synthesize them, */ + /* consistent with TrueType and CFF drivers for SFNT-based fonts. */ + has_vertical_info = + FT_BOOL( tt_face->vertical_info && + tt_face->vertical.number_Of_VMetrics > 0 ); + + if ( has_vertical_info ) + { + FT_Short tsb = 0; + FT_UShort ah = 0; + + + sfnt->get_metrics( tt_face, 1, glyph_index, &tsb, &ah ); + + top = tsb; + advance = ah; + } + else + { + /* Use OS/2 or horizontal header for vertical advance. */ + if ( tt_face->os2.version != 0xFFFFU ) + advance = (FT_Pos)( tt_face->os2.sTypoAscender - + tt_face->os2.sTypoDescender ); + else + advance = (FT_Pos)( tt_face->horizontal.Ascender - + tt_face->horizontal.Descender ); + + top = 0; /* computed after bbox is known */ + } + + glyph->linearVertAdvance = advance; + + /* Scale table-derived metrics if needed. */ + /* Outline coordinates are already in the target coordinate */ + /* space (scaled in callback, or 26.6 font units for NO_SCALE) */ + /* so bbox-derived metrics need no additional scaling. */ + if ( apply_scaling ) + { + FT_Fixed x_scale = size->metrics.x_scale; + FT_Fixed y_scale = size->metrics.y_scale; + + + glyph->metrics.horiAdvance = FT_MulFix( glyph->metrics.horiAdvance, + x_scale ); + top = FT_MulFix( top, y_scale ); + advance = FT_MulFix( advance, y_scale ); + } - //glyph->metrics.horiBearingX = FT_MulFix( glyph->metrics.horiBearingX, - // metrics->x_scale ); - glyph->metrics.horiAdvance = FT_MulFix( glyph->metrics.horiAdvance, - metrics->x_scale ); + /* Compute width, height, and bearing metrics from the glyph */ + /* outline bounding box, consistent with TrueType and CFF */ + /* drivers. */ + FT_Outline_Get_CBox( &glyph->outline, &bbox ); + + glyph->metrics.width = bbox.xMax - bbox.xMin; + glyph->metrics.height = bbox.yMax - bbox.yMin; + glyph->metrics.horiBearingX = bbox.xMin; + glyph->metrics.horiBearingY = bbox.yMax; + + /* Finalize vertical metrics. */ + /* vertBearingX centers the glyph horizontally for vertical */ + /* layout, matching both TrueType and CFF drivers. */ + /* When no vmtx data is available, vertBearingY centers the */ + /* glyph vertically within the advance height. */ + if ( !has_vertical_info ) + top = ( advance - glyph->metrics.height ) / 2; + + glyph->metrics.vertBearingX = glyph->metrics.horiBearingX - + glyph->metrics.horiAdvance / 2; + glyph->metrics.vertBearingY = top; + glyph->metrics.vertAdvance = advance; } /* Cache management - clear cache every */ diff --git a/3rdparty/freetype/src/hvf/hvfobjs.c b/3rdparty/freetype/src/hvf/hvfobjs.c index b55204a5beba..96536b8ef15b 100644 --- a/3rdparty/freetype/src/hvf/hvfobjs.c +++ b/3rdparty/freetype/src/hvf/hvfobjs.c @@ -202,8 +202,8 @@ face->num_axes = mm_var->num_axis; /* Allocate storage for HVF axis coordinates. */ - if ( !( FT_MEM_QNEW_ARRAY( *(HVFAxisValue**)&face->axis_coords, - face->num_axes ) ) ) + if ( FT_QNEW_ARRAY( *(HVFAxisValue**)&face->axis_coords, + face->num_axes ) ) { face->num_axes = 0; goto Cleanup; @@ -242,7 +242,7 @@ return FT_Err_Ok; /* Allocate temporary storage for current FreeType coordinates. */ - if ( !( FT_MEM_QNEW_ARRAY( ft_coords, face->num_axes ) ) ) + if ( FT_QNEW_ARRAY( ft_coords, face->num_axes ) ) return error; /* Get current variation coordinates. */ diff --git a/3rdparty/freetype/src/hvf/hvfobjs.h b/3rdparty/freetype/src/hvf/hvfobjs.h index daf97f729f31..ae9c90595e81 100644 --- a/3rdparty/freetype/src/hvf/hvfobjs.h +++ b/3rdparty/freetype/src/hvf/hvfobjs.h @@ -115,8 +115,6 @@ FT_BEGIN_HEADER FT_GlyphLoader loader; /* Standard FreeType loader. */ FT_Outline* outline; /* Points to `loader->current.outline`. */ FT_Bool path_begun; /* Path state tracking. */ - - HVF_Face face; /* Reference to face. */ /* Pre-calculated scaling factors for efficient coordinate conversion. */ HVFXYCoord x_scale_fixed; /* x_scale * 65536.0 (or just 65536.0) */ diff --git a/3rdparty/freetype/src/psaux/psintrp.c b/3rdparty/freetype/src/psaux/psintrp.c index 7e3475e6f589..4db0a544aeda 100644 --- a/3rdparty/freetype/src/psaux/psintrp.c +++ b/3rdparty/freetype/src/psaux/psintrp.c @@ -415,7 +415,7 @@ /* Blend numOperands on the stack, */ /* store results into the first numBlends values, */ /* then pop remaining arguments. */ - static void + static FT_Error cf2_doBlend( const CFF_Blend blend, CF2_Stack opStack, CF2_UInt numBlends ) @@ -424,9 +424,13 @@ CF2_UInt base; CF2_UInt i, j; CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV ); + CF2_UInt count = cf2_stack_count( opStack ); + + if ( numOperands > count ) + return FT_THROW( Stack_Underflow ); - base = cf2_stack_count( opStack ) - numOperands; + base = count - numOperands; delta = base + numBlends; FT_TRACE6(( " (" )); @@ -455,6 +459,8 @@ /* leave only `numBlends' results on stack */ cf2_stack_pop( opStack, numOperands - numBlends ); + + return FT_Err_Ok; } @@ -769,13 +775,10 @@ /* do the blend */ numBlends = (FT_UInt)cf2_stack_popInt( opStack ); - if ( numBlends > stackSize ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; - } - cf2_doBlend( &font->blend, opStack, numBlends ); + lastError = cf2_doBlend( &font->blend, opStack, numBlends ); + if ( lastError ) + goto exit; font->blend.usedBV = TRUE; } @@ -985,8 +988,8 @@ FT_TRACE4(( "%s", op1 == cf2_cmdCALLGSUBR ? " callgsubr" : " callsubr" )); - if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR ) || - ( font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) ) + if ( ( !font->isT1 && charstringIndex >= CF2_MAX_SUBR ) || + ( font->isT1 && charstringIndex >= T1_MAX_SUBRS_CALLS ) ) { /* max subr plus one for charstring */ lastError = FT_THROW( Invalid_Glyph_Format ); diff --git a/3rdparty/freetype/src/psaux/psstack.c b/3rdparty/freetype/src/psaux/psstack.c index 797486588a34..1360ba30dab7 100644 --- a/3rdparty/freetype/src/psaux/psstack.c +++ b/3rdparty/freetype/src/psaux/psstack.c @@ -211,7 +211,7 @@ CF2_UInt idx, CF2_Fixed val ) { - if ( idx > cf2_stack_count( stack ) ) + if ( idx >= cf2_stack_count( stack ) ) { CF2_SET_ERROR( stack->error, Stack_Overflow ); return; @@ -245,6 +245,7 @@ CF2_StackNumber last = { { 0 }, CF2_NumberInt }; CF2_Int start_idx, idx, i; + CF2_Int offset; if ( count < 2 ) @@ -256,6 +257,8 @@ return; } + offset = (CF2_Int)cf2_stack_count( stack ) - count; + /* before C99 it is implementation-defined whether */ /* the result of `%' is negative if the first operand */ /* is negative */ @@ -303,7 +306,7 @@ { start_idx++; idx = start_idx; - last = stack->buffer[idx]; + last = stack->buffer[idx + offset]; } idx += shift; @@ -312,9 +315,9 @@ else if ( idx < 0 ) idx += count; - tmp = stack->buffer[idx]; - stack->buffer[idx] = last; - last = tmp; + tmp = stack->buffer[idx + offset]; + stack->buffer[idx + offset] = last; + last = tmp; } } diff --git a/3rdparty/freetype/src/raster/ftraster.c b/3rdparty/freetype/src/raster/ftraster.c index 4165800a1aac..08b4c9dd7be1 100644 --- a/3rdparty/freetype/src/raster/ftraster.c +++ b/3rdparty/freetype/src/raster/ftraster.c @@ -2517,12 +2517,8 @@ Render_Glyph( RAS_ARG ) { FT_Error error; - Long buffer[FT_MAX_BLACK_POOL]; - ras.buff = buffer; - ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */ - Set_High_Precision( RAS_VARS ras.outline.flags & FT_OUTLINE_HIGH_PRECISION ); @@ -2665,6 +2661,9 @@ const FT_Outline* outline = (const FT_Outline*)params->source; const FT_Bitmap* target_map = params->target; + FT_ULong estimate; + int ret; + #ifndef FT_STATIC_RASTER black_TWorker worker[1]; #endif @@ -2712,7 +2711,36 @@ if ( ras.bPitch > 0 ) ras.bOrigin += ras.bTop * ras.bPitch; - return Render_Glyph( RAS_VAR ); + /* allocate memory based on empirical estimate from CJK fonts */ + estimate = ( ras.bTop + ras.bRight ) * 8UL + + 80UL * sizeof ( TProfile ) / sizeof ( Long ); + if ( estimate > FT_MAX_BLACK_POOL ) + { + FT_Error error; + FT_Memory memory = (FT_Memory)((black_PRaster)raster)->memory; + + + if ( FT_QNEW_ARRAY( ras.buff, estimate ) ) + ret = error; + else + { + ras.sizeBuff = ras.buff + estimate; + ret = Render_Glyph( RAS_VAR ); + FT_FREE( ras.buff ); + } + } + else + { + Long buffer[FT_MAX_BLACK_POOL]; /* stack allocation */ + + + ras.buff = buffer; + ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */ + + ret = Render_Glyph( RAS_VAR ); + } + + return ret; } diff --git a/3rdparty/freetype/src/sfnt/ttsbit.c b/3rdparty/freetype/src/sfnt/ttsbit.c index 1655e40b6814..d479b6a0b78e 100644 --- a/3rdparty/freetype/src/sfnt/ttsbit.c +++ b/3rdparty/freetype/src/sfnt/ttsbit.c @@ -1602,9 +1602,10 @@ metrics->horiBearingY = (FT_Short)( originOffsetY + metrics->height ); metrics->vertBearingY = (FT_Short)originOffsetY; - metrics->horiAdvance = (FT_UShort)( aadvance * - face->root.size->metrics.x_ppem / - face->header.Units_Per_EM ); + metrics->horiAdvance = + (FT_UShort)FT_MulDiv( aadvance, + face->root.size->metrics.x_ppem, + face->header.Units_Per_EM ); if ( face->vertical_info ) tt_face_get_metrics( face, TRUE, glyph_index, &abearing, &aadvance ); @@ -1615,9 +1616,10 @@ aadvance = (FT_UShort)FT_ABS( face->horizontal.Ascender - face->horizontal.Descender ); - metrics->vertAdvance = (FT_UShort)( aadvance * - face->root.size->metrics.x_ppem / - face->header.Units_Per_EM ); + metrics->vertAdvance = + (FT_UShort)FT_MulDiv( aadvance, + face->root.size->metrics.x_ppem, + face->header.Units_Per_EM ); } return error; diff --git a/3rdparty/freetype/src/smooth/ftgrays.c b/3rdparty/freetype/src/smooth/ftgrays.c index 0f7b63937d70..0f1cf441896f 100644 --- a/3rdparty/freetype/src/smooth/ftgrays.c +++ b/3rdparty/freetype/src/smooth/ftgrays.c @@ -68,11 +68,14 @@ * * This renderer has the following advantages: * - * - It doesn't need an intermediate bitmap. Instead, one can supply a - * callback function that will be called by the renderer to draw gray - * spans on any target surface. You can thus do direct composition on - * any kind of bitmap, provided that you give the renderer the right - * callback. + * - It doesn't need an intermediate bitmap. Instead, linked lists + * of cells (pixels visited by an outline) are stored, which requires + * less memory and can be maintained on the stack for small glyphs. + * + * - One can supply a callback function that will be called by the + * renderer to draw gray spans on any target surface. You can thus + * do direct composition on any kind of bitmap, provided that you give + * the renderer the right callback. * * - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on * each pixel cell by straight segments. @@ -464,7 +467,10 @@ typedef ptrdiff_t FT_PtrDist; } TPixmap; - /* maximum number of gray cells in the buffer */ + /* Maximum number of gray cells in the stack buffer; */ + /* for example, a buffer of 680 cells can accommodate */ + /* a glyph with the taxicab perimeter of 680 pixels. */ + /* A larger buffer can be allocated when necessary. */ #if FT_RENDER_POOL_SIZE > 2048 #define FT_MAX_GRAY_POOL ( FT_RENDER_POOL_SIZE / sizeof ( TCell ) ) #else @@ -492,9 +498,10 @@ typedef ptrdiff_t FT_PtrDist; TCoord count_ey; /* same as (max_ey - min_ey) */ int error; /* pool overflow exception */ + PCell buffer; /* buffer */ + PCell cell_null; /* last cell, used as dumpster and limit */ PCell cell; /* current cell */ PCell cell_free; /* call allocation next free slot */ - PCell cell_null; /* last cell, used as dumpster and limit */ PCell* ycells; /* array of cell linked-lists; one per */ /* vertical coordinate in the current band */ @@ -1861,10 +1868,6 @@ typedef ptrdiff_t FT_PtrDist; static int gray_convert_glyph( RAS_ARG ) { - TCell buffer[FT_MAX_GRAY_POOL]; - 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 */ TCoord* band; @@ -1873,89 +1876,74 @@ typedef ptrdiff_t FT_PtrDist; /* Initialize the null cell at the end of the poll. */ - ras.cell_null = buffer + FT_MAX_GRAY_POOL - 1; ras.cell_null->x = CELL_MAX_X_VALUE; ras.cell_null->area = 0; ras.cell_null->cover = 0; ras.cell_null->next = NULL; /* set up vertical bands */ - ras.ycells = (PCell*)buffer; + ras.ycells = (PCell*)ras.buffer; - if ( height > n ) - { - /* two divisions rounded up */ - n = ( height + n - 1 ) / n; - 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 ); + band = bands; + band[1] = ras.cbox.yMin; + band[0] = ras.cbox.yMax; - ras.count_ey = ras.max_ey - ras.min_ey; - - band = bands; - band[1] = ras.cbox.xMin; - band[0] = ras.cbox.xMax; - - do - { - TCoord i; + do + { + size_t n; + TCoord i; - ras.min_ex = band[1]; - ras.max_ex = band[0]; + ras.min_ey = band[1]; + ras.max_ey = band[0]; + 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; + /* 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 ); + n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) + / sizeof ( TCell ); - ras.cell_free = buffer + n; - ras.cell = ras.cell_null; - ras.error = Smooth_Err_Ok; + ras.cell_free = ras.buffer + n; + ras.cell = ras.cell_null; + ras.error = Smooth_Err_Ok; - error = gray_convert_glyph_inner( RAS_VAR_ continued ); - continued = 1; + error = gray_convert_glyph_inner( RAS_VAR_ continued ); + continued = 1; - if ( !error ) - { - if ( ras.render_span ) /* for FT_RASTER_FLAG_DIRECT only */ - gray_sweep_direct( RAS_VAR ); - else - gray_sweep( RAS_VAR ); - band--; - continue; - } - else if ( error != Smooth_Err_Raster_Overflow ) - goto Exit; + if ( !error ) + { + if ( ras.render_span ) /* for FT_RASTER_FLAG_DIRECT only */ + gray_sweep_direct( RAS_VAR ); + else + gray_sweep( RAS_VAR ); + band--; + continue; + } + else if ( error != Smooth_Err_Raster_Overflow ) + goto Exit; - /* render pool overflow; we will reduce the render band by half */ - i = ( band[0] - band[1] ) >> 1; + /* render pool overflow; we will reduce the render band by half */ + i = ( band[0] - band[1] ) >> 1; - /* this should never happen even with tiny rendering pool */ - if ( i == 0 ) - { - FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); - error = FT_THROW( Raster_Overflow ); - goto Exit; - } + /* this should never happen even with tiny rendering pool */ + if ( i == 0 ) + { + FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); + error = FT_THROW( Raster_Overflow ); + goto Exit; + } - band++; - band[1] = band[0]; - band[0] += i; - } while ( band >= bands ); - } + band++; + band[1] = band[0]; + band[0] += i; + } while ( band >= bands ); Exit: - ras.cell = ras.cell_free = ras.cell_null = NULL; - ras.ycells = NULL; - return error; } @@ -1964,6 +1952,9 @@ typedef ptrdiff_t FT_PtrDist; gray_raster_render( FT_Raster raster, const FT_Raster_Params* params ) { + FT_ULong estimate; + int ret; + const FT_Outline* outline = (const FT_Outline*)params->source; const FT_Bitmap* target_map = params->target; @@ -2039,7 +2030,36 @@ typedef ptrdiff_t FT_PtrDist; if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax ) return Smooth_Err_Ok; - return gray_convert_glyph( RAS_VAR ); + /* allocate memory based on empirical estimate from CJK fonts */ + estimate = ( ras.cbox.xMax - ras.cbox.xMin + + ras.cbox.yMax - ras.cbox.yMin ) * 10UL; + if ( estimate > FT_MAX_GRAY_POOL ) + { + FT_Error error; + FT_Memory memory = (FT_Memory)((gray_PRaster)raster)->memory; + + + if ( FT_QNEW_ARRAY( ras.buffer, estimate ) ) + ret = error; + else + { + ras.cell_null = ras.buffer + estimate - 1; + ret = gray_convert_glyph( RAS_VAR ); + FT_FREE( ras.buffer ); + } + } + else + { + TCell buffer[FT_MAX_GRAY_POOL]; /* stack allocation */ + + + ras.buffer = buffer; + ras.cell_null = ras.buffer + FT_MAX_GRAY_POOL - 1; + + ret = gray_convert_glyph( RAS_VAR ); + } + + return ret; } diff --git a/3rdparty/freetype/src/truetype/ttgload.c b/3rdparty/freetype/src/truetype/ttgload.c index dcff7c3bb713..f9a54c4efa0c 100644 --- a/3rdparty/freetype/src/truetype/ttgload.c +++ b/3rdparty/freetype/src/truetype/ttgload.c @@ -345,8 +345,8 @@ FT_Byte* limit = load->limit; FT_GlyphLoader gloader = load->gloader; FT_Outline* outline = &gloader->current.outline; - FT_Int n_contours = load->n_contours; - FT_Int n_points; + FT_UInt n_contours = (FT_UInt)load->n_contours; + FT_UInt n_points; FT_UShort n_ins; FT_Byte *flag, *flag_limit; @@ -354,7 +354,6 @@ FT_Vector *vec, *vec_limit; FT_Pos x, y; FT_UShort *cont, *cont_limit; - FT_Int last; /* check that we can add the contours to the glyph */ @@ -363,27 +362,25 @@ goto Fail; /* check space for contours array + instructions count */ - if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit ) + if ( n_contours >= 0xFFFU || p + 2 * n_contours + 2 > limit ) goto Invalid_Outline; /* reading the contours' endpoints & number of points */ cont = outline->contours; cont_limit = cont + n_contours; - last = -1; + n_points = 0; for ( ; cont < cont_limit; cont++ ) { *cont = FT_NEXT_USHORT( p ); - if ( *cont <= last ) + if ( *cont < n_points ) goto Invalid_Outline; - last = *cont; + n_points = *cont + 1U; } - n_points = last + 1; - - FT_TRACE5(( " # of points: %d\n", n_points )); + FT_TRACE5(( " # of points: %u\n", n_points )); /* note that we will add four phantom points later */ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); diff --git a/3rdparty/freetype/src/truetype/ttgxvar.c b/3rdparty/freetype/src/truetype/ttgxvar.c index 5ab6e17119c1..d006dab833e9 100644 --- a/3rdparty/freetype/src/truetype/ttgxvar.c +++ b/3rdparty/freetype/src/truetype/ttgxvar.c @@ -4025,13 +4025,13 @@ /* modeled after `af_iup_shift' */ static void - tt_delta_shift( int p1, - int p2, - int ref, + tt_delta_shift( FT_UInt p1, + FT_UInt p2, + FT_UInt ref, FT_Vector* in_points, FT_Vector* out_points ) { - int p; + FT_UInt p; FT_Vector delta; @@ -4062,14 +4062,14 @@ /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */ /* `Ins_IUP' with spec differences in handling ill-defined cases. */ static void - tt_delta_interpolate( int p1, - int p2, - int ref1, - int ref2, + tt_delta_interpolate( FT_UInt p1, + FT_UInt p2, + FT_UInt ref1, + FT_UInt ref2, FT_Vector* in_points, FT_Vector* out_points ) { - int p, i; + FT_UInt p, i; FT_Pos out, in1, in2, out1, out2, d1, d2; @@ -4135,24 +4135,18 @@ FT_Vector* in_points, FT_Bool* has_delta ) { - FT_Int first_point; - FT_Int end_point; + FT_UInt first_point; + FT_UInt end_point; - FT_Int first_delta; - FT_Int cur_delta; + FT_UInt first_delta; + FT_UInt cur_delta; - FT_Int point; - FT_Short contour; + FT_UInt point; + FT_UInt contour; - /* ignore empty outlines */ - if ( !outline->n_contours ) - return; - - contour = 0; - point = 0; - - do + for ( point = 0, contour = 0; + contour < outline->n_contours; contour++ ) { end_point = outline->contours[contour]; first_point = point; @@ -4213,9 +4207,7 @@ out_points ); } } - contour++; - - } while ( contour < outline->n_contours ); + } } diff --git a/3rdparty/freetype/src/truetype/ttinterp.c b/3rdparty/freetype/src/truetype/ttinterp.c index da21e1b8542c..a975cce7eb34 100644 --- a/3rdparty/freetype/src/truetype/ttinterp.c +++ b/3rdparty/freetype/src/truetype/ttinterp.c @@ -2841,7 +2841,13 @@ ARRAY_BOUND_ERROR; } else + { + Modify_CVT_Check( exc ); + if ( exc->error ) + return; + exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale ); + } } @@ -4923,37 +4929,38 @@ Compute_Point_Displacement( TT_ExecContext exc, FT_F26Dot6* x, FT_F26Dot6* y, - TT_GlyphZone zone, - FT_UShort* refp ) + FT_Vector* cur, + FT_UInt* refp ) { - TT_GlyphZoneRec zp; - FT_UShort p; - FT_F26Dot6 d; + TT_GlyphZone zp; + FT_UShort p; + FT_F26Dot6 d; if ( exc->opcode & 1 ) { - zp = exc->zp0; + zp = &exc->zp0; p = exc->GS.rp1; } else { - zp = exc->zp1; + zp = &exc->zp1; p = exc->GS.rp2; } - if ( BOUNDS( p, zp.n_points ) ) + if ( BOUNDS( p, zp->n_points ) ) { if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); - *refp = 0; return FAILURE; } - *zone = zp; - *refp = p; + /* return reference if zones match */ + if ( refp ) + *refp = cur == zp->cur ? p + : ~0U; /* nan */ - d = PROJECT( zp.cur + p, zp.org + p ); + d = PROJECT( zp->cur + p, zp->org + p ); *x = FT_MulFix( d, exc->moveVector.x ); *y = FT_MulFix( d, exc->moveVector.y ); @@ -4965,10 +4972,9 @@ /* See `ttinterp.h' for details on backward compatibility mode. */ static void Move_Zp2_Point( TT_ExecContext exc, - FT_UShort point, + FT_UInt point, FT_F26Dot6 dx, - FT_F26Dot6 dy, - FT_Bool touch ) + FT_F26Dot6 dy ) { if ( exc->GS.freeVector.x != 0 ) { @@ -4978,8 +4984,7 @@ #endif exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx ); - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; + exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; } if ( exc->GS.freeVector.y != 0 ) @@ -4990,8 +4995,7 @@ #endif exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy ); - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; + exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; } } @@ -5007,11 +5011,9 @@ FT_Long* args ) { FT_Long loop = exc->GS.loop; - TT_GlyphZoneRec zp; - FT_UShort refp; FT_F26Dot6 dx, dy; - FT_UShort point; + FT_UInt point; if ( exc->new_top < loop ) @@ -5023,12 +5025,12 @@ exc->new_top -= loop; - if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) + if ( Compute_Point_Displacement( exc, &dx, &dy, NULL, NULL ) ) return; while ( loop-- ) { - point = (FT_UShort)*(--args); + point = (FT_UInt)*(--args); if ( BOUNDS( point, exc->zp2.n_points ) ) { @@ -5039,7 +5041,7 @@ } } else - Move_Zp2_Point( exc, point, dx, dy, TRUE ); + Move_Zp2_Point( exc, point, dx, dy ); } Fail: @@ -5061,12 +5063,10 @@ Ins_SHC( TT_ExecContext exc, FT_Long* args ) { - TT_GlyphZoneRec zp; - FT_UShort refp; + FT_UInt refp, start, limit, i; FT_F26Dot6 dx, dy; FT_UShort contour, bounds; - FT_UShort start, limit, i; contour = (FT_UShort)args[0]; @@ -5079,7 +5079,7 @@ return; } - if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) + if ( Compute_Point_Displacement( exc, &dx, &dy, exc->zp2.cur, &refp ) ) return; if ( contour == 0 ) @@ -5095,8 +5095,8 @@ for ( i = start; i < limit; i++ ) { - if ( zp.cur != exc->zp2.cur || refp != i ) - Move_Zp2_Point( exc, i, dx, dy, TRUE ); + if ( refp != i ) + Move_Zp2_Point( exc, i, dx, dy ); } } @@ -5111,40 +5111,59 @@ Ins_SHZ( TT_ExecContext exc, FT_Long* args ) { - TT_GlyphZoneRec zp; - FT_UShort refp; - FT_F26Dot6 dx, - dy; - - FT_UShort limit, i; + FT_Vector* cur; + FT_UInt refp, i, limit; + FT_F26Dot6 dx, dy; - if ( BOUNDS( args[0], 2 ) ) + /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points, */ + /* which must be subtracted. */ + switch ( (FT_Int)args[0] ) { + case 0: + cur = exc->twilight.cur; + limit = exc->twilight.n_points; + break; + + case 1: + cur = exc->pts.cur; + limit = exc->pts.n_points > 4U ? exc->pts.n_points - 4U : 0; + break; + + default: if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; } - if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) + if ( Compute_Point_Displacement( exc, &dx, &dy, cur, &refp ) ) return; - /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */ - /* Twilight zone has no real contours, so use `n_points'. */ - /* Normal zone's `n_points' includes phantoms, so must */ - /* use end of last contour. */ - if ( exc->GS.gep2 == 0 ) - limit = exc->zp2.n_points; - else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 ) - limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1; - else - limit = 0; + /* XXX: UNDOCUMENTED! SHZ doesn't touch the points. */ + if ( dx ) + { +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( !exc->backward_compatibility ) +#endif + for ( i = 0; i < limit; i++ ) + { + if ( refp != i ) + cur[i].x = ADD_LONG( cur[i].x, dx ); + } + } - /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ - for ( i = 0; i < limit; i++ ) + if ( dy ) { - if ( zp.cur != exc->zp2.cur || refp != i ) - Move_Zp2_Point( exc, i, dx, dy, FALSE ); +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( exc->backward_compatibility != 0x7 ) +#endif + for ( i = 0; i < limit; i++ ) + { + if ( refp != i ) + cur[i].y = ADD_LONG( cur[i].y, dy ); + } } } @@ -5161,7 +5180,7 @@ { FT_Long loop = exc->GS.loop; FT_F26Dot6 dx, dy; - FT_UShort point; + FT_UInt point; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL FT_Bool in_twilight = FT_BOOL( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || @@ -5183,7 +5202,7 @@ while ( loop-- ) { - point = (FT_UShort)*(--args); + point = (FT_UInt)*(--args); if ( BOUNDS( point, exc->zp2.n_points ) ) { @@ -5206,11 +5225,11 @@ ( exc->backward_compatibility != 0x7 && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ) ) ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); + Move_Zp2_Point( exc, point, 0, dy ); } else #endif - Move_Zp2_Point( exc, point, dx, dy, TRUE ); + Move_Zp2_Point( exc, point, dx, dy ); } Fail: @@ -6191,14 +6210,14 @@ IUP_WorkerRec V; FT_Byte mask; - FT_UInt first_point; /* first point of contour */ - FT_UInt end_point; /* end point (last+1) of contour */ + FT_UInt first_point; /* first point of contour */ + FT_UInt end_point; /* end point (last+1) of contour */ - FT_UInt first_touched; /* first touched point in contour */ - FT_UInt cur_touched; /* current touched point in contour */ + FT_UInt first_touched; /* first touched point in contour */ + FT_UInt cur_touched; /* current touched point in contour */ - FT_UInt point; /* current point */ - FT_Short contour; /* current contour */ + FT_UInt point; /* current point */ + FT_UInt contour; /* current contour */ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL @@ -7339,56 +7358,11 @@ } if ( exc->error ) - { - switch ( exc->error ) - { - case FT_ERR( Invalid_Opcode ): - { - TT_DefRecord* def = exc->IDefs; - TT_DefRecord* limit = FT_OFFSET( def, exc->numIDefs ); - - - /* looking for redefined instructions */ - for ( ; def < limit; def++ ) - { - if ( def->active && exc->opcode == (FT_Byte)def->opc ) - { - TT_CallRec* callrec; - - - if ( exc->callTop >= exc->callSize ) - { - exc->error = FT_THROW( Invalid_Reference ); - goto LErrorLabel_; - } - - callrec = &exc->callStack[exc->callTop]; - - callrec->Caller_Range = exc->curRange; - callrec->Caller_IP = exc->IP + 1; - callrec->Cur_Count = 1; - callrec->Def = def; - - if ( Ins_Goto_CodeRange( exc, - def->range, - def->start ) == FAILURE ) - goto LErrorLabel_; - - goto LSuiteLabel_; - } - } - } - FALL_THROUGH; - - default: - goto LErrorLabel_; - } - } + goto LErrorLabel_; exc->top = exc->new_top; exc->IP += exc->length; - LSuiteLabel_: if ( exc->IP >= exc->codeSize ) { if ( exc->callTop > 0 )