From 8d96b52ac5e6ec4b6a127a8324c803bcf2732c45 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 5 Sep 2011 09:59:28 +0200 Subject: freetype 2.4.6 --- freetype/src/base/ftobjs.c | 6 + freetype/src/base/ftpatent.c | 2 +- freetype/src/base/ftstroke.c | 809 ++++++++++++++++++++++++++++----------- freetype/src/base/ftsystem.c | 4 +- freetype/src/bdf/bdflib.c | 29 +- freetype/src/cff/cffparse.c | 31 +- freetype/src/psaux/t1decode.c | 90 +++-- freetype/src/sfnt/sfobjs.c | 59 ++- freetype/src/truetype/ttdriver.c | 3 + freetype/src/truetype/ttobjs.c | 75 ++++ freetype/src/type1/t1load.c | 6 +- 11 files changed, 802 insertions(+), 312 deletions(-) (limited to 'freetype/src') diff --git a/freetype/src/base/ftobjs.c b/freetype/src/base/ftobjs.c index c627c0b5b..5069afb2c 100644 --- a/freetype/src/base/ftobjs.c +++ b/freetype/src/base/ftobjs.c @@ -155,6 +155,9 @@ (const FT_Byte*)args->memory_base, args->memory_size ); } + +#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT + else if ( args->flags & FT_OPEN_PATHNAME ) { /* create a normal system stream */ @@ -170,6 +173,9 @@ FT_FREE( stream ); stream = args->stream; } + +#endif + else error = FT_Err_Invalid_Argument; diff --git a/freetype/src/base/ftpatent.c b/freetype/src/base/ftpatent.c index 501cab52c..82b42f034 100644 --- a/freetype/src/base/ftpatent.c +++ b/freetype/src/base/ftpatent.c @@ -269,7 +269,7 @@ #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ - !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER ) + !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) if ( face && FT_IS_SFNT( face ) ) { result = !face->internal->ignore_unpatented_hinter; diff --git a/freetype/src/base/ftstroke.c b/freetype/src/base/ftstroke.c index cd4bf0433..3f24f9ee8 100644 --- a/freetype/src/base/ftstroke.c +++ b/freetype/src/base/ftstroke.c @@ -34,7 +34,7 @@ return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT - : FT_STROKER_BORDER_LEFT ; + : FT_STROKER_BORDER_LEFT; } @@ -47,20 +47,21 @@ return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT - : FT_STROKER_BORDER_RIGHT ; + : FT_STROKER_BORDER_RIGHT; } - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** BEZIER COMPUTATIONS *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BEZIER COMPUTATIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ #define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 ) -#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 6 ) +#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 ) + #define FT_EPSILON 2 #define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON ) @@ -69,7 +70,7 @@ static FT_Pos ft_pos_abs( FT_Pos x ) { - return x >= 0 ? x : -x ; + return x >= 0 ? x : -x; } @@ -114,18 +115,28 @@ if ( close1 ) { if ( close2 ) - *angle_in = *angle_out = 0; + { + /* basically a point; */ + /* do nothing to retain original direction */ + } else - *angle_in = *angle_out = FT_Atan2( d2.x, d2.y ); - } - else if ( close2 ) - { - *angle_in = *angle_out = FT_Atan2( d1.x, d1.y ); + { + *angle_in = + *angle_out = FT_Atan2( d2.x, d2.y ); + } } - else + else /* !close1 */ { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_out = FT_Atan2( d2.x, d2.y ); + if ( close2 ) + { + *angle_in = + *angle_out = FT_Atan2( d1.x, d1.y ); + } + else + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_out = FT_Atan2( d2.x, d2.y ); + } } theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) ); @@ -162,6 +173,17 @@ } + /* Return the average of `angle1' and `angle2'. */ + /* This gives correct result even if `angle1' and `angle2' */ + /* have opposite signs. */ + static FT_Angle + ft_angle_mean( FT_Angle angle1, + FT_Angle angle2 ) + { + return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2; + } + + static FT_Bool ft_cubic_is_small_enough( FT_Vector* base, FT_Angle *angle_in, @@ -184,34 +206,70 @@ close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y ); - if ( close1 || close3 ) + if ( close1 ) { if ( close2 ) { - /* basically a point */ - *angle_in = *angle_out = *angle_mid = 0; - } - else if ( close1 ) - { - *angle_in = *angle_mid = FT_Atan2( d2.x, d2.y ); - *angle_out = FT_Atan2( d3.x, d3.y ); + if ( close3 ) + { + /* basically a point; */ + /* do nothing to retain original direction */ + } + else /* !close3 */ + { + *angle_in = + *angle_mid = + *angle_out = FT_Atan2( d3.x, d3.y ); + } } - else /* close2 */ + else /* !close2 */ { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y ); + if ( close3 ) + { + *angle_in = + *angle_mid = + *angle_out = FT_Atan2( d2.x, d2.y ); + } + else /* !close3 */ + { + *angle_in = + *angle_mid = FT_Atan2( d2.x, d2.y ); + *angle_out = FT_Atan2( d3.x, d3.y ); + } } } - else if ( close2 ) - { - *angle_in = *angle_mid = FT_Atan2( d1.x, d1.y ); - *angle_out = FT_Atan2( d3.x, d3.y ); - } - else + else /* !close1 */ { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_mid = FT_Atan2( d2.x, d2.y ); - *angle_out = FT_Atan2( d3.x, d3.y ); + if ( close2 ) + { + if ( close3 ) + { + *angle_in = + *angle_mid = + *angle_out = FT_Atan2( d1.x, d1.y ); + } + else /* !close3 */ + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_out = FT_Atan2( d3.x, d3.y ); + *angle_mid = ft_angle_mean( *angle_in, *angle_out ); + } + } + else /* !close2 */ + { + if ( close3 ) + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_mid = + *angle_out = FT_Atan2( d2.x, d2.y ); + } + else /* !close3 */ + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_mid = FT_Atan2( d2.x, d2.y ); + *angle_out = FT_Atan2( d3.x, d3.y ); + } + } } theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) ); @@ -222,13 +280,13 @@ } - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** STROKE BORDERS *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** STROKE BORDERS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ typedef enum FT_StrokeTags_ { @@ -239,7 +297,7 @@ } FT_StrokeTags; -#define FT_STROKE_TAG_BEGIN_END (FT_STROKE_TAG_BEGIN|FT_STROKE_TAG_END) +#define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ) typedef struct FT_StrokeBorderRec_ { @@ -247,7 +305,7 @@ FT_UInt max_points; FT_Vector* points; FT_Byte* tags; - FT_Bool movable; + FT_Bool movable; /* TRUE for ends of lineto borders */ FT_Int start; /* index of current sub-path start point */ FT_Memory memory; FT_Bool valid; @@ -368,6 +426,12 @@ } else { + /* don't add zero-length lineto */ + if ( border->num_points > 0 && + FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) && + FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) ) + return error; + /* add one point */ error = ft_stroke_border_grow( border, 1 ); if ( !error ) @@ -403,6 +467,7 @@ FT_Vector* vec = border->points + border->num_points; FT_Byte* tag = border->tags + border->num_points; + vec[0] = *control; vec[1] = *to; @@ -411,7 +476,9 @@ border->num_points += 2; } + border->movable = FALSE; + return error; } @@ -444,7 +511,9 @@ border->num_points += 3; } + border->movable = FALSE; + return error; } @@ -530,7 +599,7 @@ if ( border->start >= 0 ) ft_stroke_border_close( border, FALSE ); - border->start = border->num_points; + border->start = border->num_points; border->movable = FALSE; return ft_stroke_border_lineto( border, to, FALSE ); @@ -673,34 +742,38 @@ } } - outline->n_points = (short)( outline->n_points + border->num_points ); + outline->n_points = (short)( outline->n_points + border->num_points ); FT_ASSERT( FT_Outline_Check( outline ) == 0 ); } - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** STROKER *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** STROKER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ #define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI ) typedef struct FT_StrokerRec_ { - FT_Angle angle_in; - FT_Angle angle_out; - FT_Vector center; - FT_Bool first_point; - FT_Bool subpath_open; - FT_Angle subpath_angle; - FT_Vector subpath_start; + FT_Angle angle_in; /* direction into curr join */ + FT_Angle angle_out; /* direction out of join */ + FT_Vector center; /* current position */ + FT_Fixed line_length; /* length of last lineto */ + FT_Bool first_point; /* is this the start? */ + FT_Bool subpath_open; /* is the subpath open? */ + FT_Angle subpath_angle; /* subpath start direction */ + FT_Vector subpath_start; /* subpath start position */ + FT_Fixed subpath_line_length; /* subpath start lineto len */ + FT_Bool handle_wide_strokes; /* use wide strokes logic? */ FT_Stroker_LineCap line_cap; FT_Stroker_LineJoin line_join; + FT_Stroker_LineJoin line_join_saved; FT_Fixed miter_limit; FT_Fixed radius; @@ -733,7 +806,9 @@ ft_stroke_border_init( &stroker->borders[0], memory ); ft_stroke_border_init( &stroker->borders[1], memory ); } + *astroker = stroker; + return error; } @@ -752,6 +827,14 @@ stroker->line_join = line_join; stroker->miter_limit = miter_limit; + /* ensure miter limit has sensible value */ + if ( stroker->miter_limit < 0x10000 ) + stroker->miter_limit = 0x10000; + + /* save line join style: */ + /* line join style can be temporarily changed when stroking curves */ + stroker->line_join_saved = line_join; + FT_Stroker_Rewind( stroker ); } @@ -788,7 +871,7 @@ } - /* creates a circular arc at a corner or cap */ + /* create a circular arc at a corner or cap */ static FT_Error ft_stroker_arcto( FT_Stroker stroker, FT_Int side ) @@ -815,7 +898,7 @@ } - /* adds a cap at the end of an opened path */ + /* add a cap at the end of an opened path */ static FT_Error ft_stroker_cap( FT_Stroker stroker, FT_Angle angle, @@ -829,6 +912,7 @@ /* add a round cap */ stroker->angle_in = angle; stroker->angle_out = angle + FT_ANGLE_PI; + error = ft_stroker_arcto( stroker, side ); } else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE ) @@ -881,7 +965,7 @@ delta.x += stroker->center.x; delta.y += stroker->center.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); + error = ft_stroke_border_lineto( border, &delta, FALSE ); } Exit: @@ -892,40 +976,52 @@ /* process an inside corner, i.e. compute intersection */ static FT_Error ft_stroker_inside( FT_Stroker stroker, - FT_Int side) + FT_Int side, + FT_Fixed line_length ) { FT_StrokeBorder border = stroker->borders + side; FT_Angle phi, theta, rotate; - FT_Fixed length, thcos, sigma; + FT_Fixed length, thcos; FT_Vector delta; FT_Error error = FT_Err_Ok; + FT_Bool intersect; /* use intersection of lines? */ rotate = FT_SIDE_TO_ROTATE( side ); - /* compute median angle */ - theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); - if ( theta == FT_ANGLE_PI ) - theta = rotate; + theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2; + + /* Only intersect borders if between two lineto's and both */ + /* lines are long enough (line_length is zero for curves). */ + if ( !border->movable || line_length == 0 ) + intersect = FALSE; else - theta = theta / 2; + { + /* compute minimum required length of lines */ + FT_Fixed min_length = ft_pos_abs( FT_MulFix( stroker->radius, + FT_Tan( theta ) ) ); - phi = stroker->angle_in + theta; - thcos = FT_Cos( theta ); - sigma = FT_MulFix( stroker->miter_limit, thcos ); + intersect = FT_BOOL( stroker->line_length >= min_length && + line_length >= min_length ); + } - /* TODO: find better criterion to switch off the optimization */ - if ( sigma < 0x10000L ) + if ( !intersect ) { FT_Vector_From_Polar( &delta, stroker->radius, stroker->angle_out + rotate ); delta.x += stroker->center.x; delta.y += stroker->center.y; + border->movable = FALSE; } else { + /* compute median angle */ + phi = stroker->angle_in + theta; + + thcos = FT_Cos( theta ); + length = FT_DivFix( stroker->radius, thcos ); FT_Vector_From_Polar( &delta, length, phi + rotate ); @@ -942,7 +1038,8 @@ /* process an outside corner, i.e. compute bevel/miter/round */ static FT_Error ft_stroker_outside( FT_Stroker stroker, - FT_Int side ) + FT_Int side, + FT_Fixed line_length ) { FT_StrokeBorder border = stroker->borders + side; FT_Error error; @@ -953,79 +1050,119 @@ error = ft_stroker_arcto( stroker, side ); else { - /* this is a mitered or beveled corner */ - FT_Fixed sigma, radius = stroker->radius; - FT_Angle theta, phi; - FT_Fixed thcos; - FT_Bool miter; + /* this is a mitered (pointed) or beveled (truncated) corner */ + FT_Fixed sigma = 0, radius = stroker->radius; + FT_Angle theta = 0, phi = 0; + FT_Fixed thcos = 0; + FT_Bool bevel, fixed_bevel; rotate = FT_SIDE_TO_ROTATE( side ); - miter = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER ); - theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); - if ( theta == FT_ANGLE_PI ) + bevel = + FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL ); + + fixed_bevel = + FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE ); + + if ( !bevel ) { - theta = rotate; - phi = stroker->angle_in; + theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + + if ( theta == FT_ANGLE_PI ) + { + theta = rotate; + phi = stroker->angle_in; + } + else + { + theta /= 2; + phi = stroker->angle_in + theta + rotate; + } + + thcos = FT_Cos( theta ); + sigma = FT_MulFix( stroker->miter_limit, thcos ); + + /* is miter limit exceeded? */ + if ( sigma < 0x10000L ) + { + /* don't create variable bevels for very small deviations; */ + /* FT_Sin(x) = 0 for x <= 57 */ + if ( fixed_bevel || ft_pos_abs( theta ) > 57 ) + bevel = TRUE; + } } - else + + if ( bevel ) /* this is a bevel (broken angle) */ { - theta = theta / 2; - phi = stroker->angle_in + theta + rotate; - } + if ( fixed_bevel ) + { + /* the outer corners are simply joined together */ + FT_Vector delta; - thcos = FT_Cos( theta ); - sigma = FT_MulFix( stroker->miter_limit, thcos ); - /* FT_Sin(x) = 0 for x <= 57 */ - if ( sigma >= 0x10000L || ft_pos_abs( theta ) <= 57 ) - miter = FALSE; + /* add bevel */ + FT_Vector_From_Polar( &delta, + radius, + stroker->angle_out + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; - if ( miter ) /* this is a miter (broken angle) */ - { - FT_Vector middle, delta; - FT_Fixed length; + border->movable = FALSE; + error = ft_stroke_border_lineto( border, &delta, FALSE ); + } + else /* variable bevel */ + { + /* the miter is truncated */ + FT_Vector middle, delta; + FT_Fixed length; - /* compute middle point */ - FT_Vector_From_Polar( &middle, - FT_MulFix( radius, stroker->miter_limit ), - phi ); - middle.x += stroker->center.x; - middle.y += stroker->center.y; + /* compute middle point */ + FT_Vector_From_Polar( &middle, + FT_MulFix( radius, stroker->miter_limit ), + phi ); + middle.x += stroker->center.x; + middle.y += stroker->center.y; - /* compute first angle point */ - length = FT_MulFix( radius, - FT_DivFix( 0x10000L - sigma, - ft_pos_abs( FT_Sin( theta ) ) ) ); + /* compute first angle point */ + length = FT_MulFix( radius, + FT_DivFix( 0x10000L - sigma, + ft_pos_abs( FT_Sin( theta ) ) ) ); - FT_Vector_From_Polar( &delta, length, phi + rotate ); - delta.x += middle.x; - delta.y += middle.y; + FT_Vector_From_Polar( &delta, length, phi + rotate ); + delta.x += middle.x; + delta.y += middle.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; + error = ft_stroke_border_lineto( border, &delta, FALSE ); + if ( error ) + goto Exit; - /* compute second angle point */ - FT_Vector_From_Polar( &delta, length, phi - rotate ); - delta.x += middle.x; - delta.y += middle.y; + /* compute second angle point */ + FT_Vector_From_Polar( &delta, length, phi - rotate ); + delta.x += middle.x; + delta.y += middle.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; + error = ft_stroke_border_lineto( border, &delta, FALSE ); + if ( error ) + goto Exit; - /* finally, add a movable end point */ - FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; + /* finally, add an end point; only needed if not lineto */ + /* (line_length is zero for curves) */ + if ( line_length == 0 ) + { + FT_Vector_From_Polar( &delta, + radius, + stroker->angle_out + rotate ); - error = ft_stroke_border_lineto( border, &delta, TRUE ); - } + delta.x += stroker->center.x; + delta.y += stroker->center.y; - else /* this is a bevel (intersection) */ + error = ft_stroke_border_lineto( border, &delta, FALSE ); + } + } + } + else /* this is a miter (intersection) */ { FT_Fixed length; FT_Vector delta; @@ -1041,13 +1178,18 @@ if ( error ) goto Exit; - /* now add end point */ - FT_Vector_From_Polar( &delta, stroker->radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; + /* now add an end point; only needed if not lineto */ + /* (line_length is zero for curves) */ + if ( line_length == 0 ) + { + FT_Vector_From_Polar( &delta, + stroker->radius, + stroker->angle_out + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; - error = ft_stroke_border_lineto( border, &delta, TRUE ); + error = ft_stroke_border_lineto( border, &delta, FALSE ); + } } } @@ -1057,7 +1199,8 @@ static FT_Error - ft_stroker_process_corner( FT_Stroker stroker ) + ft_stroker_process_corner( FT_Stroker stroker, + FT_Fixed line_length ) { FT_Error error = FT_Err_Ok; FT_Angle turn; @@ -1078,12 +1221,12 @@ inside_side = 1; /* process the inside side */ - error = ft_stroker_inside( stroker, inside_side ); + error = ft_stroker_inside( stroker, inside_side, line_length ); if ( error ) goto Exit; /* process the outside side */ - error = ft_stroker_outside( stroker, 1 - inside_side ); + error = ft_stroker_outside( stroker, 1 - inside_side, line_length ); Exit: return error; @@ -1094,7 +1237,8 @@ /* start of the subpath */ static FT_Error ft_stroker_subpath_start( FT_Stroker stroker, - FT_Angle start_angle ) + FT_Angle start_angle, + FT_Fixed line_length ) { FT_Vector delta; FT_Vector point; @@ -1119,9 +1263,11 @@ border++; error = ft_stroke_border_moveto( border, &point ); - /* save angle for last cap */ - stroker->subpath_angle = start_angle; - stroker->first_point = FALSE; + /* save angle, position, and line length for last join */ + /* (line_length is zero for curves) */ + stroker->subpath_angle = start_angle; + stroker->first_point = FALSE; + stroker->subpath_line_length = line_length; Exit: return error; @@ -1139,10 +1285,19 @@ FT_Vector delta; FT_Angle angle; FT_Int side; + FT_Fixed line_length; + delta.x = to->x - stroker->center.x; delta.y = to->y - stroker->center.y; + /* a zero-length lineto is a no-op; avoid creating a spurious corner */ + if ( delta.x == 0 && delta.y == 0 ) + goto Exit; + + /* compute length of line */ + line_length = FT_Vector_Length( &delta ); + angle = FT_Atan2( delta.x, delta.y ); FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 ); @@ -1152,7 +1307,7 @@ /* This is the first segment of a subpath. We need to */ /* add a point to each border at their respective starting */ /* point locations. */ - error = ft_stroker_subpath_start( stroker, angle ); + error = ft_stroker_subpath_start( stroker, angle, line_length ); if ( error ) goto Exit; } @@ -1160,13 +1315,12 @@ { /* process the current corner */ stroker->angle_out = angle; - error = ft_stroker_process_corner( stroker ); + error = ft_stroker_process_corner( stroker, line_length ); if ( error ) goto Exit; } /* now add a line segment to both the `inside' and `outside' paths */ - for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) { FT_Vector point; @@ -1175,6 +1329,7 @@ point.x = to->x + delta.x; point.y = to->y + delta.y; + /* the ends of lineto borders are movable */ error = ft_stroke_border_lineto( border, &point, TRUE ); if ( error ) goto Exit; @@ -1183,8 +1338,9 @@ delta.y = -delta.y; } - stroker->angle_in = angle; - stroker->center = *to; + stroker->angle_in = angle; + stroker->center = *to; + stroker->line_length = line_length; Exit: return error; @@ -1202,10 +1358,20 @@ FT_Vector bez_stack[34]; FT_Vector* arc; FT_Vector* limit = bez_stack + 30; - FT_Angle start_angle; FT_Bool first_arc = TRUE; + /* if all control points are coincident, this is a no-op; */ + /* avoid creating a spurious corner */ + if ( FT_IS_SMALL( stroker->center.x - control->x ) && + FT_IS_SMALL( stroker->center.y - control->y ) && + FT_IS_SMALL( control->x - to->x ) && + FT_IS_SMALL( control->y - to->y ) ) + { + stroker->center = *to; + goto Exit; + } + arc = bez_stack; arc[0] = *to; arc[1] = *control; @@ -1216,11 +1382,15 @@ FT_Angle angle_in, angle_out; - angle_in = angle_out = 0; /* remove compiler warnings */ + /* initialize with current direction */ + angle_in = angle_out = stroker->angle_in; if ( arc < limit && !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) ) { + if ( stroker->first_point ) + stroker->angle_in = angle_in; + ft_conic_split( arc ); arc += 2; continue; @@ -1230,32 +1400,54 @@ { first_arc = FALSE; - start_angle = angle_in; - /* process corner if necessary */ if ( stroker->first_point ) - error = ft_stroker_subpath_start( stroker, start_angle ); + error = ft_stroker_subpath_start( stroker, angle_in, 0 ); else { - stroker->angle_out = start_angle; - error = ft_stroker_process_corner( stroker ); + stroker->angle_out = angle_in; + error = ft_stroker_process_corner( stroker, 0 ); } } + else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > + FT_SMALL_CONIC_THRESHOLD / 4 ) + { + /* if the deviation from one arc to the next is too great, */ + /* add a round corner */ + stroker->center = arc[2]; + stroker->angle_out = angle_in; + stroker->line_join = FT_STROKER_LINEJOIN_ROUND; + + error = ft_stroker_process_corner( stroker, 0 ); + + /* reinstate line join style */ + stroker->line_join = stroker->line_join_saved; + } + + if ( error ) + goto Exit; /* the arc's angle is small enough; we can add it directly to each */ /* border */ { - FT_Vector ctrl, end; - FT_Angle theta, phi, rotate; - FT_Fixed length; - FT_Int side; + FT_Vector ctrl, end; + FT_Angle theta, phi, rotate, alpha0 = 0; + FT_Fixed length; + FT_StrokeBorder border; + FT_Int side; theta = FT_Angle_Diff( angle_in, angle_out ) / 2; phi = angle_in + theta; length = FT_DivFix( stroker->radius, FT_Cos( theta ) ); - for ( side = 0; side <= 1; side++ ) + /* compute direction of original arc */ + if ( stroker->handle_wide_strokes ) + alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y ); + + for ( border = stroker->borders, side = 0; + side <= 1; + side++, border++ ) { rotate = FT_SIDE_TO_ROTATE( side ); @@ -1269,8 +1461,70 @@ end.x += arc[0].x; end.y += arc[0].y; - error = ft_stroke_border_conicto( stroker->borders + side, - &ctrl, &end ); + if ( stroker->handle_wide_strokes ) + { + FT_Vector start; + FT_Angle alpha1; + + + /* determine whether the border radius is greater than the */ + /* radius of curvature of the original arc */ + start = border->points[border->num_points - 1]; + + alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); + + /* is the direction of the border arc opposite to */ + /* that of the original arc? */ + if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > + FT_ANGLE_PI / 2 ) + { + FT_Angle beta, gamma; + FT_Vector bvec, delta; + FT_Fixed blen, sinA, sinB, alen; + + + /* use the sine rule to find the intersection point */ + beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y ); + gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); + + bvec.x = end.x - start.x; + bvec.y = end.y - start.y; + + blen = FT_Vector_Length( &bvec ); + + sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); + sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); + + alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB ); + + FT_Vector_From_Polar( &delta, alen, beta ); + delta.x += start.x; + delta.y += start.y; + + /* circumnavigate the negative sector backwards */ + border->movable = FALSE; + error = ft_stroke_border_lineto( border, &delta, FALSE ); + if ( error ) + goto Exit; + error = ft_stroke_border_lineto( border, &end, FALSE ); + if ( error ) + goto Exit; + error = ft_stroke_border_conicto( border, &ctrl, &start ); + if ( error ) + goto Exit; + /* and then move to the endpoint */ + error = ft_stroke_border_lineto( border, &end, FALSE ); + if ( error ) + goto Exit; + + continue; + } + + /* else fall through */ + } + + /* simply add an arc */ + error = ft_stroke_border_conicto( border, &ctrl, &end ); if ( error ) goto Exit; } @@ -1278,8 +1532,7 @@ arc -= 2; - if ( arc < bez_stack ) - stroker->angle_in = angle_out; + stroker->angle_in = angle_out; } stroker->center = *to; @@ -1301,10 +1554,22 @@ FT_Vector bez_stack[37]; FT_Vector* arc; FT_Vector* limit = bez_stack + 32; - FT_Angle start_angle; FT_Bool first_arc = TRUE; + /* if all control points are coincident, this is a no-op; */ + /* avoid creating a spurious corner */ + if ( FT_IS_SMALL( stroker->center.x - control1->x ) && + FT_IS_SMALL( stroker->center.y - control1->y ) && + FT_IS_SMALL( control1->x - control2->x ) && + FT_IS_SMALL( control1->y - control2->y ) && + FT_IS_SMALL( control2->x - to->x ) && + FT_IS_SMALL( control2->y - to->y ) ) + { + stroker->center = *to; + goto Exit; + } + arc = bez_stack; arc[0] = *to; arc[1] = *control2; @@ -1316,13 +1581,16 @@ FT_Angle angle_in, angle_mid, angle_out; - /* remove compiler warnings */ - angle_in = angle_out = angle_mid = 0; + /* initialize with current direction */ + angle_in = angle_out = angle_mid = stroker->angle_in; if ( arc < limit && !ft_cubic_is_small_enough( arc, &angle_in, &angle_mid, &angle_out ) ) { + if ( stroker->first_point ) + stroker->angle_in = angle_in; + ft_cubic_split( arc ); arc += 3; continue; @@ -1333,36 +1601,56 @@ first_arc = FALSE; /* process corner if necessary */ - start_angle = angle_in; - if ( stroker->first_point ) - error = ft_stroker_subpath_start( stroker, start_angle ); + error = ft_stroker_subpath_start( stroker, angle_in, 0 ); else { - stroker->angle_out = start_angle; - error = ft_stroker_process_corner( stroker ); + stroker->angle_out = angle_in; + error = ft_stroker_process_corner( stroker, 0 ); } - if ( error ) - goto Exit; + } + else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > + FT_SMALL_CUBIC_THRESHOLD / 4 ) + { + /* if the deviation from one arc to the next is too great, */ + /* add a round corner */ + stroker->center = arc[3]; + stroker->angle_out = angle_in; + stroker->line_join = FT_STROKER_LINEJOIN_ROUND; + + error = ft_stroker_process_corner( stroker, 0 ); + + /* reinstate line join style */ + stroker->line_join = stroker->line_join_saved; } + if ( error ) + goto Exit; + /* the arc's angle is small enough; we can add it directly to each */ /* border */ { - FT_Vector ctrl1, ctrl2, end; - FT_Angle theta1, phi1, theta2, phi2, rotate; - FT_Fixed length1, length2; - FT_Int side; + FT_Vector ctrl1, ctrl2, end; + FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0; + FT_Fixed length1, length2; + FT_StrokeBorder border; + FT_Int side; - theta1 = ft_pos_abs( angle_mid - angle_in ) / 2; - theta2 = ft_pos_abs( angle_out - angle_mid ) / 2; - phi1 = (angle_mid + angle_in ) / 2; - phi2 = (angle_mid + angle_out ) / 2; + theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2; + theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2; + phi1 = ft_angle_mean( angle_in, angle_mid ); + phi2 = ft_angle_mean( angle_mid, angle_out ); length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) ); length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) ); - for ( side = 0; side <= 1; side++ ) + /* compute direction of original arc */ + if ( stroker->handle_wide_strokes ) + alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y ); + + for ( border = stroker->borders, side = 0; + side <= 1; + side++, border++ ) { rotate = FT_SIDE_TO_ROTATE( side ); @@ -1380,16 +1668,81 @@ end.x += arc[0].x; end.y += arc[0].y; - error = ft_stroke_border_cubicto( stroker->borders + side, - &ctrl1, &ctrl2, &end ); + if ( stroker->handle_wide_strokes ) + { + FT_Vector start; + FT_Angle alpha1; + + + /* determine whether the border radius is greater than the */ + /* radius of curvature of the original arc */ + start = border->points[border->num_points - 1]; + + alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); + + /* is the direction of the border arc opposite to */ + /* that of the original arc? */ + if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > + FT_ANGLE_PI / 2 ) + { + FT_Angle beta, gamma; + FT_Vector bvec, delta; + FT_Fixed blen, sinA, sinB, alen; + + + /* use the sine rule to find the intersection point */ + beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y ); + gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); + + bvec.x = end.x - start.x; + bvec.y = end.y - start.y; + + blen = FT_Vector_Length( &bvec ); + + sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); + sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); + + alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB ); + + FT_Vector_From_Polar( &delta, alen, beta ); + delta.x += start.x; + delta.y += start.y; + + /* circumnavigate the negative sector backwards */ + border->movable = FALSE; + error = ft_stroke_border_lineto( border, &delta, FALSE ); + if ( error ) + goto Exit; + error = ft_stroke_border_lineto( border, &end, FALSE ); + if ( error ) + goto Exit; + error = ft_stroke_border_cubicto( border, + &ctrl2, + &ctrl1, + &start ); + if ( error ) + goto Exit; + /* and then move to the endpoint */ + error = ft_stroke_border_lineto( border, &end, FALSE ); + if ( error ) + goto Exit; + + continue; + } + + /* else fall through */ + } + + /* simply add an arc */ + error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end ); if ( error ) goto Exit; } } arc -= 3; - if ( arc < bez_stack ) - stroker->angle_in = angle_out; + + stroker->angle_in = angle_out; } stroker->center = *to; @@ -1414,9 +1767,21 @@ stroker->center = *to; stroker->subpath_open = open; + /* Determine if we need to check whether the border radius is greater */ + /* than the radius of curvature of a curve, to handle this case */ + /* specially. This is only required if bevel joins or butt caps may */ + /* be created, because round & miter joins and round & square caps */ + /* cover the negative sector created with wide strokes. */ + stroker->handle_wide_strokes = + FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND || + ( stroker->subpath_open && + stroker->line_cap == FT_STROKER_LINECAP_BUTT ) ); + /* record the subpath start point for each border */ stroker->subpath_start = *to; + stroker->angle_in = 0; + return FT_Err_Ok; } @@ -1446,6 +1811,7 @@ FT_Vector* src_point = left->points + left->num_points - 1; FT_Byte* src_tag = left->tags + left->num_points - 1; + while ( src_point >= left->points + left->start ) { *dst_point = *src_point; @@ -1455,14 +1821,14 @@ dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END; else { - FT_Byte ttag = (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END ); + FT_Byte ttag = + (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END ); /* switch begin/end tags if necessary */ if ( ttag == FT_STROKE_TAG_BEGIN || ttag == FT_STROKE_TAG_END ) dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END; - } src_point--; @@ -1497,6 +1863,7 @@ { FT_StrokeBorder right = stroker->borders; + /* All right, this is an opened path, we need to add a cap between */ /* right & left, add the reverse of left, then add a final cap */ /* between left & right. */ @@ -1525,13 +1892,14 @@ FT_Angle turn; FT_Int inside_side; + /* close the path if needed */ if ( stroker->center.x != stroker->subpath_start.x || stroker->center.y != stroker->subpath_start.y ) { - error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); - if ( error ) - goto Exit; + error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); + if ( error ) + goto Exit; } /* process the corner */ @@ -1549,19 +1917,23 @@ if ( turn < 0 ) inside_side = 1; - error = ft_stroker_inside( stroker, inside_side ); + error = ft_stroker_inside( stroker, + inside_side, + stroker->subpath_line_length ); if ( error ) goto Exit; /* process the outside side */ - error = ft_stroker_outside( stroker, 1 - inside_side ); + error = ft_stroker_outside( stroker, + 1 - inside_side, + stroker->subpath_line_length ); if ( error ) goto Exit; } /* then end our two subpaths */ - ft_stroke_border_close( stroker->borders + 0, TRUE ); - ft_stroke_border_close( stroker->borders + 1, FALSE ); + ft_stroke_border_close( stroker->borders + 0, FALSE ); + ft_stroke_border_close( stroker->borders + 1, TRUE ); } Exit: @@ -1683,9 +2055,9 @@ FT_Error error; - FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ - FT_Int tag; /* current point's state */ + FT_Int n; /* index of contour in outline */ + FT_UInt first; /* index of first point in contour */ + FT_Int tag; /* current point's state */ if ( !outline || !stroker ) @@ -1866,9 +2238,10 @@ return FT_Err_Invalid_Outline; } -/* declare an extern to access ft_outline_glyph_class global allocated - in ftglyph.c, and use the FT_OUTLINE_GLYPH_CLASS_GET macro to access - it when FT_CONFIG_OPTION_PIC is defined */ + + /* declare an extern to access `ft_outline_glyph_class' globally */ + /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */ + /* macro to access it when FT_CONFIG_OPTION_PIC is defined */ #ifndef FT_CONFIG_OPTION_PIC extern const FT_Glyph_Class ft_outline_glyph_class; #endif @@ -1882,10 +2255,12 @@ FT_Stroker stroker, FT_Bool destroy ) { - FT_Error error = FT_Err_Invalid_Argument; - FT_Glyph glyph = NULL; - FT_Library library = stroker->library; - FT_UNUSED(library); + FT_Error error = FT_Err_Invalid_Argument; + FT_Glyph glyph = NULL; + FT_Library library = stroker->library; + + FT_UNUSED( library ); + if ( pglyph == NULL ) goto Exit; @@ -1906,7 +2281,7 @@ } { - FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph; + FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; FT_Outline* outline = &oglyph->outline; FT_UInt num_points, num_contours; @@ -1956,10 +2331,12 @@ FT_Bool inside, FT_Bool destroy ) { - FT_Error error = FT_Err_Invalid_Argument; - FT_Glyph glyph = NULL; - FT_Library library = stroker->library; - FT_UNUSED(library); + FT_Error error = FT_Err_Invalid_Argument; + FT_Glyph glyph = NULL; + FT_Library library = stroker->library; + + FT_UNUSED( library ); + if ( pglyph == NULL ) goto Exit; @@ -1980,7 +2357,7 @@ } { - FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph; + FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; FT_StrokerBorder border; FT_Outline* outline = &oglyph->outline; FT_UInt num_points, num_contours; diff --git a/freetype/src/base/ftsystem.c b/freetype/src/base/ftsystem.c index 66c5d76a9..7e203bef8 100644 --- a/freetype/src/base/ftsystem.c +++ b/freetype/src/base/ftsystem.c @@ -4,7 +4,7 @@ /* */ /* ANSI-specific FreeType low-level system interface (body). */ /* */ -/* Copyright 1996-2001, 2002, 2006, 2008, 2009, 2010 by */ +/* Copyright 1996-2002, 2006, 2008-2011 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -137,6 +137,7 @@ /* */ /*************************************************************************/ +#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT /*************************************************************************/ /* */ @@ -267,6 +268,7 @@ return FT_Err_Ok; } +#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ #ifdef FT_DEBUG_MEMORY diff --git a/freetype/src/bdf/bdflib.c b/freetype/src/bdf/bdflib.c index 21b8d9d40..61bae36b3 100644 --- a/freetype/src/bdf/bdflib.c +++ b/freetype/src/bdf/bdflib.c @@ -1,6 +1,6 @@ /* * Copyright 2000 Computing Research Labs, New Mexico State University - * Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 + * Copyright 2001-2011 * Francesco Zappa Nardelli * * Permission is hereby granted, free of charge, to any person obtaining a @@ -983,7 +983,7 @@ FT_Error error = BDF_Err_Ok; - /* First check to see if the property has */ + /* First check whether the property has */ /* already been added or not. If it has, then */ /* simply ignore it. */ if ( hash_lookup( name, &(font->proptbl) ) ) @@ -1276,7 +1276,7 @@ FT_Error error = BDF_Err_Ok; - /* First, check to see if the property already exists in the font. */ + /* First, check whether the property already exists in the font. */ if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 ) { /* The property already exists in the font, so simply replace */ @@ -1530,8 +1530,8 @@ goto Exit; } - /* Check to see whether a glyph is being scanned but should be */ - /* ignored because it is an unencoded glyph. */ + /* Check whether a glyph is being scanned but should be */ + /* ignored because it is an unencoded glyph. */ if ( ( p->flags & _BDF_GLYPH ) && p->glyph_enc == -1 && p->opts->keep_unencoded == 0 ) @@ -1585,17 +1585,18 @@ p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 ); - /* Check that the encoding is in the range [0,65536] because */ - /* otherwise p->have (a bitmap with static size) overflows. */ - if ( (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 ) + /* Check that the encoding is in the range [0,65536] because */ + /* otherwise p->have (a bitmap with static size) overflows. */ + if ( p->glyph_enc > 0 && + (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 ) { error = BDF_Err_Invalid_File_Format; goto Exit; } - /* Check to see whether this encoding has already been encountered. */ - /* If it has then change it to unencoded so it gets added if */ - /* indicated. */ + /* Check whether this encoding has already been encountered. */ + /* If it has then change it to unencoded so it gets added if */ + /* indicated. */ if ( p->glyph_enc >= 0 ) { if ( _bdf_glyph_modified( p->have, p->glyph_enc ) ) @@ -1634,8 +1635,8 @@ } else { - /* Unencoded glyph. Check to see whether it should */ - /* be added or not. */ + /* Unencoded glyph. Check whether it should */ + /* be added or not. */ if ( p->opts->keep_unencoded != 0 ) { /* Allocate the next unencoded glyph. */ @@ -1676,7 +1677,7 @@ else glyph = font->glyphs + ( font->glyphs_used - 1 ); - /* Check to see whether a bitmap is being constructed. */ + /* Check whether a bitmap is being constructed. */ if ( p->flags & _BDF_BITMAP ) { /* If there are more rows than are specified in the glyph metrics, */ diff --git a/freetype/src/cff/cffparse.c b/freetype/src/cff/cffparse.c index 0d11a7278..4f71e858a 100644 --- a/freetype/src/cff/cffparse.c +++ b/freetype/src/cff/cffparse.c @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (body) */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 by */ +/* Copyright 1996-2004, 2007-2011 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -35,8 +35,6 @@ #define FT_COMPONENT trace_cffparse - - FT_LOCAL_DEF( void ) cff_parser_init( CFF_Parser parser, FT_UInt code, @@ -475,6 +473,12 @@ if ( scaling < 0 || scaling > 9 ) { /* Return default matrix in case of unlikely values. */ + + FT_TRACE1(( "cff_parse_font_matrix:" + " strange scaling value for xx element (%d),\n" + " " + " using default matrix\n", scaling )); + matrix->xx = 0x10000L; matrix->yx = 0; matrix->yx = 0; @@ -493,6 +497,12 @@ offset->y = cff_parse_fixed_scaled( data, scaling ); *upm = power_tens[scaling]; + + FT_TRACE4(( " font matrix: [%f %f %f %f]\n", + (double)matrix->xx / *upm / 65536, + (double)matrix->xy / *upm / 65536, + (double)matrix->yx / *upm / 65536, + (double)matrix->yy / *upm / 65536 )); } Exit: @@ -518,6 +528,12 @@ bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) ); bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) ); error = CFF_Err_Ok; + + FT_TRACE4(( " bbox: [%d %d %d %d]\n", + bbox->xMin / 65536, + bbox->yMin / 65536, + bbox->xMax / 65536, + bbox->yMax / 65536 )); } return error; @@ -557,8 +573,8 @@ if ( parser->top >= parser->stack + 3 ) { - dict->cid_registry = (FT_UInt)cff_parse_num ( data++ ); - dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ ); + dict->cid_registry = (FT_UInt)cff_parse_num( data++ ); + dict->cid_ordering = (FT_UInt)cff_parse_num( data++ ); if ( **data == 30 ) FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" )); dict->cid_supplement = cff_parse_num( data ); @@ -566,6 +582,11 @@ FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n", dict->cid_supplement )); error = CFF_Err_Ok; + + FT_TRACE4(( " ROS: registry sid %d, ordering sid %d, supplement %d\n", + dict->cid_registry, + dict->cid_ordering, + dict->cid_supplement )); } return error; diff --git a/freetype/src/psaux/t1decode.c b/freetype/src/psaux/t1decode.c index ea31c51b1..90874f022 100644 --- a/freetype/src/psaux/t1decode.c +++ b/freetype/src/psaux/t1decode.c @@ -4,8 +4,7 @@ /* */ /* PostScript Type 1 decoding routines (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */ -/* 2010 by */ +/* Copyright 2000-2011 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -28,6 +27,8 @@ #include "psauxerr.h" +/* ensure proper sign extension */ +#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) /*************************************************************************/ /* */ @@ -396,7 +397,7 @@ FT_ASSERT( ( decoder->len_buildchar == 0 ) == ( decoder->buildchar == NULL ) ); - if ( decoder->len_buildchar > 0 ) + if ( decoder->buildchar && decoder->len_buildchar > 0 ) ft_memset( &decoder->buildchar[0], 0, sizeof( decoder->buildchar[0] ) * decoder->len_buildchar ); @@ -662,7 +663,7 @@ if ( large_int ) FT_TRACE4(( " %ld", value )); else - FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) )); + FT_TRACE4(( " %ld", Fix2Int( value ) )); #endif *top++ = value; @@ -684,8 +685,8 @@ top -= 2; - subr_no = (FT_Int)( top[1] >> 16 ); - arg_cnt = (FT_Int)( top[0] >> 16 ); + subr_no = Fix2Int( top[1] ); + arg_cnt = Fix2Int( top[0] ); /***********************************************************/ /* */ @@ -724,6 +725,24 @@ switch ( subr_no ) { + case 0: /* end flex feature */ + if ( arg_cnt != 3 ) + goto Unexpected_OtherSubr; + + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected flex end\n" )); + goto Syntax_Error; + } + + /* the two `results' are popped by the following setcurrentpoint */ + top[0] = x; + top[1] = y; + known_othersubr_result_cnt = 2; + break; + case 1: /* start flex feature */ if ( arg_cnt != 0 ) goto Unexpected_OtherSubr; @@ -757,24 +776,6 @@ } break; - case 0: /* end flex feature */ - if ( arg_cnt != 3 ) - goto Unexpected_OtherSubr; - - if ( decoder->flex_state == 0 || - decoder->num_flex_vectors != 7 ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected flex end\n" )); - goto Syntax_Error; - } - - /* the two `results' are popped by the following setcurrentpoint */ - top[0] = x; - top[1] = y; - known_othersubr_result_cnt = 2; - break; - case 3: /* change hints */ if ( arg_cnt != 1 ) goto Unexpected_OtherSubr; @@ -818,17 +819,18 @@ goto Syntax_Error; } - /* we want to compute: */ + /* We want to compute */ /* */ - /* a0*w0 + a1*w1 + ... + ak*wk */ + /* a0*w0 + a1*w1 + ... + ak*wk */ /* */ - /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */ - /* however, given that w0 + w1 + ... + wk == 1, we can */ - /* rewrite it easily as: */ + /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ /* */ - /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */ + /* However, given that w0 + w1 + ... + wk == 1, we can */ + /* rewrite it easily as */ /* */ - /* where k == num_designs-1 */ + /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ + /* */ + /* where k == num_designs-1. */ /* */ /* I guess that's why it's written in this `compact' */ /* form. */ @@ -862,7 +864,7 @@ if ( arg_cnt != 1 || blend == NULL ) goto Unexpected_OtherSubr; - idx = (FT_Int)( top[0] >> 16 ); + idx = Fix2Int( top[0] ); if ( idx < 0 || idx + blend->num_designs > decoder->len_buildchar ) @@ -930,7 +932,7 @@ if ( arg_cnt != 2 || blend == NULL ) goto Unexpected_OtherSubr; - idx = (FT_Int)( top[1] >> 16 ); + idx = Fix2Int( top[1] ); if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; @@ -951,7 +953,7 @@ if ( arg_cnt != 1 || blend == NULL ) goto Unexpected_OtherSubr; - idx = (FT_Int)( top[0] >> 16 ); + idx = Fix2Int( top[0] ); if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; @@ -1009,11 +1011,15 @@ break; default: - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unknown othersubr [%d %d], wish me luck\n", - arg_cnt, subr_no )); - unknown_othersubr_result_cnt = arg_cnt; - break; + if ( arg_cnt >= 0 && subr_no >= 0 ) + { + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unknown othersubr [%d %d], wish me luck\n", + arg_cnt, subr_no )); + unknown_othersubr_result_cnt = arg_cnt; + break; + } + /* fall through */ Unexpected_OtherSubr: FT_ERROR(( "t1_decoder_parse_charstrings:" @@ -1139,8 +1145,8 @@ top[0], top[1], top[2], - (FT_Int)( top[3] >> 16 ), - (FT_Int)( top[4] >> 16 ) ); + Fix2Int( top[3] ), + Fix2Int( top[4] ) ); case op_sbw: FT_TRACE4(( " sbw" )); @@ -1324,7 +1330,7 @@ FT_TRACE4(( " callsubr" )); - idx = (FT_Int)( top[0] >> 16 ); + idx = Fix2Int( top[0] ); if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) { FT_ERROR(( "t1_decoder_parse_charstrings:" diff --git a/freetype/src/sfnt/sfobjs.c b/freetype/src/sfnt/sfobjs.c index e581af9b9..44471f6b6 100644 --- a/freetype/src/sfnt/sfobjs.c +++ b/freetype/src/sfnt/sfobjs.c @@ -582,12 +582,12 @@ /* do we have outlines in there? */ #ifdef FT_CONFIG_OPTION_INCREMENTAL - has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || - tt_face_lookup_table( face, TTAG_glyf ) != 0 || - tt_face_lookup_table( face, TTAG_CFF ) != 0 ); + has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || + tt_face_lookup_table( face, TTAG_glyf ) != 0 || + tt_face_lookup_table( face, TTAG_CFF ) != 0 ); #else - has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || - tt_face_lookup_table( face, TTAG_CFF ) != 0 ); + has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || + tt_face_lookup_table( face, TTAG_CFF ) != 0 ); #endif is_apple_sbit = 0; @@ -662,8 +662,9 @@ if ( face->format_tag == TTAG_true ) { FT_TRACE2(( "This is an SFNT Mac font.\n" )); + has_outline = 0; - error = SFNT_Err_Ok; + error = SFNT_Err_Ok; } else { @@ -998,40 +999,36 @@ /* table cannot be used to compute the text height reliably! */ /* */ - /* The ascender/descender/height are computed from the OS/2 table */ - /* when found. Otherwise, they're taken from the horizontal */ - /* header. */ - /* */ + /* The ascender and descender are taken from the `hhea' table. */ + /* If zero, they are taken from the `OS/2' table. */ root->ascender = face->horizontal.Ascender; root->descender = face->horizontal.Descender; - root->height = (FT_Short)( root->ascender - root->descender + - face->horizontal.Line_Gap ); + root->height = (FT_Short)( root->ascender - root->descender + + face->horizontal.Line_Gap ); -#if 0 - /* if the line_gap is 0, we add an extra 15% to the text height -- */ - /* this computation is based on various versions of Times New Roman */ - if ( face->horizontal.Line_Gap == 0 ) - root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 ); -#endif /* 0 */ - -#if 0 - /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */ - /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */ - if ( face->os2.version != 0xFFFFU && root->ascender ) + if ( !( root->ascender || root->descender ) ) { - FT_Int height; - + if ( face->os2.version != 0xFFFFU ) + { + if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = face->os2.sTypoDescender; - root->ascender = face->os2.sTypoAscender; - root->descender = -face->os2.sTypoDescender; + root->height = (FT_Short)( root->ascender - root->descender + + face->os2.sTypoLineGap ); + } + else + { + root->ascender = (FT_Short)face->os2.usWinAscent; + root->descender = -(FT_Short)face->os2.usWinDescent; - height = root->ascender + root->descender + face->os2.sTypoLineGap; - if ( height > root->height ) - root->height = height; + root->height = (FT_UShort)( root->ascender - root->descender ); + } + } } -#endif /* 0 */ root->max_advance_width = face->horizontal.advance_Width_Max; root->max_advance_height = (FT_Short)( face->vertical_info diff --git a/freetype/src/truetype/ttdriver.c b/freetype/src/truetype/ttdriver.c index 66061fd3a..e70a61123 100644 --- a/freetype/src/truetype/ttdriver.c +++ b/freetype/src/truetype/ttdriver.c @@ -246,7 +246,10 @@ FT_Request_Metrics( size->face, req ); if ( FT_IS_SCALABLE( size->face ) ) + { error = tt_size_reset( ttsize ); + ttsize->root.metrics = ttsize->metrics; + } return error; } diff --git a/freetype/src/truetype/ttobjs.c b/freetype/src/truetype/ttobjs.c index bcbd3b56c..d77c3c421 100644 --- a/freetype/src/truetype/ttobjs.c +++ b/freetype/src/truetype/ttobjs.c @@ -409,6 +409,54 @@ } + /* Check whether `.notdef' is the only glyph in the `loca' table. */ + static FT_Bool + tt_check_single_notdef( FT_Face ttface ) + { + FT_Bool result = FALSE; + + TT_Face face = (TT_Face)ttface; + FT_UInt asize; + FT_ULong i; + FT_ULong glyph_index = 0; + FT_UInt count = 0; + + + for( i = 0; i < face->num_locations; i++ ) + { + tt_face_get_location( face, i, &asize ); + if ( asize > 0 ) + { + count += 1; + if ( count > 1 ) + break; + glyph_index = i; + } + } + + /* Only have a single outline. */ + if ( count == 1 ) + { + if ( glyph_index == 0 ) + result = TRUE; + else + { + /* FIXME: Need to test glyphname == .notdef ? */ + FT_Error error; + char buf[8]; + + + error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 ); + if ( !error && + buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) ) + result = TRUE; + } + } + + return result; + } + + /*************************************************************************/ /* */ /* */ @@ -504,6 +552,20 @@ if ( !error ) error = tt_face_load_prep( face, stream ); + /* Check the scalable flag based on `loca'. */ + if ( !ttface->internal->incremental_interface && + ttface->num_fixed_sizes && + face->glyph_locations && + tt_check_single_notdef( ttface ) ) + { + FT_TRACE5(( "tt_face_init:" + " Only the `.notdef' glyph has an outline.\n" + " " + " Resetting scalable flag to FALSE.\n" )); + + ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; + } + #else if ( !error ) @@ -515,6 +577,19 @@ if ( !error ) error = tt_face_load_prep( face, stream ); + /* Check the scalable flag based on `loca'. */ + if ( ttface->num_fixed_sizes && + face->glyph_locations && + tt_check_single_notdef( ttface ) ) + { + FT_TRACE5(( "tt_face_init:" + " Only the `.notdef' glyph has an outline.\n" + " " + " Resetting scalable flag to FALSE.\n" )); + + ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; + } + #endif } diff --git a/freetype/src/type1/t1load.c b/freetype/src/type1/t1load.c index 09fe6adf5..38c74b277 100644 --- a/freetype/src/type1/t1load.c +++ b/freetype/src/type1/t1load.c @@ -4,8 +4,7 @@ /* */ /* Type 1 font loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ -/* 2010 by */ +/* Copyright 1996-2011 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -922,6 +921,9 @@ PS_Blend blend = face->blend; + if ( blend && blend->num_designs == 0 ) + blend = NULL; + /* if the keyword has a dedicated callback, call it */ if ( field->type == T1_FIELD_TYPE_CALLBACK ) { -- cgit v1.2.3