xref: /inferno-os/libfreetype/ftoutln.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftoutln.c                                                              */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType outline management (body).                                  */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth   /*************************************************************************/
20*37da2899SCharles.Forsyth   /*                                                                       */
21*37da2899SCharles.Forsyth   /* All functions are declared in freetype.h.                             */
22*37da2899SCharles.Forsyth   /*                                                                       */
23*37da2899SCharles.Forsyth   /*************************************************************************/
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth #include <ft2build.h>
27*37da2899SCharles.Forsyth #include FT_OUTLINE_H
28*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth 
31*37da2899SCharles.Forsyth   /*************************************************************************/
32*37da2899SCharles.Forsyth   /*                                                                       */
33*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
34*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
35*37da2899SCharles.Forsyth   /* messages during execution.                                            */
36*37da2899SCharles.Forsyth   /*                                                                       */
37*37da2899SCharles.Forsyth #undef  FT_COMPONENT
38*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_outline
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth   static
42*37da2899SCharles.Forsyth   const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth 
45*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Decompose(FT_Outline * outline,const FT_Outline_Funcs * func_interface,void * user)48*37da2899SCharles.Forsyth   FT_Outline_Decompose( FT_Outline*              outline,
49*37da2899SCharles.Forsyth                         const FT_Outline_Funcs*  func_interface,
50*37da2899SCharles.Forsyth                         void*                    user )
51*37da2899SCharles.Forsyth   {
52*37da2899SCharles.Forsyth #undef SCALED
53*37da2899SCharles.Forsyth #define SCALED( x )  ( ( (x) << shift ) - delta )
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth     FT_Vector   v_last;
56*37da2899SCharles.Forsyth     FT_Vector   v_control;
57*37da2899SCharles.Forsyth     FT_Vector   v_start;
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth     FT_Vector*  point;
60*37da2899SCharles.Forsyth     FT_Vector*  limit;
61*37da2899SCharles.Forsyth     char*       tags;
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth     FT_Error    error;
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth     FT_Int   n;         /* index of contour in outline     */
66*37da2899SCharles.Forsyth     FT_UInt  first;     /* index of first point in contour */
67*37da2899SCharles.Forsyth     FT_Int   tag;       /* current point's state           */
68*37da2899SCharles.Forsyth 
69*37da2899SCharles.Forsyth     FT_Int   shift;
70*37da2899SCharles.Forsyth     FT_Pos   delta;
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth 
73*37da2899SCharles.Forsyth     if ( !outline || !func_interface )
74*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth     shift = func_interface->shift;
77*37da2899SCharles.Forsyth     delta = func_interface->delta;
78*37da2899SCharles.Forsyth     first = 0;
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth     for ( n = 0; n < outline->n_contours; n++ )
81*37da2899SCharles.Forsyth     {
82*37da2899SCharles.Forsyth       FT_Int  last;  /* index of last point in contour */
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth 
85*37da2899SCharles.Forsyth       last  = outline->contours[n];
86*37da2899SCharles.Forsyth       limit = outline->points + last;
87*37da2899SCharles.Forsyth 
88*37da2899SCharles.Forsyth       v_start = outline->points[first];
89*37da2899SCharles.Forsyth       v_last  = outline->points[last];
90*37da2899SCharles.Forsyth 
91*37da2899SCharles.Forsyth       v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
92*37da2899SCharles.Forsyth       v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth       v_control = v_start;
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth       point = outline->points + first;
97*37da2899SCharles.Forsyth       tags  = outline->tags  + first;
98*37da2899SCharles.Forsyth       tag   = FT_CURVE_TAG( tags[0] );
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth       /* A contour cannot start with a cubic control point! */
101*37da2899SCharles.Forsyth       if ( tag == FT_CURVE_TAG_CUBIC )
102*37da2899SCharles.Forsyth         goto Invalid_Outline;
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth       /* check first point to determine origin */
105*37da2899SCharles.Forsyth       if ( tag == FT_CURVE_TAG_CONIC )
106*37da2899SCharles.Forsyth       {
107*37da2899SCharles.Forsyth         /* first point is conic control.  Yes, this happens. */
108*37da2899SCharles.Forsyth         if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
109*37da2899SCharles.Forsyth         {
110*37da2899SCharles.Forsyth           /* start at last point if it is on the curve */
111*37da2899SCharles.Forsyth           v_start = v_last;
112*37da2899SCharles.Forsyth           limit--;
113*37da2899SCharles.Forsyth         }
114*37da2899SCharles.Forsyth         else
115*37da2899SCharles.Forsyth         {
116*37da2899SCharles.Forsyth           /* if both first and last points are conic,         */
117*37da2899SCharles.Forsyth           /* start at their middle and record its position    */
118*37da2899SCharles.Forsyth           /* for closure                                      */
119*37da2899SCharles.Forsyth           v_start.x = ( v_start.x + v_last.x ) / 2;
120*37da2899SCharles.Forsyth           v_start.y = ( v_start.y + v_last.y ) / 2;
121*37da2899SCharles.Forsyth 
122*37da2899SCharles.Forsyth           v_last = v_start;
123*37da2899SCharles.Forsyth         }
124*37da2899SCharles.Forsyth         point--;
125*37da2899SCharles.Forsyth         tags--;
126*37da2899SCharles.Forsyth       }
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth       error = func_interface->move_to( &v_start, user );
129*37da2899SCharles.Forsyth       if ( error )
130*37da2899SCharles.Forsyth         goto Exit;
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth       while ( point < limit )
133*37da2899SCharles.Forsyth       {
134*37da2899SCharles.Forsyth         point++;
135*37da2899SCharles.Forsyth         tags++;
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth         tag = FT_CURVE_TAG( tags[0] );
138*37da2899SCharles.Forsyth         switch ( tag )
139*37da2899SCharles.Forsyth         {
140*37da2899SCharles.Forsyth         case FT_CURVE_TAG_ON:  /* emit a single line_to */
141*37da2899SCharles.Forsyth           {
142*37da2899SCharles.Forsyth             FT_Vector  vec;
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth             vec.x = SCALED( point->x );
146*37da2899SCharles.Forsyth             vec.y = SCALED( point->y );
147*37da2899SCharles.Forsyth 
148*37da2899SCharles.Forsyth             error = func_interface->line_to( &vec, user );
149*37da2899SCharles.Forsyth             if ( error )
150*37da2899SCharles.Forsyth               goto Exit;
151*37da2899SCharles.Forsyth             continue;
152*37da2899SCharles.Forsyth           }
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth         case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
155*37da2899SCharles.Forsyth           v_control.x = SCALED( point->x );
156*37da2899SCharles.Forsyth           v_control.y = SCALED( point->y );
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth         Do_Conic:
159*37da2899SCharles.Forsyth           if ( point < limit )
160*37da2899SCharles.Forsyth           {
161*37da2899SCharles.Forsyth             FT_Vector  vec;
162*37da2899SCharles.Forsyth             FT_Vector  v_middle;
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth             point++;
166*37da2899SCharles.Forsyth             tags++;
167*37da2899SCharles.Forsyth             tag = FT_CURVE_TAG( tags[0] );
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth             vec.x = SCALED( point->x );
170*37da2899SCharles.Forsyth             vec.y = SCALED( point->y );
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth             if ( tag == FT_CURVE_TAG_ON )
173*37da2899SCharles.Forsyth             {
174*37da2899SCharles.Forsyth               error = func_interface->conic_to( &v_control, &vec, user );
175*37da2899SCharles.Forsyth               if ( error )
176*37da2899SCharles.Forsyth                 goto Exit;
177*37da2899SCharles.Forsyth               continue;
178*37da2899SCharles.Forsyth             }
179*37da2899SCharles.Forsyth 
180*37da2899SCharles.Forsyth             if ( tag != FT_CURVE_TAG_CONIC )
181*37da2899SCharles.Forsyth               goto Invalid_Outline;
182*37da2899SCharles.Forsyth 
183*37da2899SCharles.Forsyth             v_middle.x = ( v_control.x + vec.x ) / 2;
184*37da2899SCharles.Forsyth             v_middle.y = ( v_control.y + vec.y ) / 2;
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth             error = func_interface->conic_to( &v_control, &v_middle, user );
187*37da2899SCharles.Forsyth             if ( error )
188*37da2899SCharles.Forsyth               goto Exit;
189*37da2899SCharles.Forsyth 
190*37da2899SCharles.Forsyth             v_control = vec;
191*37da2899SCharles.Forsyth             goto Do_Conic;
192*37da2899SCharles.Forsyth           }
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth           error = func_interface->conic_to( &v_control, &v_start, user );
195*37da2899SCharles.Forsyth           goto Close;
196*37da2899SCharles.Forsyth 
197*37da2899SCharles.Forsyth         default:  /* FT_CURVE_TAG_CUBIC */
198*37da2899SCharles.Forsyth           {
199*37da2899SCharles.Forsyth             FT_Vector  vec1, vec2;
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth             if ( point + 1 > limit                             ||
203*37da2899SCharles.Forsyth                  FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
204*37da2899SCharles.Forsyth               goto Invalid_Outline;
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth             point += 2;
207*37da2899SCharles.Forsyth             tags  += 2;
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth             vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
210*37da2899SCharles.Forsyth             vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
211*37da2899SCharles.Forsyth 
212*37da2899SCharles.Forsyth             if ( point <= limit )
213*37da2899SCharles.Forsyth             {
214*37da2899SCharles.Forsyth               FT_Vector  vec;
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth               vec.x = SCALED( point->x );
218*37da2899SCharles.Forsyth               vec.y = SCALED( point->y );
219*37da2899SCharles.Forsyth 
220*37da2899SCharles.Forsyth               error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
221*37da2899SCharles.Forsyth               if ( error )
222*37da2899SCharles.Forsyth                 goto Exit;
223*37da2899SCharles.Forsyth               continue;
224*37da2899SCharles.Forsyth             }
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth             error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
227*37da2899SCharles.Forsyth             goto Close;
228*37da2899SCharles.Forsyth           }
229*37da2899SCharles.Forsyth         }
230*37da2899SCharles.Forsyth       }
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth       /* close the contour with a line segment */
233*37da2899SCharles.Forsyth       error = func_interface->line_to( &v_start, user );
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth     Close:
236*37da2899SCharles.Forsyth       if ( error )
237*37da2899SCharles.Forsyth         goto Exit;
238*37da2899SCharles.Forsyth 
239*37da2899SCharles.Forsyth       first = last + 1;
240*37da2899SCharles.Forsyth     }
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth     return 0;
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth   Exit:
245*37da2899SCharles.Forsyth     return error;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth   Invalid_Outline:
248*37da2899SCharles.Forsyth     return FT_Err_Invalid_Outline;
249*37da2899SCharles.Forsyth   }
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth 
252*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_New_Internal(FT_Memory memory,FT_UInt numPoints,FT_Int numContours,FT_Outline * anoutline)253*37da2899SCharles.Forsyth   FT_Outline_New_Internal( FT_Memory    memory,
254*37da2899SCharles.Forsyth                            FT_UInt      numPoints,
255*37da2899SCharles.Forsyth                            FT_Int       numContours,
256*37da2899SCharles.Forsyth                            FT_Outline  *anoutline )
257*37da2899SCharles.Forsyth   {
258*37da2899SCharles.Forsyth     FT_Error  error;
259*37da2899SCharles.Forsyth 
260*37da2899SCharles.Forsyth 
261*37da2899SCharles.Forsyth     if ( !anoutline || !memory )
262*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth     *anoutline = null_outline;
265*37da2899SCharles.Forsyth 
266*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( anoutline->points,   numPoints * 2L ) ||
267*37da2899SCharles.Forsyth          FT_NEW_ARRAY( anoutline->tags,     numPoints      ) ||
268*37da2899SCharles.Forsyth          FT_NEW_ARRAY( anoutline->contours, numContours    ) )
269*37da2899SCharles.Forsyth       goto Fail;
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth     anoutline->n_points    = (FT_UShort)numPoints;
272*37da2899SCharles.Forsyth     anoutline->n_contours  = (FT_Short)numContours;
273*37da2899SCharles.Forsyth     anoutline->flags      |= FT_OUTLINE_OWNER;
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth     return FT_Err_Ok;
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth   Fail:
278*37da2899SCharles.Forsyth     anoutline->flags |= FT_OUTLINE_OWNER;
279*37da2899SCharles.Forsyth     FT_Outline_Done_Internal( memory, anoutline );
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth     return error;
282*37da2899SCharles.Forsyth   }
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth 
285*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_New(FT_Library library,FT_UInt numPoints,FT_Int numContours,FT_Outline * anoutline)288*37da2899SCharles.Forsyth   FT_Outline_New( FT_Library   library,
289*37da2899SCharles.Forsyth                   FT_UInt      numPoints,
290*37da2899SCharles.Forsyth                   FT_Int       numContours,
291*37da2899SCharles.Forsyth                   FT_Outline  *anoutline )
292*37da2899SCharles.Forsyth   {
293*37da2899SCharles.Forsyth     if ( !library )
294*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth     return FT_Outline_New_Internal( library->memory, numPoints,
297*37da2899SCharles.Forsyth                                     numContours, anoutline );
298*37da2899SCharles.Forsyth   }
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
302*37da2899SCharles.Forsyth 
303*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Check(FT_Outline * outline)304*37da2899SCharles.Forsyth   FT_Outline_Check( FT_Outline*  outline )
305*37da2899SCharles.Forsyth   {
306*37da2899SCharles.Forsyth     if ( outline )
307*37da2899SCharles.Forsyth     {
308*37da2899SCharles.Forsyth       FT_Int  n_points   = outline->n_points;
309*37da2899SCharles.Forsyth       FT_Int  n_contours = outline->n_contours;
310*37da2899SCharles.Forsyth       FT_Int  end0, end;
311*37da2899SCharles.Forsyth       FT_Int  n;
312*37da2899SCharles.Forsyth 
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth       /* empty glyph? */
315*37da2899SCharles.Forsyth       if ( n_points == 0 && n_contours == 0 )
316*37da2899SCharles.Forsyth         return 0;
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth       /* check point and contour counts */
319*37da2899SCharles.Forsyth       if ( n_points <= 0 || n_contours <= 0 )
320*37da2899SCharles.Forsyth         goto Bad;
321*37da2899SCharles.Forsyth 
322*37da2899SCharles.Forsyth       end0 = end = -1;
323*37da2899SCharles.Forsyth       for ( n = 0; n < n_contours; n++ )
324*37da2899SCharles.Forsyth       {
325*37da2899SCharles.Forsyth         end = outline->contours[n];
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth         /* note that we don't accept empty contours */
328*37da2899SCharles.Forsyth         if ( end <= end0 || end >= n_points )
329*37da2899SCharles.Forsyth           goto Bad;
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth         end0 = end;
332*37da2899SCharles.Forsyth       }
333*37da2899SCharles.Forsyth 
334*37da2899SCharles.Forsyth       if ( end != n_points - 1 )
335*37da2899SCharles.Forsyth         goto Bad;
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth       /* XXX: check the tags array */
338*37da2899SCharles.Forsyth       return 0;
339*37da2899SCharles.Forsyth     }
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth   Bad:
342*37da2899SCharles.Forsyth     return FT_Err_Invalid_Argument;
343*37da2899SCharles.Forsyth   }
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Copy(FT_Outline * source,FT_Outline * target)349*37da2899SCharles.Forsyth   FT_Outline_Copy( FT_Outline*  source,
350*37da2899SCharles.Forsyth                    FT_Outline  *target )
351*37da2899SCharles.Forsyth   {
352*37da2899SCharles.Forsyth     FT_Int  is_owner;
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth     if ( !source            || !target            ||
356*37da2899SCharles.Forsyth          source->n_points   != target->n_points   ||
357*37da2899SCharles.Forsyth          source->n_contours != target->n_contours )
358*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
359*37da2899SCharles.Forsyth 
360*37da2899SCharles.Forsyth     FT_MEM_COPY( target->points, source->points,
361*37da2899SCharles.Forsyth                  source->n_points * sizeof ( FT_Vector ) );
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth     FT_MEM_COPY( target->tags, source->tags,
364*37da2899SCharles.Forsyth                  source->n_points * sizeof ( FT_Byte ) );
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth     FT_MEM_COPY( target->contours, source->contours,
367*37da2899SCharles.Forsyth                  source->n_contours * sizeof ( FT_Short ) );
368*37da2899SCharles.Forsyth 
369*37da2899SCharles.Forsyth     /* copy all flags, except the `FT_OUTLINE_OWNER' one */
370*37da2899SCharles.Forsyth     is_owner      = target->flags & FT_OUTLINE_OWNER;
371*37da2899SCharles.Forsyth     target->flags = source->flags;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth     target->flags &= ~FT_OUTLINE_OWNER;
374*37da2899SCharles.Forsyth     target->flags |= is_owner;
375*37da2899SCharles.Forsyth 
376*37da2899SCharles.Forsyth     return FT_Err_Ok;
377*37da2899SCharles.Forsyth   }
378*37da2899SCharles.Forsyth 
379*37da2899SCharles.Forsyth 
380*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Done_Internal(FT_Memory memory,FT_Outline * outline)381*37da2899SCharles.Forsyth   FT_Outline_Done_Internal( FT_Memory    memory,
382*37da2899SCharles.Forsyth                             FT_Outline*  outline )
383*37da2899SCharles.Forsyth   {
384*37da2899SCharles.Forsyth     if ( outline )
385*37da2899SCharles.Forsyth     {
386*37da2899SCharles.Forsyth       if ( outline->flags & FT_OUTLINE_OWNER )
387*37da2899SCharles.Forsyth       {
388*37da2899SCharles.Forsyth         FT_FREE( outline->points   );
389*37da2899SCharles.Forsyth         FT_FREE( outline->tags     );
390*37da2899SCharles.Forsyth         FT_FREE( outline->contours );
391*37da2899SCharles.Forsyth       }
392*37da2899SCharles.Forsyth       *outline = null_outline;
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth       return FT_Err_Ok;
395*37da2899SCharles.Forsyth     }
396*37da2899SCharles.Forsyth     else
397*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
398*37da2899SCharles.Forsyth   }
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Done(FT_Library library,FT_Outline * outline)404*37da2899SCharles.Forsyth   FT_Outline_Done( FT_Library   library,
405*37da2899SCharles.Forsyth                    FT_Outline*  outline )
406*37da2899SCharles.Forsyth   {
407*37da2899SCharles.Forsyth     /* check for valid `outline' in FT_Outline_Done_Internal() */
408*37da2899SCharles.Forsyth 
409*37da2899SCharles.Forsyth     if ( !library )
410*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth     return FT_Outline_Done_Internal( library->memory, outline );
413*37da2899SCharles.Forsyth   }
414*37da2899SCharles.Forsyth 
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
417*37da2899SCharles.Forsyth 
418*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Outline_Get_CBox(FT_Outline * outline,FT_BBox * acbox)419*37da2899SCharles.Forsyth   FT_Outline_Get_CBox( FT_Outline*  outline,
420*37da2899SCharles.Forsyth                        FT_BBox     *acbox )
421*37da2899SCharles.Forsyth   {
422*37da2899SCharles.Forsyth     FT_Pos  xMin, yMin, xMax, yMax;
423*37da2899SCharles.Forsyth 
424*37da2899SCharles.Forsyth 
425*37da2899SCharles.Forsyth     if ( outline && acbox )
426*37da2899SCharles.Forsyth     {
427*37da2899SCharles.Forsyth       if ( outline->n_points == 0 )
428*37da2899SCharles.Forsyth       {
429*37da2899SCharles.Forsyth         xMin = 0;
430*37da2899SCharles.Forsyth         yMin = 0;
431*37da2899SCharles.Forsyth         xMax = 0;
432*37da2899SCharles.Forsyth         yMax = 0;
433*37da2899SCharles.Forsyth       }
434*37da2899SCharles.Forsyth       else
435*37da2899SCharles.Forsyth       {
436*37da2899SCharles.Forsyth         FT_Vector*  vec   = outline->points;
437*37da2899SCharles.Forsyth         FT_Vector*  limit = vec + outline->n_points;
438*37da2899SCharles.Forsyth 
439*37da2899SCharles.Forsyth 
440*37da2899SCharles.Forsyth         xMin = xMax = vec->x;
441*37da2899SCharles.Forsyth         yMin = yMax = vec->y;
442*37da2899SCharles.Forsyth         vec++;
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth         for ( ; vec < limit; vec++ )
445*37da2899SCharles.Forsyth         {
446*37da2899SCharles.Forsyth           FT_Pos  x, y;
447*37da2899SCharles.Forsyth 
448*37da2899SCharles.Forsyth 
449*37da2899SCharles.Forsyth           x = vec->x;
450*37da2899SCharles.Forsyth           if ( x < xMin ) xMin = x;
451*37da2899SCharles.Forsyth           if ( x > xMax ) xMax = x;
452*37da2899SCharles.Forsyth 
453*37da2899SCharles.Forsyth           y = vec->y;
454*37da2899SCharles.Forsyth           if ( y < yMin ) yMin = y;
455*37da2899SCharles.Forsyth           if ( y > yMax ) yMax = y;
456*37da2899SCharles.Forsyth         }
457*37da2899SCharles.Forsyth       }
458*37da2899SCharles.Forsyth       acbox->xMin = xMin;
459*37da2899SCharles.Forsyth       acbox->xMax = xMax;
460*37da2899SCharles.Forsyth       acbox->yMin = yMin;
461*37da2899SCharles.Forsyth       acbox->yMax = yMax;
462*37da2899SCharles.Forsyth     }
463*37da2899SCharles.Forsyth   }
464*37da2899SCharles.Forsyth 
465*37da2899SCharles.Forsyth 
466*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
467*37da2899SCharles.Forsyth 
468*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Outline_Translate(FT_Outline * outline,FT_Pos xOffset,FT_Pos yOffset)469*37da2899SCharles.Forsyth   FT_Outline_Translate( FT_Outline*  outline,
470*37da2899SCharles.Forsyth                         FT_Pos       xOffset,
471*37da2899SCharles.Forsyth                         FT_Pos       yOffset )
472*37da2899SCharles.Forsyth   {
473*37da2899SCharles.Forsyth     FT_UShort   n;
474*37da2899SCharles.Forsyth     FT_Vector*  vec = outline->points;
475*37da2899SCharles.Forsyth 
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth     for ( n = 0; n < outline->n_points; n++ )
478*37da2899SCharles.Forsyth     {
479*37da2899SCharles.Forsyth       vec->x += xOffset;
480*37da2899SCharles.Forsyth       vec->y += yOffset;
481*37da2899SCharles.Forsyth       vec++;
482*37da2899SCharles.Forsyth     }
483*37da2899SCharles.Forsyth   }
484*37da2899SCharles.Forsyth 
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Outline_Reverse(FT_Outline * outline)489*37da2899SCharles.Forsyth   FT_Outline_Reverse( FT_Outline*  outline )
490*37da2899SCharles.Forsyth   {
491*37da2899SCharles.Forsyth     FT_UShort  n;
492*37da2899SCharles.Forsyth     FT_Int     first, last;
493*37da2899SCharles.Forsyth 
494*37da2899SCharles.Forsyth 
495*37da2899SCharles.Forsyth     first = 0;
496*37da2899SCharles.Forsyth 
497*37da2899SCharles.Forsyth     for ( n = 0; n < outline->n_contours; n++ )
498*37da2899SCharles.Forsyth     {
499*37da2899SCharles.Forsyth       last  = outline->contours[n];
500*37da2899SCharles.Forsyth 
501*37da2899SCharles.Forsyth       /* reverse point table */
502*37da2899SCharles.Forsyth       {
503*37da2899SCharles.Forsyth         FT_Vector*  p = outline->points + first;
504*37da2899SCharles.Forsyth         FT_Vector*  q = outline->points + last;
505*37da2899SCharles.Forsyth         FT_Vector   swap;
506*37da2899SCharles.Forsyth 
507*37da2899SCharles.Forsyth 
508*37da2899SCharles.Forsyth         while ( p < q )
509*37da2899SCharles.Forsyth         {
510*37da2899SCharles.Forsyth           swap = *p;
511*37da2899SCharles.Forsyth           *p   = *q;
512*37da2899SCharles.Forsyth           *q   = swap;
513*37da2899SCharles.Forsyth           p++;
514*37da2899SCharles.Forsyth           q--;
515*37da2899SCharles.Forsyth         }
516*37da2899SCharles.Forsyth       }
517*37da2899SCharles.Forsyth 
518*37da2899SCharles.Forsyth       /* reverse tags table */
519*37da2899SCharles.Forsyth       {
520*37da2899SCharles.Forsyth         char*  p = outline->tags + first;
521*37da2899SCharles.Forsyth         char*  q = outline->tags + last;
522*37da2899SCharles.Forsyth         char   swap;
523*37da2899SCharles.Forsyth 
524*37da2899SCharles.Forsyth 
525*37da2899SCharles.Forsyth         while ( p < q )
526*37da2899SCharles.Forsyth         {
527*37da2899SCharles.Forsyth           swap = *p;
528*37da2899SCharles.Forsyth           *p   = *q;
529*37da2899SCharles.Forsyth           *q   = swap;
530*37da2899SCharles.Forsyth           p++;
531*37da2899SCharles.Forsyth           q--;
532*37da2899SCharles.Forsyth         }
533*37da2899SCharles.Forsyth       }
534*37da2899SCharles.Forsyth 
535*37da2899SCharles.Forsyth       first = last + 1;
536*37da2899SCharles.Forsyth     }
537*37da2899SCharles.Forsyth 
538*37da2899SCharles.Forsyth     outline->flags ^= FT_OUTLINE_REVERSE_FILL;
539*37da2899SCharles.Forsyth   }
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
543*37da2899SCharles.Forsyth 
544*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Render(FT_Library library,FT_Outline * outline,FT_Raster_Params * params)545*37da2899SCharles.Forsyth   FT_Outline_Render( FT_Library         library,
546*37da2899SCharles.Forsyth                      FT_Outline*        outline,
547*37da2899SCharles.Forsyth                      FT_Raster_Params*  params )
548*37da2899SCharles.Forsyth   {
549*37da2899SCharles.Forsyth     FT_Error     error;
550*37da2899SCharles.Forsyth     FT_Bool      update = 0;
551*37da2899SCharles.Forsyth     FT_Renderer  renderer;
552*37da2899SCharles.Forsyth     FT_ListNode  node;
553*37da2899SCharles.Forsyth 
554*37da2899SCharles.Forsyth 
555*37da2899SCharles.Forsyth     if ( !library )
556*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
557*37da2899SCharles.Forsyth 
558*37da2899SCharles.Forsyth     if ( !params )
559*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
560*37da2899SCharles.Forsyth 
561*37da2899SCharles.Forsyth     renderer = library->cur_renderer;
562*37da2899SCharles.Forsyth     node     = library->renderers.head;
563*37da2899SCharles.Forsyth 
564*37da2899SCharles.Forsyth     params->source = (void*)outline;
565*37da2899SCharles.Forsyth 
566*37da2899SCharles.Forsyth     error = FT_Err_Cannot_Render_Glyph;
567*37da2899SCharles.Forsyth     while ( renderer )
568*37da2899SCharles.Forsyth     {
569*37da2899SCharles.Forsyth       error = renderer->raster_render( renderer->raster, params );
570*37da2899SCharles.Forsyth       if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
571*37da2899SCharles.Forsyth         break;
572*37da2899SCharles.Forsyth 
573*37da2899SCharles.Forsyth       /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
574*37da2899SCharles.Forsyth       /* is unsupported by the current renderer for this glyph image */
575*37da2899SCharles.Forsyth       /* format                                                      */
576*37da2899SCharles.Forsyth 
577*37da2899SCharles.Forsyth       /* now, look for another renderer that supports the same */
578*37da2899SCharles.Forsyth       /* format                                                */
579*37da2899SCharles.Forsyth       renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
580*37da2899SCharles.Forsyth                                      &node );
581*37da2899SCharles.Forsyth       update   = 1;
582*37da2899SCharles.Forsyth     }
583*37da2899SCharles.Forsyth 
584*37da2899SCharles.Forsyth     /* if we changed the current renderer for the glyph image format */
585*37da2899SCharles.Forsyth     /* we need to select it as the next current one                  */
586*37da2899SCharles.Forsyth     if ( !error && update && renderer )
587*37da2899SCharles.Forsyth       FT_Set_Renderer( library, renderer, 0, 0 );
588*37da2899SCharles.Forsyth 
589*37da2899SCharles.Forsyth     return error;
590*37da2899SCharles.Forsyth   }
591*37da2899SCharles.Forsyth 
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
594*37da2899SCharles.Forsyth 
595*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Outline_Get_Bitmap(FT_Library library,FT_Outline * outline,FT_Bitmap * abitmap)596*37da2899SCharles.Forsyth   FT_Outline_Get_Bitmap( FT_Library   library,
597*37da2899SCharles.Forsyth                          FT_Outline*  outline,
598*37da2899SCharles.Forsyth                          FT_Bitmap   *abitmap )
599*37da2899SCharles.Forsyth   {
600*37da2899SCharles.Forsyth     FT_Raster_Params  params;
601*37da2899SCharles.Forsyth 
602*37da2899SCharles.Forsyth 
603*37da2899SCharles.Forsyth     if ( !abitmap )
604*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
605*37da2899SCharles.Forsyth 
606*37da2899SCharles.Forsyth     /* other checks are delayed to FT_Outline_Render() */
607*37da2899SCharles.Forsyth 
608*37da2899SCharles.Forsyth     params.target = abitmap;
609*37da2899SCharles.Forsyth     params.flags  = 0;
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth     if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY  ||
612*37da2899SCharles.Forsyth          abitmap->pixel_mode == FT_PIXEL_MODE_LCD   ||
613*37da2899SCharles.Forsyth          abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
614*37da2899SCharles.Forsyth       params.flags |= FT_RASTER_FLAG_AA;
615*37da2899SCharles.Forsyth 
616*37da2899SCharles.Forsyth     return FT_Outline_Render( library, outline, &params );
617*37da2899SCharles.Forsyth   }
618*37da2899SCharles.Forsyth 
619*37da2899SCharles.Forsyth 
620*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
621*37da2899SCharles.Forsyth 
622*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Vector_Transform(FT_Vector * vector,FT_Matrix * matrix)623*37da2899SCharles.Forsyth   FT_Vector_Transform( FT_Vector*  vector,
624*37da2899SCharles.Forsyth                        FT_Matrix*  matrix )
625*37da2899SCharles.Forsyth   {
626*37da2899SCharles.Forsyth     FT_Pos xz, yz;
627*37da2899SCharles.Forsyth 
628*37da2899SCharles.Forsyth 
629*37da2899SCharles.Forsyth     if ( !vector || !matrix )
630*37da2899SCharles.Forsyth       return;
631*37da2899SCharles.Forsyth 
632*37da2899SCharles.Forsyth     xz = FT_MulFix( vector->x, matrix->xx ) +
633*37da2899SCharles.Forsyth          FT_MulFix( vector->y, matrix->xy );
634*37da2899SCharles.Forsyth 
635*37da2899SCharles.Forsyth     yz = FT_MulFix( vector->x, matrix->yx ) +
636*37da2899SCharles.Forsyth          FT_MulFix( vector->y, matrix->yy );
637*37da2899SCharles.Forsyth 
638*37da2899SCharles.Forsyth     vector->x = xz;
639*37da2899SCharles.Forsyth     vector->y = yz;
640*37da2899SCharles.Forsyth   }
641*37da2899SCharles.Forsyth 
642*37da2899SCharles.Forsyth 
643*37da2899SCharles.Forsyth   /* documentation is in ftoutln.h */
644*37da2899SCharles.Forsyth 
645*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Outline_Transform(FT_Outline * outline,FT_Matrix * matrix)646*37da2899SCharles.Forsyth   FT_Outline_Transform( FT_Outline*  outline,
647*37da2899SCharles.Forsyth                         FT_Matrix*   matrix )
648*37da2899SCharles.Forsyth   {
649*37da2899SCharles.Forsyth     FT_Vector*  vec = outline->points;
650*37da2899SCharles.Forsyth     FT_Vector*  limit = vec + outline->n_points;
651*37da2899SCharles.Forsyth 
652*37da2899SCharles.Forsyth 
653*37da2899SCharles.Forsyth     for ( ; vec < limit; vec++ )
654*37da2899SCharles.Forsyth       FT_Vector_Transform( vec, matrix );
655*37da2899SCharles.Forsyth   }
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth 
658*37da2899SCharles.Forsyth /* END */
659