| Index: src/base/ftoutln.c
|
| diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
|
| index 9ae276d082a4fc6e4cfebe744ef84ac402690818..54ca5cdcf6ed206ae58024d3633159602330ce6d 100644
|
| --- a/src/base/ftoutln.c
|
| +++ b/src/base/ftoutln.c
|
| @@ -4,7 +4,7 @@
|
| /* */
|
| /* FreeType outline management (body). */
|
| /* */
|
| -/* Copyright 1996-2008, 2010, 2012 by */
|
| +/* Copyright 1996-2008, 2010, 2012-2013 by */
|
| /* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
| /* */
|
| /* This file is part of the FreeType project, and may only be used, */
|
| @@ -26,6 +26,7 @@
|
| #include <ft2build.h>
|
| #include FT_OUTLINE_H
|
| #include FT_INTERNAL_OBJECTS_H
|
| +#include FT_INTERNAL_CALC_H
|
| #include FT_INTERNAL_DEBUG_H
|
| #include FT_TRIGONOMETRY_H
|
|
|
| @@ -73,7 +74,7 @@
|
|
|
|
|
| if ( !outline || !func_interface )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
|
|
| shift = func_interface->shift;
|
| delta = func_interface->delta;
|
| @@ -286,7 +287,7 @@
|
| return error;
|
|
|
| Invalid_Outline:
|
| - return FT_Err_Invalid_Outline;
|
| + return FT_THROW( Invalid_Outline );
|
| }
|
|
|
|
|
| @@ -300,10 +301,17 @@
|
|
|
|
|
| if ( !anoutline || !memory )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
|
|
| *anoutline = null_outline;
|
|
|
| + if ( numContours < 0 ||
|
| + (FT_UInt)numContours > numPoints )
|
| + return FT_THROW( Invalid_Argument );
|
| +
|
| + if ( numPoints > FT_OUTLINE_POINTS_MAX )
|
| + return FT_THROW( Array_Too_Large );
|
| +
|
| if ( FT_NEW_ARRAY( anoutline->points, numPoints ) ||
|
| FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
|
| FT_NEW_ARRAY( anoutline->contours, numContours ) )
|
| @@ -332,7 +340,7 @@
|
| FT_Outline *anoutline )
|
| {
|
| if ( !library )
|
| - return FT_Err_Invalid_Library_Handle;
|
| + return FT_THROW( Invalid_Library_Handle );
|
|
|
| return FT_Outline_New_Internal( library->memory, numPoints,
|
| numContours, anoutline );
|
| @@ -380,7 +388,7 @@
|
| }
|
|
|
| Bad:
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
| }
|
|
|
|
|
| @@ -396,7 +404,7 @@
|
| if ( !source || !target ||
|
| source->n_points != target->n_points ||
|
| source->n_contours != target->n_contours )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
|
|
| if ( source == target )
|
| return FT_Err_Ok;
|
| @@ -435,7 +443,7 @@
|
| return FT_Err_Ok;
|
| }
|
| else
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
| }
|
|
|
|
|
| @@ -448,7 +456,7 @@
|
| /* check for valid `outline' in FT_Outline_Done_Internal() */
|
|
|
| if ( !library )
|
| - return FT_Err_Invalid_Library_Handle;
|
| + return FT_THROW( Invalid_Library_Handle );
|
|
|
| return FT_Outline_Done_Internal( library->memory, outline );
|
| }
|
| @@ -602,21 +610,21 @@
|
|
|
|
|
| if ( !library )
|
| - return FT_Err_Invalid_Library_Handle;
|
| + return FT_THROW( Invalid_Library_Handle );
|
|
|
| if ( !outline || !params )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
|
|
| renderer = library->cur_renderer;
|
| node = library->renderers.head;
|
|
|
| params->source = (void*)outline;
|
|
|
| - error = FT_Err_Cannot_Render_Glyph;
|
| + error = FT_ERR( Cannot_Render_Glyph );
|
| while ( renderer )
|
| {
|
| error = renderer->raster_render( renderer->raster, params );
|
| - if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
|
| + if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
|
| break;
|
|
|
| /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
|
| @@ -650,7 +658,7 @@
|
|
|
|
|
| if ( !abitmap )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
|
|
| /* other checks are delayed to FT_Outline_Render() */
|
|
|
| @@ -882,85 +890,126 @@
|
| FT_Outline_Embolden( FT_Outline* outline,
|
| FT_Pos strength )
|
| {
|
| + return FT_Outline_EmboldenXY( outline, strength, strength );
|
| + }
|
| +
|
| +
|
| + /* documentation is in ftoutln.h */
|
| +
|
| + FT_EXPORT_DEF( FT_Error )
|
| + FT_Outline_EmboldenXY( FT_Outline* outline,
|
| + FT_Pos xstrength,
|
| + FT_Pos ystrength )
|
| + {
|
| FT_Vector* points;
|
| FT_Vector v_prev, v_first, v_next, v_cur;
|
| - FT_Angle rotate, angle_in, angle_out;
|
| FT_Int c, n, first;
|
| FT_Int orientation;
|
|
|
|
|
| if ( !outline )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
|
|
| - strength /= 2;
|
| - if ( strength == 0 )
|
| + xstrength /= 2;
|
| + ystrength /= 2;
|
| + if ( xstrength == 0 && ystrength == 0 )
|
| return FT_Err_Ok;
|
|
|
| orientation = FT_Outline_Get_Orientation( outline );
|
| if ( orientation == FT_ORIENTATION_NONE )
|
| {
|
| if ( outline->n_contours )
|
| - return FT_Err_Invalid_Argument;
|
| + return FT_THROW( Invalid_Argument );
|
| else
|
| return FT_Err_Ok;
|
| }
|
|
|
| - if ( orientation == FT_ORIENTATION_TRUETYPE )
|
| - rotate = -FT_ANGLE_PI2;
|
| - else
|
| - rotate = FT_ANGLE_PI2;
|
| -
|
| points = outline->points;
|
|
|
| first = 0;
|
| for ( c = 0; c < outline->n_contours; c++ )
|
| {
|
| - int last = outline->contours[c];
|
| + FT_Vector in, out, shift;
|
| + FT_Fixed l_in, l_out, l, q, d;
|
| + int last = outline->contours[c];
|
|
|
|
|
| v_first = points[first];
|
| v_prev = points[last];
|
| v_cur = v_first;
|
|
|
| - for ( n = first; n <= last; n++ )
|
| + /* compute incoming normalized vector */
|
| + in.x = v_cur.x - v_prev.x;
|
| + in.y = v_cur.y - v_prev.y;
|
| + l_in = FT_Vector_Length( &in );
|
| + if ( l_in )
|
| {
|
| - FT_Vector in, out;
|
| - FT_Angle angle_diff;
|
| - FT_Pos d;
|
| - FT_Fixed scale;
|
| -
|
| + in.x = FT_DivFix( in.x, l_in );
|
| + in.y = FT_DivFix( in.y, l_in );
|
| + }
|
|
|
| + for ( n = first; n <= last; n++ )
|
| + {
|
| if ( n < last )
|
| v_next = points[n + 1];
|
| else
|
| v_next = v_first;
|
|
|
| - /* compute the in and out vectors */
|
| - in.x = v_cur.x - v_prev.x;
|
| - in.y = v_cur.y - v_prev.y;
|
| -
|
| + /* compute outgoing normalized vector */
|
| out.x = v_next.x - v_cur.x;
|
| out.y = v_next.y - v_cur.y;
|
| + l_out = FT_Vector_Length( &out );
|
| + if ( l_out )
|
| + {
|
| + out.x = FT_DivFix( out.x, l_out );
|
| + out.y = FT_DivFix( out.y, l_out );
|
| + }
|
|
|
| - angle_in = FT_Atan2( in.x, in.y );
|
| - angle_out = FT_Atan2( out.x, out.y );
|
| - angle_diff = FT_Angle_Diff( angle_in, angle_out );
|
| - scale = FT_Cos( angle_diff / 2 );
|
| + d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
|
|
|
| - if ( scale < 0x4000L && scale > -0x4000L )
|
| - in.x = in.y = 0;
|
| - else
|
| + /* shift only if turn is less than ~160 degrees */
|
| + if ( d > -0xF000L )
|
| {
|
| - d = FT_DivFix( strength, scale );
|
| + d = d + 0x10000L;
|
|
|
| - FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
|
| + /* shift components are aligned along lateral bisector */
|
| + /* and directed according to the outline orientation. */
|
| + shift.x = in.y + out.y;
|
| + shift.y = in.x + out.x;
|
| +
|
| + if ( orientation == FT_ORIENTATION_TRUETYPE )
|
| + shift.x = -shift.x;
|
| + else
|
| + shift.y = -shift.y;
|
| +
|
| + /* restrict shift magnitude to better handle collapsing segments */
|
| + q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
|
| + if ( orientation == FT_ORIENTATION_TRUETYPE )
|
| + q = -q;
|
| +
|
| + l = FT_MIN( l_in, l_out );
|
| +
|
| + /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
|
| + if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) )
|
| + shift.x = FT_MulDiv( shift.x, xstrength, d );
|
| + else
|
| + shift.x = FT_MulDiv( shift.x, l, q );
|
| +
|
| +
|
| + if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) )
|
| + shift.y = FT_MulDiv( shift.y, ystrength, d );
|
| + else
|
| + shift.y = FT_MulDiv( shift.y, l, q );
|
| }
|
| + else
|
| + shift.x = shift.y = 0;
|
|
|
| - outline->points[n].x = v_cur.x + strength + in.x;
|
| - outline->points[n].y = v_cur.y + strength + in.y;
|
| + outline->points[n].x = v_cur.x + xstrength + shift.x;
|
| + outline->points[n].y = v_cur.y + ystrength + shift.y;
|
|
|
| - v_prev = v_cur;
|
| - v_cur = v_next;
|
| + in = out;
|
| + l_in = l_out;
|
| + v_cur = v_next;
|
| }
|
|
|
| first = last + 1;
|
| @@ -975,23 +1024,12 @@
|
| FT_EXPORT_DEF( FT_Orientation )
|
| FT_Outline_Get_Orientation( FT_Outline* outline )
|
| {
|
| - FT_Pos xmin = 32768L;
|
| - FT_Pos xmin_ymin = 32768L;
|
| - FT_Pos xmin_ymax = -32768L;
|
| - FT_Vector* xmin_first = NULL;
|
| - FT_Vector* xmin_last = NULL;
|
| -
|
| - short* contour;
|
| -
|
| - FT_Vector* first;
|
| - FT_Vector* last;
|
| - FT_Vector* prev;
|
| - FT_Vector* point;
|
| -
|
| - int i;
|
| - FT_Pos ray_y[3];
|
| - FT_Orientation result[3] =
|
| - { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE };
|
| + FT_BBox cbox;
|
| + FT_Int xshift, yshift;
|
| + FT_Vector* points;
|
| + FT_Vector v_prev, v_cur;
|
| + FT_Int c, n, first;
|
| + FT_Pos area = 0;
|
|
|
|
|
| if ( !outline || outline->n_points <= 0 )
|
| @@ -1002,127 +1040,41 @@
|
| /* cubic or quadratic curves, this test deals with the polygon */
|
| /* only which is spanned up by the control points. */
|
|
|
| - first = outline->points;
|
| - for ( contour = outline->contours;
|
| - contour < outline->contours + outline->n_contours;
|
| - contour++, first = last + 1 )
|
| - {
|
| - FT_Pos contour_xmin = 32768L;
|
| - FT_Pos contour_xmax = -32768L;
|
| - FT_Pos contour_ymin = 32768L;
|
| - FT_Pos contour_ymax = -32768L;
|
| -
|
| -
|
| - last = outline->points + *contour;
|
| + FT_Outline_Get_CBox( outline, &cbox );
|
|
|
| - /* skip degenerate contours */
|
| - if ( last < first + 2 )
|
| - continue;
|
| -
|
| - for ( point = first; point <= last; ++point )
|
| - {
|
| - if ( point->x < contour_xmin )
|
| - contour_xmin = point->x;
|
| -
|
| - if ( point->x > contour_xmax )
|
| - contour_xmax = point->x;
|
| -
|
| - if ( point->y < contour_ymin )
|
| - contour_ymin = point->y;
|
| -
|
| - if ( point->y > contour_ymax )
|
| - contour_ymax = point->y;
|
| - }
|
| -
|
| - if ( contour_xmin < xmin &&
|
| - contour_xmin != contour_xmax &&
|
| - contour_ymin != contour_ymax )
|
| - {
|
| - xmin = contour_xmin;
|
| - xmin_ymin = contour_ymin;
|
| - xmin_ymax = contour_ymax;
|
| - xmin_first = first;
|
| - xmin_last = last;
|
| - }
|
| - }
|
| + xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
|
| + xshift = FT_MAX( xshift, 0 );
|
|
|
| - if ( xmin == 32768L )
|
| - return FT_ORIENTATION_TRUETYPE;
|
| + yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14;
|
| + yshift = FT_MAX( yshift, 0 );
|
|
|
| - ray_y[0] = ( xmin_ymin * 3 + xmin_ymax ) >> 2;
|
| - ray_y[1] = ( xmin_ymin + xmin_ymax ) >> 1;
|
| - ray_y[2] = ( xmin_ymin + xmin_ymax * 3 ) >> 2;
|
| + points = outline->points;
|
|
|
| - for ( i = 0; i < 3; i++ )
|
| + first = 0;
|
| + for ( c = 0; c < outline->n_contours; c++ )
|
| {
|
| - FT_Pos left_x;
|
| - FT_Pos right_x;
|
| - FT_Vector* left1;
|
| - FT_Vector* left2;
|
| - FT_Vector* right1;
|
| - FT_Vector* right2;
|
| -
|
| + FT_Int last = outline->contours[c];
|
|
|
| - RedoRay:
|
| - left_x = 32768L;
|
| - right_x = -32768L;
|
|
|
| - left1 = left2 = right1 = right2 = NULL;
|
| + v_prev = points[last];
|
|
|
| - prev = xmin_last;
|
| - for ( point = xmin_first; point <= xmin_last; prev = point, ++point )
|
| + for ( n = first; n <= last; n++ )
|
| {
|
| - FT_Pos tmp_x;
|
| -
|
| -
|
| - if ( point->y == ray_y[i] || prev->y == ray_y[i] )
|
| - {
|
| - ray_y[i]++;
|
| - goto RedoRay;
|
| - }
|
| -
|
| - if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) ||
|
| - ( point->y > ray_y[i] && prev->y > ray_y[i] ) )
|
| - continue;
|
| -
|
| - tmp_x = FT_MulDiv( point->x - prev->x,
|
| - ray_y[i] - prev->y,
|
| - point->y - prev->y ) + prev->x;
|
| -
|
| - if ( tmp_x < left_x )
|
| - {
|
| - left_x = tmp_x;
|
| - left1 = prev;
|
| - left2 = point;
|
| - }
|
| -
|
| - if ( tmp_x > right_x )
|
| - {
|
| - right_x = tmp_x;
|
| - right1 = prev;
|
| - right2 = point;
|
| - }
|
| + v_cur = points[n];
|
| + area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
|
| + ( ( v_cur.x + v_prev.x ) >> xshift );
|
| + v_prev = v_cur;
|
| }
|
|
|
| - if ( left1 && right1 )
|
| - {
|
| - if ( left1->y < left2->y && right1->y > right2->y )
|
| - result[i] = FT_ORIENTATION_TRUETYPE;
|
| - else if ( left1->y > left2->y && right1->y < right2->y )
|
| - result[i] = FT_ORIENTATION_POSTSCRIPT;
|
| - else
|
| - result[i] = FT_ORIENTATION_NONE;
|
| - }
|
| + first = last + 1;
|
| }
|
|
|
| - if ( result[0] != FT_ORIENTATION_NONE &&
|
| - ( result[0] == result[1] || result[0] == result[2] ) )
|
| - return result[0];
|
| -
|
| - if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] )
|
| - return result[1];
|
| -
|
| - return FT_ORIENTATION_TRUETYPE;
|
| + if ( area > 0 )
|
| + return FT_ORIENTATION_POSTSCRIPT;
|
| + else if ( area < 0 )
|
| + return FT_ORIENTATION_TRUETYPE;
|
| + else
|
| + return FT_ORIENTATION_NONE;
|
| }
|
|
|
|
|
|
|