summaryrefslogtreecommitdiffstats
path: root/src/base/ftoutln.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/ftoutln.c')
-rw-r--r--src/base/ftoutln.c224
1 files changed, 160 insertions, 64 deletions
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 76e2b04..9ae276d 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -882,19 +882,9 @@
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;
@@ -902,9 +892,8 @@
if ( !outline )
return FT_Err_Invalid_Argument;
- xstrength /= 2;
- ystrength /= 2;
- if ( xstrength == 0 && ystrength == 0 )
+ strength /= 2;
+ if ( strength == 0 )
return FT_Err_Ok;
orientation = FT_Outline_Get_Orientation( outline );
@@ -916,63 +905,62 @@
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++ )
{
- FT_Vector in, out, shift;
- FT_Fixed l_in, l_out, d;
- int last = outline->contours[c];
+ int last = outline->contours[c];
v_first = points[first];
v_prev = points[last];
v_cur = v_first;
- /* compute the incoming vector and its length */
- in.x = v_cur.x - v_prev.x;
- in.y = v_cur.y - v_prev.y;
- l_in = FT_Vector_Length( &in );
-
for ( n = first; n <= last; n++ )
{
+ FT_Vector in, out;
+ FT_Angle angle_diff;
+ FT_Pos d;
+ FT_Fixed scale;
+
+
if ( n < last )
v_next = points[n + 1];
else
v_next = v_first;
- /* compute the outgoing vector and its length */
+ /* compute the in and out vectors */
+ in.x = v_cur.x - v_prev.x;
+ in.y = v_cur.y - v_prev.y;
+
out.x = v_next.x - v_cur.x;
out.y = v_next.y - v_cur.y;
- l_out = FT_Vector_Length( &out );
- d = l_in * l_out + in.x * out.x + in.y * out.y;
+ 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 );
- /* shift only if turn is less then ~160 degrees */
- if ( 16 * d > l_in * l_out )
+ if ( scale < 0x4000L && scale > -0x4000L )
+ in.x = in.y = 0;
+ else
{
- /* shift components are rotated */
- shift.x = FT_DivFix( l_out * in.y + l_in * out.y, d );
- shift.y = FT_DivFix( l_out * in.x + l_in * out.x, d );
+ d = FT_DivFix( strength, scale );
- if ( orientation == FT_ORIENTATION_TRUETYPE )
- shift.x = -shift.x;
- else
- shift.y = -shift.y;
-
- shift.x = FT_MulFix( xstrength, shift.x );
- shift.y = FT_MulFix( ystrength, shift.y );
+ FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
}
- else
- shift.x = shift.y = 0;
- outline->points[n].x = v_cur.x + xstrength + shift.x;
- outline->points[n].y = v_cur.y + ystrength + shift.y;
+ outline->points[n].x = v_cur.x + strength + in.x;
+ outline->points[n].y = v_cur.y + strength + in.y;
- in = out;
- l_in = l_out;
- v_cur = v_next;
+ v_prev = v_cur;
+ v_cur = v_next;
}
first = last + 1;
@@ -987,10 +975,23 @@
FT_EXPORT_DEF( FT_Orientation )
FT_Outline_Get_Orientation( FT_Outline* outline )
{
- FT_Vector* points;
- FT_Vector v_prev, v_cur;
- FT_Int c, n, first;
- FT_Pos area = 0;
+ 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 };
if ( !outline || outline->n_points <= 0 )
@@ -1001,32 +1002,127 @@
/* cubic or quadratic curves, this test deals with the polygon */
/* only which is spanned up by the control points. */
- points = outline->points;
-
- first = 0;
- for ( c = 0; c < outline->n_contours; c++ )
+ first = outline->points;
+ for ( contour = outline->contours;
+ contour < outline->contours + outline->n_contours;
+ contour++, first = last + 1 )
{
- FT_Int last = outline->contours[c];
+ FT_Pos contour_xmin = 32768L;
+ FT_Pos contour_xmax = -32768L;
+ FT_Pos contour_ymin = 32768L;
+ FT_Pos contour_ymax = -32768L;
- v_prev = points[last];
+ last = outline->points + *contour;
- for ( n = first; n <= last; n++ )
+ /* skip degenerate contours */
+ if ( last < first + 2 )
+ continue;
+
+ for ( point = first; point <= last; ++point )
{
- v_cur = points[n];
- area += ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x );
- v_prev = v_cur;
+ 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;
}
- first = last + 1;
+ 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;
+ }
}
- if ( area > 0 )
- return FT_ORIENTATION_POSTSCRIPT;
- else if ( area < 0 )
+ if ( xmin == 32768L )
return FT_ORIENTATION_TRUETYPE;
- else
- return FT_ORIENTATION_NONE;
+
+ 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;
+
+ for ( i = 0; i < 3; i++ )
+ {
+ FT_Pos left_x;
+ FT_Pos right_x;
+ FT_Vector* left1;
+ FT_Vector* left2;
+ FT_Vector* right1;
+ FT_Vector* right2;
+
+
+ RedoRay:
+ left_x = 32768L;
+ right_x = -32768L;
+
+ left1 = left2 = right1 = right2 = NULL;
+
+ prev = xmin_last;
+ for ( point = xmin_first; point <= xmin_last; prev = point, ++point )
+ {
+ 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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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;
}