aboutsummaryrefslogtreecommitdiff
path: root/freetype/src
diff options
context:
space:
mode:
Diffstat (limited to 'freetype/src')
-rw-r--r--freetype/src/base/ftobjs.c6
-rw-r--r--freetype/src/base/ftpatent.c2
-rw-r--r--freetype/src/base/ftstroke.c809
-rw-r--r--freetype/src/base/ftsystem.c4
-rw-r--r--freetype/src/bdf/bdflib.c29
-rw-r--r--freetype/src/cff/cffparse.c31
-rw-r--r--freetype/src/psaux/t1decode.c90
-rw-r--r--freetype/src/sfnt/sfobjs.c59
-rw-r--r--freetype/src/truetype/ttdriver.c3
-rw-r--r--freetype/src/truetype/ttobjs.c75
-rw-r--r--freetype/src/type1/t1load.c6
11 files changed, 802 insertions, 312 deletions
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;
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -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 )
{