Skip to content

Commit

Permalink
Use unsigned point and contour indexing in FT_Outline.
Browse files Browse the repository at this point in the history
This doubles the number or allowed points, see
    harfbuzz/harfbuzz#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.
  • Loading branch information
apodtele committed Jun 21, 2024
1 parent 2b9fdec commit 2a7bb45
Show file tree
Hide file tree
Showing 16 changed files with 65 additions and 58 deletions.
12 changes: 10 additions & 2 deletions docs/CHANGES
Original file line number Diff line number Diff line change
@@ -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
Expand Down
16 changes: 8 additions & 8 deletions include/freetype/ftimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,23 +345,23 @@ 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;

/* */

/* 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


/**************************************************************************
Expand Down
4 changes: 2 additions & 2 deletions include/freetype/internal/tttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
10 changes: 5 additions & 5 deletions src/autofit/afhints.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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++ )
Expand Down
2 changes: 1 addition & 1 deletion src/base/ftbbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions src/base/ftoutln.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions src/base/ftstroke.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++ )
Expand All @@ -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 );
}
Expand Down
2 changes: 1 addition & 1 deletion src/pfr/pfrgload.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions src/pshinter/pshalgo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/raster/ftraster.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down
2 changes: 1 addition & 1 deletion src/sdf/ftsdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion src/smooth/ftgrays.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down
29 changes: 14 additions & 15 deletions src/truetype/ttgload.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 |
Expand All @@ -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;
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 6 additions & 8 deletions src/truetype/ttinterp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) )
Expand All @@ -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++ )
{
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/truetype/ttobjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/truetype/ttobjs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 2a7bb45

Please sign in to comment.