1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ftstroke.c                                                             */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    FreeType path stroker (body).                                        */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner/*  Copyright 2002-2006, 2008-2011 by                                      */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_STROKER_H
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRIGONOMETRY_H
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_OUTLINE_H
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_MEMORY_H
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_StrokerBorder )
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_GetInsideBorder( FT_Outline*  outline )
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Orientation  o = FT_Outline_Get_Orientation( outline );
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
37c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                        : FT_STROKER_BORDER_LEFT;
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_StrokerBorder )
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_GetOutsideBorder( FT_Outline*  outline )
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Orientation  o = FT_Outline_Get_Orientation( outline );
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT
50c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                        : FT_STROKER_BORDER_RIGHT;
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
54c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
55c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
56c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                                                               *****/
57c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                      BEZIER COMPUTATIONS                      *****/
58c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                                                               *****/
59c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
60c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SMALL_CONIC_THRESHOLD  ( FT_ANGLE_PI / 6 )
63c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define FT_SMALL_CUBIC_THRESHOLD  ( FT_ANGLE_PI / 8 )
64c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_EPSILON  2
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_IS_SMALL( x )  ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_pos_abs( FT_Pos  x )
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
73c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    return x >= 0 ? x : -x;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_conic_split( FT_Vector*  base )
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  a, b;
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].x = base[2].x;
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].x;
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = base[3].x = ( base[2].x + b ) / 2;
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].x = ( base[0].x + b ) / 2;
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].x = ( a + b ) / 2;
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].y = base[2].y;
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].y;
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = base[3].y = ( base[2].y + b ) / 2;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].y = ( base[0].y + b ) / 2;
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].y = ( a + b ) / 2;
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Bool
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_conic_is_small_enough( FT_Vector*  base,
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Angle   *angle_in,
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Angle   *angle_out )
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  d1, d2;
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle   theta;
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     close1, close2;
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d1.x = base[1].x - base[2].x;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d1.y = base[1].y - base[2].y;
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d2.x = base[0].x - base[1].x;
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d2.y = base[0].y - base[1].y;
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( close1 )
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( close2 )
118c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
119c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* basically a point;                      */
120c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* do nothing to retain original direction */
121c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
123c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
124c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        *angle_in  =
125c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        *angle_out = FT_Atan2( d2.x, d2.y );
126c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    else /* !close1 */
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
130c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( close2 )
131c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
132c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        *angle_in  =
133c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        *angle_out = FT_Atan2( d1.x, d1.y );
134c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
135c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      else
136c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        *angle_in  = FT_Atan2( d1.x, d1.y );
138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        *angle_out = FT_Atan2( d2.x, d2.y );
139c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_cubic_split( FT_Vector*  base )
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  a, b, c, d;
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[6].x = base[3].x;
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = base[1].x;
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d = base[2].x;
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[1].x = a = ( base[0].x + c ) / 2;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[5].x = b = ( base[3].x + d ) / 2;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = ( c + d ) / 2;
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].x = a = ( a + c ) / 2;
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].x = b = ( b + c ) / 2;
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[3].x = ( a + b ) / 2;
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[6].y = base[3].y;
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = base[1].y;
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d = base[2].y;
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[1].y = a = ( base[0].y + c ) / 2;
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[5].y = b = ( base[3].y + d ) / 2;
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = ( c + d ) / 2;
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].y = a = ( a + c ) / 2;
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].y = b = ( b + c ) / 2;
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[3].y = ( a + b ) / 2;
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
176c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* Return the average of `angle1' and `angle2'.            */
177c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* This gives correct result even if `angle1' and `angle2' */
178c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* have opposite signs.                                    */
179c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  static FT_Angle
180c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  ft_angle_mean( FT_Angle  angle1,
181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                 FT_Angle  angle2 )
182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  {
183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2;
184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  }
185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Bool
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_cubic_is_small_enough( FT_Vector*  base,
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Angle   *angle_in,
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Angle   *angle_mid,
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Angle   *angle_out )
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  d1, d2, d3;
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle   theta1, theta2;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     close1, close2, close3;
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d1.x = base[2].x - base[3].x;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d1.y = base[2].y - base[3].y;
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d2.x = base[1].x - base[2].x;
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d2.y = base[1].y - base[2].y;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d3.x = base[0].x - base[1].x;
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d3.y = base[0].y - base[1].y;
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
209c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( close1 )
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( close2 )
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
213c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( close3 )
214c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
215c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* basically a point;                      */
216c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* do nothing to retain original direction */
217c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
218c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        else /* !close3 */
219c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
220c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  =
221c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid =
222c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d3.x, d3.y );
223c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      else /* !close2 */
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( close3 )
228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  =
230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid =
231c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d2.x, d2.y );
232c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
233c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        else /* !close3 */
234c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
235c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  =
236c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid = FT_Atan2( d2.x, d2.y );
237c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d3.x, d3.y );
238c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    else /* !close1 */
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
243c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( close2 )
244c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( close3 )
246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  =
248c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid =
249c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d1.x, d1.y );
250c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
251c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        else /* !close3 */
252c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
253c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  = FT_Atan2( d1.x, d1.y );
254c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d3.x, d3.y );
255c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid = ft_angle_mean( *angle_in, *angle_out );
256c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
257c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
258c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      else /* !close2 */
259c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
260c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( close3 )
261c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  = FT_Atan2( d1.x, d1.y );
263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid =
264c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d2.x, d2.y );
265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        else /* !close3 */
267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
268c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_in  = FT_Atan2( d1.x, d1.y );
269c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_mid = FT_Atan2( d2.x, d2.y );
270c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          *angle_out = FT_Atan2( d3.x, d3.y );
271c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
272c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in,  *angle_mid ) );
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    theta2 < FT_SMALL_CUBIC_THRESHOLD );
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
283c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
284c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
285c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                                                               *****/
286c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                       STROKE BORDERS                          *****/
287c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                                                               *****/
288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
289c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef enum  FT_StrokeTags_
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_STROKE_TAG_ON    = 1,   /* on-curve point  */
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_STROKE_TAG_CUBIC = 2,   /* cubic off-point */
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_STROKE_TAG_BEGIN = 4,   /* sub-path start  */
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_STROKE_TAG_END   = 8    /* sub-path end    */
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } FT_StrokeTags;
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
300c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define  FT_STROKE_TAG_BEGIN_END  ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END )
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  FT_StrokeBorderRec_
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     num_points;
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     max_points;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  points;
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    tags;
308c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Bool     movable;  /* TRUE for ends of lineto borders */
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      start;    /* index of current sub-path start point */
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory;
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bool     valid;
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } FT_StrokeBorderRec, *FT_StrokeBorder;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_grow( FT_StrokeBorder  border,
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_UInt          new_points )
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   old_max = border->max_points;
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   new_max = border->num_points + new_points;
32277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error   = FT_Err_Ok;
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( new_max > old_max )
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    cur_max = old_max;
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Memory  memory  = border->memory;
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( cur_max < new_max )
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_max += ( cur_max >> 1 ) + 16;
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           FT_RENEW_ARRAY( border->tags,   old_max, cur_max ) )
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->max_points = cur_max;
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
34077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_close( FT_StrokeBorder  border,
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Bool          reverse )
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  start = border->start;
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  count = border->num_points;
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( border->start >= 0 );
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* don't record empty paths! */
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( count <= start + 1U )
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->num_points = start;
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* copy the last point to the start of this sub-path, since */
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* it contains the `adjusted' starting coordinates          */
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->num_points    = --count;
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->points[start] = border->points[count];
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( reverse )
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* reverse the points */
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector*  vec1 = border->points + start + 1;
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector*  vec2 = border->points + count - 1;
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; vec1 < vec2; vec1++, vec2-- )
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  tmp;
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tmp   = *vec1;
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            *vec1 = *vec2;
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            *vec2 = tmp;
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* then the tags */
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  tag1 = border->tags + start + 1;
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  tag2 = border->tags + count - 1;
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; tag1 < tag2; tag1++, tag2-- )
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Byte  tmp;
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tmp   = *tag1;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            *tag1 = *tag2;
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            *tag2 = tmp;
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->tags[start    ] |= FT_STROKE_TAG_BEGIN;
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->tags[count - 1] |= FT_STROKE_TAG_END;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->start   = -1;
40877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->movable = FALSE;
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_lineto( FT_StrokeBorder  border,
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Vector*       to,
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Bool          movable )
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
41777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error = FT_Err_Ok;
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( border->start >= 0 );
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( border->movable )
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* move last point */
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->points[border->num_points - 1] = *to;
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
429c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* don't add zero-length lineto */
430c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( border->num_points > 0                                          &&
431c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner           FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
432c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner           FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
433c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        return error;
434c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add one point */
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroke_border_grow( border, 1 );
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !error )
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  vec = border->points + border->num_points;
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*    tag = border->tags   + border->num_points;
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        vec[0] = *to;
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_STROKE_TAG_ON;
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        border->num_points += 1;
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->movable = movable;
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_conicto( FT_StrokeBorder  border,
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Vector*       control,
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Vector*       to )
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( border->start >= 0 );
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_grow( border, 2 );
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector*  vec = border->points + border->num_points;
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*    tag = border->tags   + border->num_points;
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
470c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec[0] = *control;
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec[1] = *to;
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag[0] = 0;
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag[1] = FT_STROKE_TAG_ON;
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->num_points += 2;
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
479c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
48077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->movable = FALSE;
481c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_cubicto( FT_StrokeBorder  border,
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Vector*       control1,
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Vector*       control2,
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Vector*       to )
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( border->start >= 0 );
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_grow( border, 3 );
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector*  vec = border->points + border->num_points;
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*    tag = border->tags   + border->num_points;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec[0] = *control1;
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec[1] = *control2;
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec[2] = *to;
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag[0] = FT_STROKE_TAG_CUBIC;
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag[1] = FT_STROKE_TAG_CUBIC;
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag[2] = FT_STROKE_TAG_ON;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border->num_points += 3;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
514c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
51577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->movable = FALSE;
516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_ARC_CUBIC_ANGLE  ( FT_ANGLE_PI / 2 )
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_arcto( FT_StrokeBorder  border,
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Vector*       center,
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Fixed         radius,
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Angle         angle_start,
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Angle         angle_diff )
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle   total, angle, step, rotate, next, theta;
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  a, b, a2, b2;
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   length;
53477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error   error = FT_Err_Ok;
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute start point */
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector_From_Polar( &a, radius, angle_start );
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a.x += center->x;
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a.y += center->y;
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    total  = angle_diff;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    angle  = angle_start;
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( total != 0 )
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      step = total;
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( step > FT_ARC_CUBIC_ANGLE )
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        step = FT_ARC_CUBIC_ANGLE;
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( step < -FT_ARC_CUBIC_ANGLE )
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        step = -FT_ARC_CUBIC_ANGLE;
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next  = angle + step;
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      theta = step;
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( theta < 0 )
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        theta = -theta;
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      theta >>= 1;
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute end point */
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &b, radius, next );
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      b.x += center->x;
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      b.y += center->y;
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute first and second control points */
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      length = FT_MulDiv( radius, FT_Sin( theta ) * 4,
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          ( 0x10000L + FT_Cos( theta ) ) * 3 );
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &a2, length, angle + rotate );
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      a2.x += a.x;
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      a2.y += a.y;
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &b2, length, next - rotate );
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      b2.x += b.x;
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      b2.y += b.y;
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add cubic arc */
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroke_border_cubicto( border, &a2, &b2, &b );
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* process the rest of the arc ?? */
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      a      = b;
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      total -= step;
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      angle  = next;
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_moveto( FT_StrokeBorder  border,
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Vector*       to )
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* close current open path if any ? */
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( border->start >= 0 )
60077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      ft_stroke_border_close( border, FALSE );
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
602c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    border->start = border->num_points;
60377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->movable = FALSE;
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
60577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    return ft_stroke_border_lineto( border, to, FALSE );
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_init( FT_StrokeBorder  border,
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Memory        memory )
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->memory = memory;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->points = NULL;
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->tags   = NULL;
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->num_points = 0;
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->max_points = 0;
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->start      = -1;
62077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->valid      = FALSE;
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_reset( FT_StrokeBorder  border )
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->num_points = 0;
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->start      = -1;
62977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->valid      = FALSE;
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_done( FT_StrokeBorder  border )
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = border->memory;
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( border->points );
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( border->tags );
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->num_points = 0;
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->max_points = 0;
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border->start      = -1;
64577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->valid      = FALSE;
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_get_counts( FT_StrokeBorder  border,
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_UInt         *anum_points,
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_UInt         *anum_contours )
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
65477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error        = FT_Err_Ok;
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_points   = 0;
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_contours = 0;
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     count      = border->num_points;
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  point      = border->points;
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    tags       = border->tags;
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      in_contour = 0;
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, num_points++, point++, tags++ )
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tags[0] & FT_STROKE_TAG_BEGIN )
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( in_contour != 0 )
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Fail;
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        in_contour = 1;
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( in_contour == 0 )
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tags[0] & FT_STROKE_TAG_END )
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        in_contour = 0;
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        num_contours++;
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( in_contour != 0 )
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->valid = TRUE;
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *anum_points   = num_points;
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *anum_contours = num_contours;
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_points   = 0;
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_contours = 0;
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto Exit;
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroke_border_export( FT_StrokeBorder  border,
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Outline*      outline )
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* copy point locations */
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ARRAY_COPY( outline->points + outline->n_points,
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   border->points,
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   border->num_points );
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* copy tags */
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   count = border->num_points;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  read  = border->tags;
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  write = (FT_Byte*)outline->tags + outline->n_points;
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count--, read++, write++ )
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( *read & FT_STROKE_TAG_ON )
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *write = FT_CURVE_TAG_ON;
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( *read & FT_STROKE_TAG_CUBIC )
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *write = FT_CURVE_TAG_CUBIC;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *write = FT_CURVE_TAG_CONIC;
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* copy contours */
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    count = border->num_points;
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   tags  = border->tags;
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Short*  write = outline->contours + outline->n_contours;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Short   idx   = (FT_Short)outline->n_points;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count--, tags++, idx++ )
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( *tags & FT_STROKE_TAG_END )
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *write++ = idx;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          outline->n_contours++;
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
745c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    outline->n_points = (short)( outline->n_points + border->num_points );
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( FT_Outline_Check( outline ) == 0 );
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
751c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
752c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
753c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                                                               *****/
754c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                           STROKER                             *****/
755c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*****                                                               *****/
756c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
757c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SIDE_TO_ROTATE( s )   ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  FT_StrokerRec_
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
763c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Angle             angle_in;             /* direction into curr join */
764c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Angle             angle_out;            /* direction out of join  */
765c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Vector            center;               /* current position */
766c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Fixed             line_length;          /* length of last lineto */
767c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Bool              first_point;          /* is this the start? */
768c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Bool              subpath_open;         /* is the subpath open? */
769c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Angle             subpath_angle;        /* subpath start direction */
770c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Vector            subpath_start;        /* subpath start position */
771c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Fixed             subpath_line_length;  /* subpath start lineto len */
772c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Bool              handle_wide_strokes;  /* use wide strokes logic? */
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stroker_LineCap   line_cap;
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stroker_LineJoin  line_join;
776c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Stroker_LineJoin  line_join_saved;
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed             miter_limit;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed             radius;
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_StrokeBorderRec   borders[2];
781295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Library           library;
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } FT_StrokerRec;
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_New( FT_Library   library,
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Stroker  *astroker )
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory;
794c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Stroker  stroker = NULL;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !library )
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return FT_Err_Invalid_Argument;
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    memory = library->memory;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !FT_NEW( stroker ) )
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
804295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      stroker->library = library;
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_stroke_border_init( &stroker->borders[0], memory );
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_stroke_border_init( &stroker->borders[1], memory );
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
809c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *astroker = stroker;
811c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_Set( FT_Stroker           stroker,
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Fixed             radius,
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Stroker_LineCap   line_cap,
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Stroker_LineJoin  line_join,
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Fixed             miter_limit )
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->radius      = radius;
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->line_cap    = line_cap;
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->line_join   = line_join;
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->miter_limit = miter_limit;
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
830c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* ensure miter limit has sensible value */
831c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( stroker->miter_limit < 0x10000 )
832c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      stroker->miter_limit = 0x10000;
833c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
834c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* save line join style:                                           */
835c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* line join style can be temporarily changed when stroking curves */
836c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->line_join_saved = line_join;
837c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stroker_Rewind( stroker );
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_Rewind( FT_Stroker  stroker )
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( stroker )
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_stroke_border_reset( &stroker->borders[0] );
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_stroke_border_reset( &stroker->borders[1] );
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_Done( FT_Stroker  stroker )
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( stroker )
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
862295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Memory  memory = stroker->library->memory;
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_stroke_border_done( &stroker->borders[0] );
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_stroke_border_done( &stroker->borders[1] );
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
868295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      stroker->library = NULL;
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( stroker );
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
874c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* create a circular arc at a corner or cap */
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroker_arcto( FT_Stroker  stroker,
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Int      side )
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle         total, rotate;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed         radius = stroker->radius;
88177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error         error  = FT_Err_Ok;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_StrokeBorder  border = stroker->borders + side;
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rotate = FT_SIDE_TO_ROTATE( side );
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( total == FT_ANGLE_PI )
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      total = -rotate * 2;
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_arcto( border,
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    &stroker->center,
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    radius,
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    stroker->angle_in + rotate,
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    total );
89677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    border->movable = FALSE;
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
901c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* add a cap at the end of an opened path */
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroker_cap( FT_Stroker  stroker,
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Angle    angle,
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Int      side )
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
90777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error = FT_Err_Ok;
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add a round cap */
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      stroker->angle_in  = angle;
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      stroker->angle_out = angle + FT_ANGLE_PI;
915c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroker_arcto( stroker, side );
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add a square cap */
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector        delta, delta2;
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed         radius = stroker->radius;
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_StrokeBorder  border = stroker->borders + side;
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &delta2, radius, angle + rotate );
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &delta,  radius, angle );
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.x += stroker->center.x + delta2.x;
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.y += stroker->center.y + delta2.y;
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
93377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = ft_stroke_border_lineto( border, &delta, FALSE );
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &delta2, radius, angle - rotate );
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &delta,  radius, angle );
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.x += delta2.x + stroker->center.x;
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.y += delta2.y + stroker->center.y;
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = ft_stroke_border_lineto( border, &delta, FALSE );
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
945295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT )
946295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
947295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* add a butt ending */
948295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Vector        delta;
949295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
950295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Fixed         radius = stroker->radius;
951295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_StrokeBorder  border = stroker->borders + side;
952295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
953295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
954295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Vector_From_Polar( &delta, radius, angle + rotate );
955295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
956295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      delta.x += stroker->center.x;
957295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      delta.y += stroker->center.y;
958295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
959295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      error = ft_stroke_border_lineto( border, &delta, FALSE );
960295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( error )
961295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        goto Exit;
962295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
963295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Vector_From_Polar( &delta, radius, angle - rotate );
964295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
965295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      delta.x += stroker->center.x;
966295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      delta.y += stroker->center.y;
967295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
968c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      error = ft_stroke_border_lineto( border, &delta, FALSE );
969295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* process an inside corner, i.e. compute intersection */
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroker_inside( FT_Stroker  stroker,
979c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                     FT_Int      side,
980c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                     FT_Fixed    line_length )
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_StrokeBorder  border = stroker->borders + side;
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle         phi, theta, rotate;
984c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Fixed         length, thcos;
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector        delta;
98677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error         error = FT_Err_Ok;
987c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Bool          intersect;          /* use intersection of lines? */
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rotate = FT_SIDE_TO_ROTATE( side );
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
992c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
993c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
994c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* Only intersect borders if between two lineto's and both */
995c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* lines are long enough (line_length is zero for curves). */
996c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( !border->movable || line_length == 0 )
997c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      intersect = FALSE;
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
999c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    {
1000c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* compute minimum required length of lines */
1001c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_Fixed  min_length = ft_pos_abs( FT_MulFix( stroker->radius,
1002c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                                    FT_Tan( theta ) ) );
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1005c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      intersect = FT_BOOL( stroker->line_length >= min_length &&
1006c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                           line_length          >= min_length );
1007c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    }
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1009c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( !intersect )
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &delta, stroker->radius,
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            stroker->angle_out + rotate );
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.x += stroker->center.x;
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.y += stroker->center.y;
1015c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
101677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      border->movable = FALSE;
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1020c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* compute median angle */
1021c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      phi = stroker->angle_in + theta;
1022c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1023c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      thcos = FT_Cos( theta );
1024c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      length = FT_DivFix( stroker->radius, thcos );
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_From_Polar( &delta, length, phi + rotate );
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.x += stroker->center.x;
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.y += stroker->center.y;
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    error = ft_stroke_border_lineto( border, &delta, FALSE );
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* process an outside corner, i.e. compute bevel/miter/round */
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroker_outside( FT_Stroker  stroker,
1041c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      FT_Int      side,
1042c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      FT_Fixed    line_length )
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_StrokeBorder  border = stroker->borders + side;
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error         error;
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle         rotate;
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroker_arcto( stroker, side );
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1053c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* this is a mitered (pointed) or beveled (truncated) corner */
1054c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_Fixed  sigma = 0, radius = stroker->radius;
1055c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_Angle  theta = 0, phi = 0;
1056c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_Fixed  thcos = 0;
1057c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_Bool   bevel, fixed_bevel;
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      rotate = FT_SIDE_TO_ROTATE( side );
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1062c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      bevel =
1063c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
1064c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1065c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      fixed_bevel =
1066c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
1067c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1068c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( !bevel )
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1070c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
1071c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1072c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( theta == FT_ANGLE_PI )
1073c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
1074c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          theta = rotate;
1075c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          phi   = stroker->angle_in;
1076c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
1077c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        else
1078c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
1079c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          theta /= 2;
1080c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          phi    = stroker->angle_in + theta + rotate;
1081c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
1082c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1083c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        thcos = FT_Cos( theta );
1084c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        sigma = FT_MulFix( stroker->miter_limit, thcos );
1085c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1086c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* is miter limit exceeded? */
1087c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( sigma < 0x10000L )
1088c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
1089c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* don't create variable bevels for very small deviations; */
1090c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* FT_Sin(x) = 0 for x <= 57                               */
1091c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
1092c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            bevel = TRUE;
1093c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1095c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1096c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( bevel )  /* this is a bevel (broken angle) */
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1098c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( fixed_bevel )
1099c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
1100c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* the outer corners are simply joined together */
1101c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector  delta;
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1104c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* add bevel */
1105c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector_From_Polar( &delta,
1106c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                radius,
1107c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                stroker->angle_out + rotate );
1108c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.x += stroker->center.x;
1109c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.y += stroker->center.y;
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1111c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          border->movable = FALSE;
1112c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroke_border_lineto( border, &delta, FALSE );
1113c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
1114c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        else /* variable bevel */
1115c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
1116c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* the miter is truncated */
1117c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector  middle, delta;
1118c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Fixed   length;
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1121c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* compute middle point */
1122c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector_From_Polar( &middle,
1123c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                FT_MulFix( radius, stroker->miter_limit ),
1124c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                phi );
1125c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          middle.x += stroker->center.x;
1126c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          middle.y += stroker->center.y;
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* compute first angle point */
1129c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          length = FT_MulFix( radius,
1130c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                              FT_DivFix( 0x10000L - sigma,
1131c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                         ft_pos_abs( FT_Sin( theta ) ) ) );
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1133c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector_From_Polar( &delta, length, phi + rotate );
1134c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.x += middle.x;
1135c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.y += middle.y;
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroke_border_lineto( border, &delta, FALSE );
1138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          if ( error )
1139c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            goto Exit;
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1141c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* compute second angle point */
1142c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector_From_Polar( &delta, length, phi - rotate );
1143c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.x += middle.x;
1144c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.y += middle.y;
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1146c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroke_border_lineto( border, &delta, FALSE );
1147c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          if ( error )
1148c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            goto Exit;
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1150c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* finally, add an end point; only needed if not lineto */
1151c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* (line_length is zero for curves)                     */
1152c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          if ( line_length == 0 )
1153c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          {
1154c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_Vector_From_Polar( &delta,
1155c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                  radius,
1156c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                  stroker->angle_out + rotate );
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1158c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            delta.x += stroker->center.x;
1159c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            delta.y += stroker->center.y;
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1161c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            error = ft_stroke_border_lineto( border, &delta, FALSE );
1162c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          }
1163c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
1164c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
1165c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      else /* this is a miter (intersection) */
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Fixed   length;
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector  delta;
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        length = FT_DivFix( stroker->radius, thcos );
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector_From_Polar( &delta, length, phi );
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta.x += stroker->center.x;
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta.y += stroker->center.y;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
117777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        error = ft_stroke_border_lineto( border, &delta, FALSE );
117877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( error )
117977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          goto Exit;
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* now add an end point; only needed if not lineto */
1182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* (line_length is zero for curves)                */
1183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( line_length == 0 )
1184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        {
1185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_Vector_From_Polar( &delta,
1186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                stroker->radius,
1187c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                stroker->angle_out + rotate );
1188c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.x += stroker->center.x;
1189c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          delta.y += stroker->center.y;
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1191c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroke_border_lineto( border, &delta, FALSE );
1192c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        }
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1202c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  ft_stroker_process_corner( FT_Stroker  stroker,
1203c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                             FT_Fixed    line_length )
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
120577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error = FT_Err_Ok;
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle  turn;
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int    inside_side;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* no specific corner processing is required if the turn is 0 */
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( turn == 0 )
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* when we turn to the right, the inside side is 0 */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    inside_side = 0;
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* otherwise, the inside side is 1 */
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( turn < 0 )
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      inside_side = 1;
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* process the inside side */
1224c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    error = ft_stroker_inside( stroker, inside_side, line_length );
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* process the outside side */
1229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    error = ft_stroker_outside( stroker, 1 - inside_side, line_length );
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* add two points to the left and right borders corresponding to the */
123777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* start of the subpath                                              */
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroker_subpath_start( FT_Stroker  stroker,
1240c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                            FT_Angle    start_angle,
1241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                            FT_Fixed    line_length )
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector        delta;
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector        point;
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error         error;
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_StrokeBorder  border;
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector_From_Polar( &delta, stroker->radius,
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          start_angle + FT_ANGLE_PI2 );
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    point.x = stroker->center.x + delta.x;
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    point.y = stroker->center.y + delta.y;
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border = stroker->borders;
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_moveto( border, &point );
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    point.x = stroker->center.x - delta.x;
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    point.y = stroker->center.y - delta.y;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    border++;
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_moveto( border, &point );
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* save angle, position, and line length for last join */
1267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* (line_length is zero for curves)                    */
1268c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->subpath_angle       = start_angle;
1269c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->first_point         = FALSE;
1270c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->subpath_line_length = line_length;
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_LineTo( FT_Stroker  stroker,
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Vector*  to )
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
128377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error         error = FT_Err_Ok;
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_StrokeBorder  border;
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector        delta;
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle         angle;
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           side;
1288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Fixed         line_length;
1289c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta.x = to->x - stroker->center.x;
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta.y = to->y - stroker->center.y;
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1294c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* a zero-length lineto is a no-op; avoid creating a spurious corner */
1295c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( delta.x == 0 && delta.y == 0 )
1296c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner       goto Exit;
1297c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1298c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* compute length of line */
1299c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    line_length = FT_Vector_Length( &delta );
1300c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    angle = FT_Atan2( delta.x, delta.y );
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* process corner if necessary */
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( stroker->first_point )
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* This is the first segment of a subpath.  We need to     */
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add a point to each border at their respective starting */
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* point locations.                                        */
1310c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      error = ft_stroker_subpath_start( stroker, angle, line_length );
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* process the current corner */
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      stroker->angle_out = angle;
1318c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      error = ft_stroker_process_corner( stroker, line_length );
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
132377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    /* now add a line segment to both the `inside' and `outside' paths */
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector  point;
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point.x = to->x + delta.x;
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point.y = to->y + delta.y;
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1332c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* the ends of lineto borders are movable */
133377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = ft_stroke_border_lineto( border, &point, TRUE );
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.x = -delta.x;
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta.y = -delta.y;
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->angle_in    = angle;
1342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->center      = *to;
1343c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->line_length = line_length;
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_ConicTo( FT_Stroker  stroker,
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Vector*  control,
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Vector*  to )
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
135777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error    error = FT_Err_Ok;
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   bez_stack[34];
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  arc;
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit = bez_stack + 30;
136177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Bool     first_arc = TRUE;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1364c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* if all control points are coincident, this is a no-op; */
1365c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* avoid creating a spurious corner                       */
1366c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( FT_IS_SMALL( stroker->center.x - control->x ) &&
1367c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( stroker->center.y - control->y ) &&
1368c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( control->x        - to->x      ) &&
1369c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( control->y        - to->y      ) )
1370c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    {
1371c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner       stroker->center = *to;
1372c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner       goto Exit;
1373c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    }
1374c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc    = bez_stack;
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[0] = *to;
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[1] = *control;
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[2] = stroker->center;
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( arc >= bez_stack )
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Angle  angle_in, angle_out;
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1385c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* initialize with current direction */
1386c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      angle_in = angle_out = stroker->angle_in;
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( arc < limit                                             &&
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1391c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( stroker->first_point )
1392c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          stroker->angle_in = angle_in;
1393c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ft_conic_split( arc );
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        arc += 2;
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( first_arc )
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
140177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        first_arc = FALSE;
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* process corner if necessary */
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( stroker->first_point )
1405c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroker_subpath_start( stroker, angle_in, 0 );
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1408c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          stroker->angle_out = angle_in;
1409c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroker_process_corner( stroker, 0 );
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1412c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
1413c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                  FT_SMALL_CONIC_THRESHOLD / 4                             )
1414c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
1415c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* if the deviation from one arc to the next is too great, */
1416c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* add a round corner                                      */
1417c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->center    = arc[2];
1418c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->angle_out = angle_in;
1419c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
1420c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1421c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        error = ft_stroker_process_corner( stroker, 0 );
1422c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1423c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* reinstate line join style */
1424c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->line_join = stroker->line_join_saved;
1425c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
1426c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1427c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( error )
1428c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        goto Exit;
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the arc's angle is small enough; we can add it directly to each */
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* border                                                          */
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1433c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Vector        ctrl, end;
1434c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Angle         theta, phi, rotate, alpha0 = 0;
1435c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Fixed         length;
1436c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_StrokeBorder  border;
1437c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Int           side;
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        theta  = FT_Angle_Diff( angle_in, angle_out ) / 2;
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        phi    = angle_in + theta;
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        length = FT_DivFix( stroker->radius, FT_Cos( theta ) );
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1444c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* compute direction of original arc */
1445c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( stroker->handle_wide_strokes )
1446c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y );
1447c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1448c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        for ( border = stroker->borders, side = 0;
1449c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              side <= 1;
1450c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              side++, border++ )
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rotate = FT_SIDE_TO_ROTATE( side );
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* compute control point */
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector_From_Polar( &ctrl, length, phi + rotate );
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ctrl.x += arc[1].x;
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ctrl.y += arc[1].y;
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* compute end point */
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          end.x += arc[0].x;
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          end.y += arc[0].y;
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1464c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          if ( stroker->handle_wide_strokes )
1465c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          {
1466c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_Vector  start;
1467c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_Angle   alpha1;
1468c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1469c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1470c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* determine whether the border radius is greater than the */
1471c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* radius of curvature of the original arc                 */
1472c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            start = border->points[border->num_points - 1];
1473c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1474c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
1475c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1476c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* is the direction of the border arc opposite to */
1477c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* that of the original arc? */
1478c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
1479c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                   FT_ANGLE_PI / 2                             )
1480c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            {
1481c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Angle   beta, gamma;
1482c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Vector  bvec, delta;
1483c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Fixed   blen, sinA, sinB, alen;
1484c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1485c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1486c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              /* use the sine rule to find the intersection point */
1487c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              beta  = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y );
1488c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              gamma = FT_Atan2( arc[0].x - end.x,   arc[0].y - end.y );
1489c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1490c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              bvec.x = end.x - start.x;
1491c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              bvec.y = end.y - start.y;
1492c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1493c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              blen = FT_Vector_Length( &bvec );
1494c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1495c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
1496c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
1497c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1498c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
1499c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1500c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Vector_From_Polar( &delta, alen, beta );
1501c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              delta.x += start.x;
1502c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              delta.y += start.y;
1503c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1504c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              /* circumnavigate the negative sector backwards */
1505c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              border->movable = FALSE;
1506c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_lineto( border, &delta, FALSE );
1507c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1508c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1509c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_lineto( border, &end, FALSE );
1510c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1511c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1512c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_conicto( border, &ctrl, &start );
1513c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1514c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1515c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              /* and then move to the endpoint */
1516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_lineto( border, &end, FALSE );
1517c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1518c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1519c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1520c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              continue;
1521c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            }
1522c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1523c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* else fall through */
1524c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          }
1525c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1526c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* simply add an arc */
1527c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroke_border_conicto( border, &ctrl, &end );
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error )
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Exit;
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      arc -= 2;
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1535c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      stroker->angle_in = angle_out;
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->center = *to;
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_CubicTo( FT_Stroker  stroker,
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Vector*  control1,
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Vector*  control2,
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Vector*  to )
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
155377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error    error = FT_Err_Ok;
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   bez_stack[37];
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  arc;
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit = bez_stack + 32;
155777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Bool     first_arc = TRUE;
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1560c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* if all control points are coincident, this is a no-op; */
1561c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* avoid creating a spurious corner */
1562c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( FT_IS_SMALL( stroker->center.x - control1->x ) &&
1563c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( stroker->center.y - control1->y ) &&
1564c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( control1->x       - control2->x ) &&
1565c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( control1->y       - control2->y ) &&
1566c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( control2->x       - to->x       ) &&
1567c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         FT_IS_SMALL( control2->y       - to->y       ) )
1568c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    {
1569c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner       stroker->center = *to;
1570c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner       goto Exit;
1571c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    }
1572c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc    = bez_stack;
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[0] = *to;
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[1] = *control2;
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[2] = *control1;
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[3] = stroker->center;
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( arc >= bez_stack )
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Angle  angle_in, angle_mid, angle_out;
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1584c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* initialize with current direction */
1585c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      angle_in = angle_out = angle_mid = stroker->angle_in;
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( arc < limit                                         &&
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           !ft_cubic_is_small_enough( arc, &angle_in,
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      &angle_mid, &angle_out ) )
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1591c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( stroker->first_point )
1592c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          stroker->angle_in = angle_in;
1593c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ft_cubic_split( arc );
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        arc += 3;
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( first_arc )
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
160177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        first_arc = FALSE;
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* process corner if necessary */
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( stroker->first_point )
1605c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroker_subpath_start( stroker, angle_in, 0 );
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1608c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          stroker->angle_out = angle_in;
1609c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroker_process_corner( stroker, 0 );
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1612c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
1613c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                  FT_SMALL_CUBIC_THRESHOLD / 4                             )
1614c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
1615c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* if the deviation from one arc to the next is too great, */
1616c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* add a round corner                                      */
1617c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->center    = arc[3];
1618c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->angle_out = angle_in;
1619c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
1620c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1621c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        error = ft_stroker_process_corner( stroker, 0 );
1622c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1623c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* reinstate line join style */
1624c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        stroker->line_join = stroker->line_join_saved;
1625c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
1626c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1627c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( error )
1628c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        goto Exit;
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the arc's angle is small enough; we can add it directly to each */
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* border                                                          */
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1633c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Vector        ctrl1, ctrl2, end;
1634c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Angle         theta1, phi1, theta2, phi2, rotate, alpha0 = 0;
1635c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Fixed         length1, length2;
1636c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_StrokeBorder  border;
1637c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Int           side;
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1640c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        theta1  = FT_Angle_Diff( angle_in,  angle_mid ) / 2;
1641c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        theta2  = FT_Angle_Diff( angle_mid, angle_out ) / 2;
1642c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        phi1    = ft_angle_mean( angle_in,  angle_mid );
1643c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        phi2    = ft_angle_mean( angle_mid, angle_out );
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
1645295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1647c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        /* compute direction of original arc */
1648c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( stroker->handle_wide_strokes )
1649c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y );
1650c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1651c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        for ( border = stroker->borders, side = 0;
1652c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              side <= 1;
1653c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              side++, border++ )
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rotate = FT_SIDE_TO_ROTATE( side );
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* compute control points */
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate );
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ctrl1.x += arc[2].x;
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ctrl1.y += arc[2].y;
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate );
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ctrl2.x += arc[1].x;
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ctrl2.y += arc[1].y;
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* compute end point */
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          end.x += arc[0].x;
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          end.y += arc[0].y;
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1671c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          if ( stroker->handle_wide_strokes )
1672c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          {
1673c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_Vector  start;
1674c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_Angle   alpha1;
1675c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1676c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1677c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* determine whether the border radius is greater than the */
1678c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* radius of curvature of the original arc                 */
1679c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            start = border->points[border->num_points - 1];
1680c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1681c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
1682c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1683c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* is the direction of the border arc opposite to */
1684c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* that of the original arc? */
1685c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
1686c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                   FT_ANGLE_PI / 2                             )
1687c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            {
1688c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Angle   beta, gamma;
1689c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Vector  bvec, delta;
1690c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Fixed   blen, sinA, sinB, alen;
1691c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1692c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1693c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              /* use the sine rule to find the intersection point */
1694c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              beta  = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y );
1695c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              gamma = FT_Atan2( arc[0].x - end.x,   arc[0].y - end.y );
1696c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1697c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              bvec.x = end.x - start.x;
1698c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              bvec.y = end.y - start.y;
1699c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1700c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              blen = FT_Vector_Length( &bvec );
1701c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1702c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
1703c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
1704c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1705c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
1706c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1707c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              FT_Vector_From_Polar( &delta, alen, beta );
1708c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              delta.x += start.x;
1709c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              delta.y += start.y;
1710c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1711c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              /* circumnavigate the negative sector backwards */
1712c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              border->movable = FALSE;
1713c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_lineto( border, &delta, FALSE );
1714c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1715c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1716c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_lineto( border, &end, FALSE );
1717c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1718c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1719c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_cubicto( border,
1720c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                                &ctrl2,
1721c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                                &ctrl1,
1722c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                                &start );
1723c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1724c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1725c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              /* and then move to the endpoint */
1726c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              error = ft_stroke_border_lineto( border, &end, FALSE );
1727c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              if ( error )
1728c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                goto Exit;
1729c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1730c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner              continue;
1731c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            }
1732c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1733c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            /* else fall through */
1734c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          }
1735c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1736c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          /* simply add an arc */
1737c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end );
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error )
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Exit;
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      arc -= 3;
1744c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1745c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      stroker->angle_in = angle_out;
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->center = *to;
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_BeginSubPath( FT_Stroker  stroker,
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Vector*  to,
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Bool     open )
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We cannot process the first point, because there is not enough      */
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* information regarding its corner/cap.  The latter will be processed */
176477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    /* in the `FT_Stroker_EndSubPath' routine.                             */
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
176677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    stroker->first_point  = TRUE;
176777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    stroker->center       = *to;
176877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    stroker->subpath_open = open;
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1770c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* Determine if we need to check whether the border radius is greater */
1771c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* than the radius of curvature of a curve, to handle this case       */
1772c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* specially.  This is only required if bevel joins or butt caps may  */
1773c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* be created, because round & miter joins and round & square caps    */
1774c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* cover the negative sector created with wide strokes.               */
1775c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->handle_wide_strokes =
1776c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND  ||
1777c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner               ( stroker->subpath_open                        &&
1778c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                 stroker->line_cap == FT_STROKER_LINECAP_BUTT ) );
1779c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
178077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    /* record the subpath start point for each border */
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stroker->subpath_start = *to;
178277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1783c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    stroker->angle_in = 0;
1784c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
178577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    return FT_Err_Ok;
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_stroker_add_reverse_left( FT_Stroker  stroker,
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_Bool     open )
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
179377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_StrokeBorder  right = stroker->borders + 0;
179477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_StrokeBorder  left  = stroker->borders + 1;
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           new_points;
179677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error         error = FT_Err_Ok;
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( left->start >= 0 );
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_points = left->num_points - left->start;
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( new_points > 0 )
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroke_border_grow( right, (FT_UInt)new_points );
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  dst_point = right->points + right->num_points;
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*    dst_tag   = right->tags   + right->num_points;
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  src_point = left->points  + left->num_points - 1;
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*    src_tag   = left->tags    + left->num_points - 1;
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1814c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( src_point >= left->points + left->start )
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *dst_point = *src_point;
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *dst_tag   = *src_tag;
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( open )
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1824c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_Byte  ttag =
1825c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                       (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* switch begin/end tags if necessary */
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ttag == FT_STROKE_TAG_BEGIN ||
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 ttag == FT_STROKE_TAG_END   )
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          src_point--;
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          src_tag--;
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dst_point++;
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dst_tag++;
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      left->num_points   = left->start;
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      right->num_points += new_points;
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
184477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      right->movable = FALSE;
184577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      left->movable  = FALSE;
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* there's a lot of magic in this function! */
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_EndSubPath( FT_Stroker  stroker )
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
185977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error = FT_Err_Ok;
186077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( stroker->subpath_open )
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_StrokeBorder  right = stroker->borders;
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1866c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* All right, this is an opened path, we need to add a cap between */
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* right & left, add the reverse of left, then add a final cap     */
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* between left & right.                                           */
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroker_cap( stroker, stroker->angle_in, 0 );
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
187477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* add reversed points from `left' to `right' */
187577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = ft_stroker_add_reverse_left( stroker, TRUE );
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now add the final cap */
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      stroker->center = stroker->subpath_start;
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = ft_stroker_cap( stroker,
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              stroker->subpath_angle + FT_ANGLE_PI, 0 );
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* Now end the right subpath accordingly.  The left one is */
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* rewind and doesn't need further processing.             */
188877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      ft_stroke_border_close( right, FALSE );
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Angle  turn;
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    inside_side;
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1895c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* close the path if needed */
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( stroker->center.x != stroker->subpath_start.x ||
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           stroker->center.y != stroker->subpath_start.y )
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1900c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
1901c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner         if ( error )
1902c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner           goto Exit;
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* process the corner */
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      stroker->angle_out = stroker->subpath_angle;
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      turn               = FT_Angle_Diff( stroker->angle_in,
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          stroker->angle_out );
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* no specific corner processing is required if the turn is 0 */
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( turn != 0 )
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* when we turn to the right, the inside side is 0 */
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        inside_side = 0;
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* otherwise, the inside side is 1 */
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( turn < 0 )
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          inside_side = 1;
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1920c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        error = ft_stroker_inside( stroker,
1921c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                   inside_side,
1922c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                   stroker->subpath_line_length );
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* process the outside side */
1927c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        error = ft_stroker_outside( stroker,
1928c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                    1 - inside_side,
1929c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                    stroker->subpath_line_length );
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* then end our two subpaths */
1935c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      ft_stroke_border_close( stroker->borders + 0, FALSE );
1936c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      ft_stroke_border_close( stroker->borders + 1, TRUE );
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_GetBorderCounts( FT_Stroker        stroker,
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_StrokerBorder  border,
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_UInt          *anum_points,
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_UInt          *anum_contours )
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_points = 0, num_contours = 0;
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !stroker || border > 1 )
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Err_Invalid_Argument;
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_get_counts( stroker->borders + border,
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         &num_points, &num_contours );
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( anum_points )
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *anum_points = num_points;
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( anum_contours )
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *anum_contours = num_contours;
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_GetCounts( FT_Stroker  stroker,
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt    *anum_points,
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt    *anum_contours )
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count1, count2, num_points   = 0;
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count3, count4, num_contours = 0;
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_get_counts( stroker->borders + 0,
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         &count1, &count2 );
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_stroke_border_get_counts( stroker->borders + 1,
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         &count3, &count4 );
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_points   = count1 + count3;
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_contours = count2 + count4;
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *anum_points   = num_points;
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *anum_contours = num_contours;
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_ExportBorder( FT_Stroker        stroker,
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_StrokerBorder  border,
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Outline*       outline )
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( border == FT_STROKER_BORDER_LEFT  ||
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         border == FT_STROKER_BORDER_RIGHT )
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_StrokeBorder  sborder = & stroker->borders[border];
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( sborder->valid )
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ft_stroke_border_export( sborder, outline );
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_Export( FT_Stroker   stroker,
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Outline*  outline )
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline );
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline );
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *  The following is very similar to FT_Outline_Decompose, except
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *  that we do support opened paths, and do not scale the outline.
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   */
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Stroker_ParseOutline( FT_Stroker   stroker,
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Outline*  outline,
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Bool      opened )
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_last;
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_control;
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_start;
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  point;
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit;
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tags;
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2058c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Int      n;         /* index of contour in outline     */
2059c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_UInt     first;     /* index of first point in contour */
2060c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Int      tag;       /* current point's state           */
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline || !stroker )
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return FT_Err_Invalid_Argument;
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stroker_Rewind( stroker );
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = 0;
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < outline->n_contours; n++ )
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  last;  /* index of last point in contour */
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last  = outline->contours[n];
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      limit = outline->points + last;
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip empty points; we don't stroke these */
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( last <= first )
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = last + 1;
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_start = outline->points[first];
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_last  = outline->points[last];
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_control = v_start;
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point = outline->points + first;
209177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      tags  = outline->tags   + first;
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag   = FT_CURVE_TAG( tags[0] );
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A contour cannot start with a cubic control point! */
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CUBIC )
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Invalid_Outline;
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check first point to determine origin */
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CONIC )
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* First point is conic control.  Yes, this happens. */
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at last point if it is on the curve */
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start = v_last;
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          limit--;
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2110295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          /* if both first and last points are conic, */
2111295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          /* start at their middle                    */
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.x = ( v_start.x + v_last.x ) / 2;
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.y = ( v_start.y + v_last.y ) / 2;
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point--;
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags--;
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Stroker_BeginSubPath( stroker, &v_start, opened );
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( point < limit )
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags++;
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag = FT_CURVE_TAG( tags[0] );
2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        switch ( tag )
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_ON:  /* emit a single line_to */
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec;
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.x = point->x;
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.y = point->y;
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = FT_Stroker_LineTo( stroker, &vec );
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( error )
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_control.x = point->x;
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_control.y = point->y;
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        Do_Conic:
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point < limit )
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec;
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  v_middle;
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point++;
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tags++;
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tag = FT_CURVE_TAG( tags[0] );
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec = point[0];
2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( tag == FT_CURVE_TAG_ON )
2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = FT_Stroker_ConicTo( stroker, &v_control, &vec );
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              continue;
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( tag != FT_CURVE_TAG_CONIC )
2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Invalid_Outline;
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v_middle.x = ( v_control.x + vec.x ) / 2;
2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v_middle.y = ( v_control.y + vec.y ) / 2;
2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( error )
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v_control = vec;
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Do_Conic;
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Close;
2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        default:  /* FT_CURVE_TAG_CUBIC */
2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec1, vec2;
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point + 1 > limit                             ||
2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Invalid_Outline;
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point += 2;
2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tags  += 2;
2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec1 = point[-2];
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec2 = point[-1];
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point <= limit )
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Vector  vec;
2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec = point[0];
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              continue;
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Close;
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Close:
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      /* don't try to end the path if no segments have been generated */
2226c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( !stroker->first_point )
2227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      {
2228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        error = FT_Stroker_EndSubPath( stroker );
2229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        if ( error )
2230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          goto Exit;
2231c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      }
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = last + 1;
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
223677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    return FT_Err_Ok;
2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Invalid_Outline:
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Err_Invalid_Outline;
2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
2246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* declare an extern to access `ft_outline_glyph_class' globally     */
2247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* allocated  in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
2248c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* macro to access it when FT_CONFIG_OPTION_PIC is defined           */
2249295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_CONFIG_OPTION_PIC
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  extern const FT_Glyph_Class  ft_outline_glyph_class;
2251295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif
2252295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "basepic.h"
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Glyph_Stroke( FT_Glyph    *pglyph,
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Stroker   stroker,
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Bool      destroy )
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Error    error   = FT_Err_Invalid_Argument;
2263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Glyph    glyph   = NULL;
2264c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Library  library = stroker->library;
2265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
2266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_UNUSED( library );
2267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( pglyph == NULL )
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph = *pglyph;
2273295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Glyph  copy;
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Glyph_Copy( glyph, &copy );
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph = copy;
2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_OutlineGlyph  oglyph  = (FT_OutlineGlyph)glyph;
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Outline*      outline = &oglyph->outline;
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt          num_points, num_contours;
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
229377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Outline_Done( glyph->library, outline );
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Outline_New( glyph->library,
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              num_points, num_contours, outline );
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      outline->n_points   = 0;
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      outline->n_contours = 0;
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stroker_Export( stroker, outline );
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( destroy )
2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Done_Glyph( *pglyph );
2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pglyph = glyph;
2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto Exit;
2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Done_Glyph( glyph );
2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph = NULL;
2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !destroy )
2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *pglyph = NULL;
2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftstroke.h */
2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Glyph_StrokeBorder( FT_Glyph    *pglyph,
2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Stroker   stroker,
2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Bool      inside,
2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Bool      destroy )
2337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2338c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Error    error   = FT_Err_Invalid_Argument;
2339c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Glyph    glyph   = NULL;
2340c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Library  library = stroker->library;
2341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
2342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_UNUSED( library );
2343c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( pglyph == NULL )
2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph = *pglyph;
2349295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Glyph  copy;
2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Glyph_Copy( glyph, &copy );
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph = copy;
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2364c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      FT_OutlineGlyph   oglyph  = (FT_OutlineGlyph)glyph;
2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_StrokerBorder  border;
2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Outline*       outline = &oglyph->outline;
2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt           num_points, num_contours;
2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      border = FT_Outline_GetOutsideBorder( outline );
2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( inside )
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( border == FT_STROKER_BORDER_LEFT )
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          border = FT_STROKER_BORDER_RIGHT;
2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          border = FT_STROKER_BORDER_LEFT;
2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
237977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (void)FT_Stroker_GetBorderCounts( stroker, border,
2384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        &num_points, &num_contours );
2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Outline_Done( glyph->library, outline );
2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Outline_New( glyph->library,
2389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              num_points,
2390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              num_contours,
2391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              outline );
2392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
2394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      outline->n_points   = 0;
2396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      outline->n_contours = 0;
2397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stroker_ExportBorder( stroker, border, outline );
2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( destroy )
2402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Done_Glyph( *pglyph );
2403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pglyph = glyph;
2405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto Exit;
2406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
2408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Done_Glyph( glyph );
2409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph = NULL;
2410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !destroy )
2412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *pglyph = NULL;
2413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
2420