[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.
This commit is contained in:
Alexei Podtelezhnikov 2025-07-26 07:00:51 -04:00
parent b04db3872c
commit d6022b6d6e

View file

@ -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;