Sync with trunk r47367
[reactos.git] / lib / 3rdparty / freetype / src / base / ftstroke.c
index 8f7e045..75bcbde 100644 (file)
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (body).                                        */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006 by                              */
+/*  Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 by            */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
  /***************************************************************************/
  /***************************************************************************/
 
-  typedef enum
+  typedef enum  FT_StrokeTags_
   {
     FT_STROKE_TAG_ON    = 1,   /* on-curve point  */
     FT_STROKE_TAG_CUBIC = 2,   /* cubic off-point */
   {
     FT_UInt   old_max = border->max_points;
     FT_UInt   new_max = border->num_points + new_points;
-    FT_Error  error   = 0;
+    FT_Error  error   = FT_Err_Ok;
 
 
     if ( new_max > old_max )
 
       border->max_points = cur_max;
     }
+
   Exit:
     return error;
   }
     }
 
     border->start   = -1;
-    border->movable = 0;
+    border->movable = FALSE;
   }
 
 
                            FT_Vector*       to,
                            FT_Bool          movable )
   {
-    FT_Error  error = 0;
+    FT_Error  error = FT_Err_Ok;
 
 
     FT_ASSERT( border->start >= 0 );
 
       border->num_points += 2;
     }
-    border->movable = 0;
+    border->movable = FALSE;
     return error;
   }
 
 
       border->num_points += 3;
     }
-    border->movable = 0;
+    border->movable = FALSE;
     return error;
   }
 
     FT_Angle   total, angle, step, rotate, next, theta;
     FT_Vector  a, b, a2, b2;
     FT_Fixed   length;
-    FT_Error   error = 0;
+    FT_Error   error = FT_Err_Ok;
 
 
     /* compute start point */
   {
     /* close current open path if any ? */
     if ( border->start >= 0 )
-      ft_stroke_border_close( border, 0 );
+      ft_stroke_border_close( border, FALSE );
 
     border->start   = border->num_points;
-    border->movable = 0;
+    border->movable = FALSE;
 
-    return ft_stroke_border_lineto( border, to, 0 );
+    return ft_stroke_border_lineto( border, to, FALSE );
   }
 
 
     border->num_points = 0;
     border->max_points = 0;
     border->start      = -1;
-    border->valid      = 0;
+    border->valid      = FALSE;
   }
 
 
   {
     border->num_points = 0;
     border->start      = -1;
-    border->valid      = 0;
+    border->valid      = FALSE;
   }
 
 
     border->num_points = 0;
     border->max_points = 0;
     border->start      = -1;
