Revert to signed span positioning.

In the context of FT_Outline_Render, the outline can be placed
arbitrarily and the resulting spans should be signed. This partially
reverts ef04e4eb20 and fixes #1410.  However, for internal use,
when outlines are placed in the first quadrant, we still can interpret
positions as unsigned.

* include/freetype/ftimage.h (FT_Span): Use signed position again.
* src/smooth/ftgrays.c (gray_sweep_direct): Sync with FT_Span.
* src/smooth/ftsmooth.c (ft_smooth_lcd_spans, ft_smooth_lcdv_spans,
ft_smooth_overlap_spans): Prevent sign extension.
This commit is contained in:
Alexei Podtelezhnikov 2026-05-17 12:29:34 -04:00
parent c0bac4c2d2
commit 7e0e56f84f
3 changed files with 13 additions and 9 deletions

View file

@ -875,7 +875,7 @@ FT_BEGIN_HEADER
*/
typedef struct FT_Span_
{
unsigned short x;
short x;
unsigned short len;
unsigned char coverage;

View file

@ -1805,7 +1805,7 @@ typedef ptrdiff_t FT_PtrDist;
FT_FILL_RULE( coverage, cover, fill );
span[n].coverage = (unsigned char)coverage;
span[n].x = (unsigned short)x;
span[n].x = (short)x;
span[n].len = (unsigned short)( cell->x - x );
if ( ++n == FT_MAX_GRAY_SPANS )
@ -1824,7 +1824,7 @@ typedef ptrdiff_t FT_PtrDist;
FT_FILL_RULE( coverage, area, fill );
span[n].coverage = (unsigned char)coverage;
span[n].x = (unsigned short)cell->x;
span[n].x = (short)cell->x;
span[n].len = 1;
if ( ++n == FT_MAX_GRAY_SPANS )

View file

@ -124,7 +124,8 @@
for ( ; count--; spans++ )
for ( dst = dst_line + spans->x * 3, w = spans->len; w--; dst += 3 )
for ( dst = dst_line + (unsigned short)spans->x * 3,
w = spans->len; w--; dst += 3 )
*dst = spans->coverage;
}
@ -290,7 +291,8 @@
for ( ; count--; spans++ )
for ( dst = dst_line + spans->x, w = spans->len; w--; dst++ )
for ( dst = dst_line + (unsigned short)spans->x,
w = spans->len; w--; dst++ )
{
dst[0] += ( spans->coverage * target->wght[0] + 85 ) >> 8;
dst[1] += ( spans->coverage * target->wght[1] + 85 ) >> 8;
@ -385,7 +387,8 @@
for ( ; count--; spans++ )
for ( dst = dst_line + spans->x, w = spans->len; w--; dst++ )
for ( dst = dst_line + (unsigned short)spans->x,
w = spans->len; w--; dst++ )
{
dst[ 0] += ( spans->coverage * target->wght[0] + 85 ) >> 8;
dst[ pitch] += ( spans->coverage * target->wght[1] + 85 ) >> 8;
@ -473,7 +476,7 @@
unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch;
unsigned short x;
unsigned int x, i;
unsigned int cover, sum;
@ -487,8 +490,9 @@
cover = ( spans->coverage + SCALE * SCALE / 2 ) / ( SCALE * SCALE );
for ( x = 0; x < spans->len; x++ )
{
sum = dst[( spans->x + x ) / SCALE] + cover;
dst[( spans->x + x ) / SCALE] = (unsigned char)( sum - ( sum >> 8 ) );
i = ( (unsigned short)spans->x + x ) / SCALE;
sum = dst[i] + cover;
dst[i] = (unsigned char)( sum - ( sum >> 8 ) );
}
}
}