From d6022b6d6ee2cd645fc2bcbe7ed2c19b18de7e45 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 26 Jul 2025 07:00:51 -0400 Subject: [PATCH] [smooth] Remove usage of setjmp and longjmp. To support WASM targets with slow or unsupported setjmp and longjmp, we eliminate these calls in favor of an error propagation model. When gray_set_cell is out of cells, it raises an exception which is later handled in gray_convert_glyph_inner. This is a less invasive alternative to !385. * src/smooth/ftgrays.c (gray_set_cell): Raise the overflow exception and redirect all work to `cell_null`. (gray_move,line,conic,cubic_to): Return the exception. (gray_convert_glyph, gray_convert_glyph_inner): Handle the exception. --- src/smooth/ftgrays.c | 65 +++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 4d3ddf74b..9964e37e3 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -157,10 +157,6 @@ #define ft_memset memset -#define ft_setjmp setjmp -#define ft_longjmp longjmp -#define ft_jmp_buf jmp_buf - typedef ptrdiff_t FT_PtrDist; @@ -495,6 +491,7 @@ typedef ptrdiff_t FT_PtrDist; TCoord min_ey, max_ey; TCoord count_ey; /* same as (max_ey - min_ey) */ + int error; /* pool overflow exception */ PCell cell; /* current cell */ PCell cell_free; /* call allocation next free slot */ PCell cell_null; /* last cell, used as dumpster and limit */ @@ -510,8 +507,6 @@ 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 ) @@ -613,9 +608,14 @@ typedef ptrdiff_t FT_PtrDist; } /* insert new cell */ - cell = ras.cell_free++; - if ( cell >= ras.cell_null ) - ft_longjmp( ras.jump_buffer, 1 ); + cell = ras.cell_free; + if ( cell == ras.cell_null ) + { + ras.error = FT_THROW( Raster_Overflow ); + goto Found; + } + + ras.cell_free = cell + 1; cell->x = ex; cell->area = 0; @@ -1353,7 +1353,8 @@ typedef ptrdiff_t FT_PtrDist; ras.x = x; ras.y = y; - return 0; + + return ras.error; } @@ -1365,7 +1366,8 @@ typedef ptrdiff_t FT_PtrDist; gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); - return 0; + + return ras.error; } @@ -1378,7 +1380,8 @@ typedef ptrdiff_t FT_PtrDist; gray_render_conic( RAS_VAR_ control, to ); - return 0; + + return ras.error; } @@ -1392,7 +1395,8 @@ typedef ptrdiff_t FT_PtrDist; gray_render_cubic( RAS_VAR_ control1, control2, to ); - return 0; + + return ras.error; } @@ -1700,30 +1704,22 @@ typedef ptrdiff_t FT_PtrDist; gray_convert_glyph_inner( RAS_ARG_ int continued ) { - volatile int error; + int error; - if ( ft_setjmp( ras.jump_buffer ) == 0 ) - { - if ( continued ) - FT_Trace_Disable(); - error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); - if ( continued ) - FT_Trace_Enable(); + if ( continued ) + FT_Trace_Disable(); + error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); + if ( continued ) + FT_Trace_Enable(); - FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n", - ras.min_ey, - ras.max_ey, - ras.cell_null - ras.cell_free, - ras.cell_null - ras.cell_free == 1 ? "" : "s" )); - } - else - { - error = FT_THROW( Raster_Overflow ); - - FT_TRACE7(( "band [%d..%d]: to be bisected\n", - ras.min_ey, ras.max_ey )); - } + FT_TRACE7(( error == Smooth_Err_Raster_Overflow + ? "band [%d..%d]: to be bisected\n" + : "band [%d..%d]: %td cell%s remaining\n", + ras.min_ey, + ras.max_ey, + ras.cell_null - ras.cell_free, + ras.cell_null - ras.cell_free == 1 ? "" : "s" )); return error; } @@ -1922,6 +1918,7 @@ typedef ptrdiff_t FT_PtrDist; ras.cell_free = buffer + n; ras.cell = ras.cell_null; + ras.error = Smooth_Err_Ok; error = gray_convert_glyph_inner( RAS_VAR_ continued ); continued = 1;