-    border->valid      = 0;
+    border->valid      = FALSE;
   }
 
 
                                FT_UInt         *anum_points,
                                FT_UInt         *anum_contours )
   {
-    FT_Error  error        = 0;
+    FT_Error  error        = FT_Err_Ok;
     FT_UInt   num_points   = 0;
     FT_UInt   num_contours = 0;
 
 
       if ( tags[0] & FT_STROKE_TAG_END )
       {
-        if ( in_contour == 0 )
-          goto Fail;
-
         in_contour = 0;
         num_contours++;
       }
     if ( in_contour != 0 )
       goto Fail;
 
-    border->valid = 1;
+    border->valid = TRUE;
 
   Exit:
     *anum_points   = num_points;
 
     FT_Bool              valid;
     FT_StrokeBorderRec   borders[2];
-    FT_Memory            memory;
+    FT_Library           library;
 
   } FT_StrokerRec;
 
 
     if ( !FT_NEW( stroker ) )
     {
-      stroker->memory = memory;
+      stroker->library = library;
 
       ft_stroke_border_init( &stroker->borders[0], memory );
       ft_stroke_border_init( &stroker->borders[1], memory );
   {
     if ( stroker )
     {
-      FT_Memory  memory = stroker->memory;
+      FT_Memory  memory = stroker->library->memory;
 
 
       ft_stroke_border_done( &stroker->borders[0] );
       ft_stroke_border_done( &stroker->borders[1] );
 
-      stroker->memory = NULL;
+      stroker->library = NULL;
       FT_FREE( stroker );
     }
   }
   {
     FT_Angle         total, rotate;
     FT_Fixed         radius = stroker->radius;
-    FT_Error         error  = 0;
+    FT_Error         error  = FT_Err_Ok;
     FT_StrokeBorder  border = stroker->borders + side;
 
 
                                     radius,
                                     stroker->angle_in + rotate,
                                     total );
-    border->movable = 0;
+    border->movable = FALSE;
     return error;
   }
 
                   FT_Angle    angle,
                   FT_Int      side )
   {
-    FT_Error  error  = 0;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
       delta.x += stroker->center.x + delta2.x;
       delta.y += stroker->center.y + delta2.y;
 
-      error = ft_stroke_border_lineto( border, &delta, 0 );
+      error = ft_stroke_border_lineto( border, &delta, FALSE );
       if ( error )
         goto Exit;
 
       delta.x += delta2.x + stroker->center.x;
       delta.y += delta2.y + stroker->center.y;
 
-      error = ft_stroke_border_lineto( border, &delta, 0 );
+      error = ft_stroke_border_lineto( border, &delta, FALSE );
+    }
+    else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT )
+    {
+      /* add a butt ending */
+      FT_Vector        delta;
+      FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
+      FT_Fixed         radius = stroker->radius;
+      FT_StrokeBorder  border = stroker->borders + side;
+
+
+      FT_Vector_From_Polar( &delta, radius, angle + rotate );
+
+      delta.x += stroker->center.x;
+      delta.y += stroker->center.y;
+
+      error = ft_stroke_border_lineto( border, &delta, FALSE );
+      if ( error )
+        goto Exit;
+
+      FT_Vector_From_Polar( &delta, radius, angle - rotate );
+
+      delta.x += stroker->center.x;
+      delta.y += stroker->center.y;
+
+      error = ft_stroke_border_lineto( border, &delta, FALSE );   
     }
 
   Exit:
     FT_Angle         phi, theta, rotate;
     FT_Fixed         length, thcos, sigma;
     FT_Vector        delta;
-    FT_Error         error = 0;
+    FT_Error         error = FT_Err_Ok;
 
 
     rotate = FT_SIDE_TO_ROTATE( side );
                             stroker->angle_out + rotate );
       delta.x += stroker->center.x;
       delta.y += stroker->center.y;
-      border->movable = 0;
+      border->movable = FALSE;
     }
     else
     {
       delta.y += stroker->center.y;
     }
 
-    error = ft_stroke_border_lineto( border, &delta, 0 );
+    error = ft_stroke_border_lineto( border, &delta, FALSE );
 
     return error;
   }
 
 
     if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
-    {
       error = ft_stroker_arcto( stroker, side );
-    }
     else
     {
       /* this is a mitered or beveled corner */
       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 );
+      theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
       if ( theta == FT_ANGLE_PI )
       {
         theta = rotate;
       thcos = FT_Cos( theta );
       sigma = FT_MulFix( stroker->miter_limit, thcos );
 
-      if ( sigma >= 0x10000L )
-        miter = 0;
+      /* FT_Sin(x) = 0 for x <= 57 */
+      if ( sigma >= 0x10000L || ft_pos_abs( theta ) <= 57 )
+        miter = FALSE;
 
       if ( miter )  /* this is a miter (broken angle) */
       {
         delta.x += middle.x;
         delta.y += middle.y;
 
-        error = ft_stroke_border_lineto( border, &delta, 0 );
+        error = ft_stroke_border_lineto( border, &delta, FALSE );
         if ( error )
           goto Exit;
 
         delta.x += middle.x;
         delta.y += middle.y;
 
-        error = ft_stroke_border_lineto( border, &delta, 0 );
+        error = ft_stroke_border_lineto( border, &delta, FALSE );
         if ( error )
           goto Exit;
 
         delta.x += stroker->center.x;
         delta.y += stroker->center.y;
 
-        error = ft_stroke_border_lineto( border, &delta, 1 );
+        error = ft_stroke_border_lineto( border, &delta, TRUE );
       }
 
       else /* this is a bevel (intersection) */
         delta.x += stroker->center.x;
         delta.y += stroker->center.y;
 
-        error = ft_stroke_border_lineto( border, &delta, 0 );
-        if (error) goto Exit;
+        error = ft_stroke_border_lineto( border, &delta, FALSE );
+        if ( error )
+          goto Exit;
 
         /* now add end point */
         FT_Vector_From_Polar( &delta, stroker->radius,
         delta.x += stroker->center.x;
         delta.y += stroker->center.y;
 
-        error = ft_stroke_border_lineto( border, &delta, 1 );
+        error = ft_stroke_border_lineto( border, &delta, TRUE );
       }
     }
 
   static FT_Error
   ft_stroker_process_corner( FT_Stroker  stroker )
   {
-    FT_Error  error = 0;
+    FT_Error  error = FT_Err_Ok;
     FT_Angle  turn;
     FT_Int    inside_side;
 
 
 
   /* add two points to the left and right borders corresponding to the */
-  /* start of the subpath..                                            */
+  /* start of the subpath                                              */
   static FT_Error
   ft_stroker_subpath_start( FT_Stroker  stroker,
                             FT_Angle    start_angle )
 
     /* save angle for last cap */
     stroker->subpath_angle = start_angle;
-    stroker->first_point   = 0;
+    stroker->first_point   = FALSE;
 
   Exit:
     return error;
   FT_Stroker_LineTo( FT_Stroker  stroker,
                      FT_Vector*  to )
   {
-    FT_Error         error = 0;
+    FT_Error         error = FT_Err_Ok;
     FT_StrokeBorder  border;
     FT_Vector        delta;
     FT_Angle         angle;
         goto Exit;
     }
 
-    /* now add a line segment to both the "inside" and "outside" paths */
+    /* now add a line segment to both the `inside' and `outside' paths */
 
     for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
     {
       point.x = to->x + delta.x;
       point.y = to->y + delta.y;
 
-      error = ft_stroke_border_lineto( border, &point, 1 );
+      error = ft_stroke_border_lineto( border, &point, TRUE );
       if ( error )
         goto Exit;
 
                       FT_Vector*  control,
                       FT_Vector*  to )
   {
-    FT_Error    error = 0;
+    FT_Error    error = FT_Err_Ok;
     FT_Vector   bez_stack[34];
     FT_Vector*  arc;
     FT_Vector*  limit = bez_stack + 30;
     FT_Angle    start_angle;
-    FT_Bool     first_arc = 1;
+    FT_Bool     first_arc = TRUE;
 
 
     arc    = bez_stack;
 
       if ( first_arc )
       {
-        first_arc = 0;
+        first_arc = FALSE;
 
         start_angle = angle_in;
 
                       FT_Vector*  control2,
                       FT_Vector*  to )
   {
-    FT_Error    error = 0;
+    FT_Error    error = FT_Err_Ok;
     FT_Vector   bez_stack[37];
     FT_Vector*  arc;
     FT_Vector*  limit = bez_stack + 32;
     FT_Angle    start_angle;
-    FT_Bool     first_arc = 1;
+    FT_Bool     first_arc = TRUE;
 
 
     arc    = bez_stack;
 
       if ( first_arc )
       {
-        first_arc = 0;
+        first_arc = FALSE;
 
         /* process corner if necessary */
         start_angle = angle_in;
         phi1    = (angle_mid + angle_in ) / 2;
         phi2    = (angle_mid + angle_out ) / 2;
         length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
-        length2 = FT_DivFix( stroker->radius, FT_Cos(theta2) );
+        length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );
 
         for ( side = 0; side <= 1; side++ )
         {
   {
     /* We cannot process the first point, because there is not enough      */
     /* information regarding its corner/cap.  The latter will be processed */
-    /* in the "end_subpath" routine.                                       */
+    /* in the `FT_Stroker_EndSubPath' routine.                             */
     /*                                                                     */
-    stroker->first_point   = 1;
-    stroker->center        = *to;
-    stroker->subpath_open  = open;
+    stroker->first_point  = TRUE;
+    stroker->center       = *to;
+    stroker->subpath_open = open;
 
-    /* record the subpath start point index for each border */
+    /* record the subpath start point for each border */
     stroker->subpath_start = *to;
-    return 0;
+
+    return FT_Err_Ok;
   }
 
 
   ft_stroker_add_reverse_left( FT_Stroker  stroker,
                                FT_Bool     open )
   {
-    FT_StrokeBorder  right  = stroker->borders + 0;
-    FT_StrokeBorder  left   = stroker->borders + 1;
+    FT_StrokeBorder  right = stroker->borders + 0;
+    FT_StrokeBorder  left  = stroker->borders + 1;
     FT_Int           new_points;
-    FT_Error         error  = 0;
+    FT_Error         error = FT_Err_Ok;
 
 
     FT_ASSERT( left->start >= 0 );
       left->num_points   = left->start;
       right->num_points += new_points;
 
-      right->movable = 0;
-      left->movable  = 0;
+      right->movable = FALSE;
+      left->movable  = FALSE;
     }
 
   Exit:
   FT_EXPORT_DEF( FT_Error )
   FT_Stroker_EndSubPath( FT_Stroker  stroker )
   {
-    FT_Error  error  = 0;
+    FT_Error  error = FT_Err_Ok;
+
 
     if ( stroker->subpath_open )
     {
       if ( error )
         goto Exit;
 
-      /* add reversed points from "left" to "right" */
-      error = ft_stroker_add_reverse_left( stroker, 1 );
+      /* add reversed points from `left' to `right' */
+      error = ft_stroker_add_reverse_left( stroker, TRUE );
       if ( error )
         goto Exit;
 
 
       /* Now end the right subpath accordingly.  The left one is */
       /* rewind and doesn't need further processing.             */
-      ft_stroke_border_close( right, 0 );
+      ft_stroke_border_close( right, FALSE );
     }
     else
     {
       }
 
       /* then end our two subpaths */
-      ft_stroke_border_close( stroker->borders + 0, 1 );
-      ft_stroke_border_close( stroker->borders + 1, 0 );
+      ft_stroke_border_close( stroker->borders + 0, TRUE );
+      ft_stroke_border_close( stroker->borders + 1, FALSE );
     }
 
   Exit:
       v_control = v_start;
 
       point = outline->points + first;
-      tags  = outline->tags  + first;
+      tags  = outline->tags   + first;
       tag   = FT_CURVE_TAG( tags[0] );
 
       /* A contour cannot start with a cubic control point! */
         }
         else
         {
-          /* if both first and last points are conic,         */
-          /* start at their middle and record its position    */
-          /* for closure                                      */
+          /* if both first and last points are conic, */
+          /* start at their middle                    */
           v_start.x = ( v_start.x + v_last.x ) / 2;
           v_start.y = ( v_start.y + v_last.y ) / 2;
-
-          v_last = v_start;
         }
         point--;
         tags--;
       first = last + 1;
     }
 
-    return 0;
+    return FT_Err_Ok;
 
   Exit:
     return error;
     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 */
+#ifndef FT_CONFIG_OPTION_PIC
   extern const FT_Glyph_Class  ft_outline_glyph_class;
+#endif
+#include "basepic.h"
 
 
   /* documentation is in ftstroke.h */
   {
     FT_Error  error = FT_Err_Invalid_Argument;
     FT_Glyph  glyph = NULL;
-
+    FT_Library library = stroker->library;
+    FT_UNUSED(library);
 
     if ( pglyph == NULL )
       goto Exit;
 
     glyph = *pglyph;
-    if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class )
+    if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
       goto Exit;
 
     {
       FT_UInt          num_points, num_contours;
 
 
-      error = FT_Stroker_ParseOutline( stroker, outline, 0 );
+      error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
       if ( error )
         goto Fail;
 
   {
     FT_Error  error = FT_Err_Invalid_Argument;
     FT_Glyph  glyph = NULL;
-
+    FT_Library library = stroker->library;
+    FT_UNUSED(library);
 
     if ( pglyph == NULL )
       goto Exit;
 
     glyph = *pglyph;
-    if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class )
+    if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
       goto Exit;
 
     {
           border = FT_STROKER_BORDER_LEFT;
       }
 
-      error = FT_Stroker_ParseOutline( stroker, outline, 0 );
+      error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
       if ( error )
         goto Fail;