1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ftoutln.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    FreeType outline management (body).                                  */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 1996-2008, 2010, 2012-2013 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  /*************************************************************************/
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* All functions are declared in freetype.h.                             */
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_OUTLINE_H
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
29a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_INTERNAL_CALC_H
300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include FT_INTERNAL_DEBUG_H
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRIGONOMETRY_H
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_outline
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Decompose( FT_Outline*              outline,
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        const FT_Outline_Funcs*  func_interface,
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        void*                    user )
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef SCALED
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define SCALED( x )  ( ( (x) << shift ) - delta )
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_last;
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_control;
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_start;
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  point;
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit;
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tags;
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int   n;         /* index of contour in outline     */
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  first;     /* index of first point in contour */
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int   tag;       /* current point's state           */
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int   shift;
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos   delta;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline || !func_interface )
77a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    shift = func_interface->shift;
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta = func_interface->delta;
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = 0;
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < outline->n_contours; n++ )
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  last;  /* index of last point in contour */
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
880a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
890a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last = outline->contours[n];
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( last < 0 )
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Invalid_Outline;
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      limit = outline->points + last;
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
950a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_start   = outline->points[first];
960a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_start.x = SCALED( v_start.x );
970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_start.y = SCALED( v_start.y );
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
990a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last   = outline->points[last];
1000a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last.x = SCALED( v_last.x );
1010a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last.y = SCALED( v_last.y );
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_control = v_start;
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point = outline->points + first;
1060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      tags  = outline->tags   + first;
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag   = FT_CURVE_TAG( tags[0] );
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A contour cannot start with a cubic control point! */
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CUBIC )
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Invalid_Outline;
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check first point to determine origin */
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CONIC )
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* first point is conic control.  Yes, this happens. */
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at last point if it is on the curve */
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start = v_last;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          limit--;
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if both first and last points are conic,         */
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at their middle and record its position    */
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for closure                                      */
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.x = ( v_start.x + v_last.x ) / 2;
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.y = ( v_start.y + v_last.y ) / 2;
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_last = v_start;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point--;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags--;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "  move to (%.2f, %.2f)\n",
1380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                  v_start.x / 64.0, v_start.y / 64.0 ));
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = func_interface->move_to( &v_start, user );
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( point < limit )
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags++;
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag = FT_CURVE_TAG( tags[0] );
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        switch ( tag )
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_ON:  /* emit a single line_to */
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec;
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.x = SCALED( point->x );
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.y = SCALED( point->y );
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1590a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  line to (%.2f, %.2f)\n",
1600a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec.x / 64.0, vec.y / 64.0 ));
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->line_to( &vec, user );
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( error )
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_control.x = SCALED( point->x );
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_control.y = SCALED( point->y );
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        Do_Conic:
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point < limit )
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec;
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  v_middle;
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point++;
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tags++;
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tag = FT_CURVE_TAG( tags[0] );
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.x = SCALED( point->x );
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.y = SCALED( point->y );
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( tag == FT_CURVE_TAG_ON )
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1870a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              FT_TRACE5(( "  conic to (%.2f, %.2f)"
1880a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          " with control (%.2f, %.2f)\n",
1890a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec.x / 64.0, vec.y / 64.0,
1900a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          v_control.x / 64.0, v_control.y / 64.0 ));
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = func_interface->conic_to( &v_control, &vec, user );
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              continue;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( tag != FT_CURVE_TAG_CONIC )
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Invalid_Outline;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v_middle.x = ( v_control.x + vec.x ) / 2;
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v_middle.y = ( v_control.y + vec.y ) / 2;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  conic to (%.2f, %.2f)"
2040a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        " with control (%.2f, %.2f)\n",
2050a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_middle.x / 64.0, v_middle.y / 64.0,
2060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_control.x / 64.0, v_control.y / 64.0 ));
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->conic_to( &v_control, &v_middle, user );
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( error )
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v_control = vec;
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Do_Conic;
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE5(( "  conic to (%.2f, %.2f)"
2160a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      " with control (%.2f, %.2f)\n",
2170a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      v_start.x / 64.0, v_start.y / 64.0,
2180a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      v_control.x / 64.0, v_control.y / 64.0 ));
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error = func_interface->conic_to( &v_control, &v_start, user );
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Close;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        default:  /* FT_CURVE_TAG_CUBIC */
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec1, vec2;
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point + 1 > limit                             ||
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Invalid_Outline;
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point += 2;
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tags  += 2;
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2340a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec1.x = SCALED( point[-2].x );
2350a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec1.y = SCALED( point[-2].y );
2360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
2370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec2.x = SCALED( point[-1].x );
2380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec2.y = SCALED( point[-1].y );
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point <= limit )
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Vector  vec;
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec.x = SCALED( point->x );
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec.y = SCALED( point->y );
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              FT_TRACE5(( "  cubic to (%.2f, %.2f)"
2490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
2500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec.x / 64.0, vec.y / 64.0,
2510a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec1.x / 64.0, vec1.y / 64.0,
2520a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec2.x / 64.0, vec2.y / 64.0 ));
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              continue;
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2590a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  cubic to (%.2f, %.2f)"
2600a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
2610a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_start.x / 64.0, v_start.y / 64.0,
2620a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec1.x / 64.0, vec1.y / 64.0,
2630a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec2.x / 64.0, vec2.y / 64.0 ));
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Close;
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* close the contour with a line segment */
2710a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "  line to (%.2f, %.2f)\n",
2720a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                  v_start.x / 64.0, v_start.y / 64.0 ));
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = func_interface->line_to( &v_start, user );
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Close:
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = last + 1;
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2820a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
2830a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    return FT_Err_Ok;
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2860a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Invalid_Outline:
290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_THROW( Invalid_Outline );
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_New_Internal( FT_Memory    memory,
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_UInt      numPoints,
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Int       numContours,
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Outline  *anoutline )
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !anoutline || !memory )
304a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *anoutline = null_outline;
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
308a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( numContours < 0                  ||
309a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         (FT_UInt)numContours > numPoints )
310a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
311a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( numPoints > FT_OUTLINE_POINTS_MAX )
313a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Array_Too_Large );
314a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
315295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( FT_NEW_ARRAY( anoutline->points,   numPoints   ) ||
316aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich         FT_NEW_ARRAY( anoutline->tags,     numPoints   ) ||
317aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich         FT_NEW_ARRAY( anoutline->contours, numContours ) )
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    anoutline->n_points    = (FT_UShort)numPoints;
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    anoutline->n_contours  = (FT_Short)numContours;
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    anoutline->flags      |= FT_OUTLINE_OWNER;
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Err_Ok;
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    anoutline->flags |= FT_OUTLINE_OWNER;
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Outline_Done_Internal( memory, anoutline );
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_New( FT_Library   library,
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_UInt      numPoints,
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Int       numContours,
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Outline  *anoutline )
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !library )
343a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Library_Handle );
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Outline_New_Internal( library->memory, numPoints,
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    numContours, anoutline );
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Check( FT_Outline*  outline )
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline )
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  n_points   = outline->n_points;
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  n_contours = outline->n_contours;
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  end0, end;
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  n;
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* empty glyph? */
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( n_points == 0 && n_contours == 0 )
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 0;
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check point and contour counts */
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( n_points <= 0 || n_contours <= 0 )
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Bad;
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end0 = end = -1;
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < n_contours; n++ )
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end = outline->contours[n];
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* note that we don't accept empty contours */
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( end <= end0 || end >= n_points )
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Bad;
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end0 = end;
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( end != n_points - 1 )
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Bad;
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* XXX: check the tags array */
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Bad:
391a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_THROW( Invalid_Argument );
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Copy( const FT_Outline*  source,
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Outline        *target )
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  is_owner;
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !source            || !target            ||
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         source->n_points   != target->n_points   ||
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         source->n_contours != target->n_contours )
407a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( source == target )
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return FT_Err_Ok;
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ARRAY_COPY( target->points, source->points, source->n_points );
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* copy all flags, except the `FT_OUTLINE_OWNER' one */
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    is_owner      = target->flags & FT_OUTLINE_OWNER;
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    target->flags = source->flags;
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    target->flags &= ~FT_OUTLINE_OWNER;
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    target->flags |= is_owner;
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Err_Ok;
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Done_Internal( FT_Memory    memory,
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Outline*  outline )
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( memory && outline )
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( outline->flags & FT_OUTLINE_OWNER )
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( outline->points   );
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( outline->tags     );
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( outline->contours );
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *outline = null_outline;
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return FT_Err_Ok;
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
446a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Done( FT_Library   library,
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Outline*  outline )
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check for valid `outline' in FT_Outline_Done_Internal() */
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !library )
459a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Library_Handle );
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Outline_Done_Internal( library->memory, outline );
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Get_CBox( const FT_Outline*  outline,
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_BBox           *acbox )
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  xMin, yMin, xMax, yMax;
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline && acbox )
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( outline->n_points == 0 )
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        xMin = 0;
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        yMin = 0;
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        xMax = 0;
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        yMax = 0;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  vec   = outline->points;
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  limit = vec + outline->n_points;
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        xMin = xMax = vec->x;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        yMin = yMax = vec->y;
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        vec++;
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; vec < limit; vec++ )
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  x, y;
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          x = vec->x;
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( x < xMin ) xMin = x;
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( x > xMax ) xMax = x;
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          y = vec->y;
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( y < yMin ) yMin = y;
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( y > yMax ) yMax = y;
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      acbox->xMin = xMin;
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      acbox->xMax = xMax;
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      acbox->yMin = yMin;
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      acbox->yMax = yMax;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Translate( const FT_Outline*  outline,
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Pos             xOffset,
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Pos             yOffset )
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort   n;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline )
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec = outline->points;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < outline->n_points; n++ )
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->x += xOffset;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->y += yOffset;
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec++;
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Reverse( FT_Outline*  outline )
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  n;
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     first, last;
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline )
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = 0;
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < outline->n_contours; n++ )
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last  = outline->contours[n];
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* reverse point table */
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  p = outline->points + first;
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  q = outline->points + last;
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector   swap;
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( p < q )
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          swap = *p;
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *p   = *q;
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *q   = swap;
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p++;
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          q--;
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* reverse tags table */
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char*  p = outline->tags + first;
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char*  q = outline->tags + last;
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char   swap;
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( p < q )
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          swap = *p;
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *p   = *q;
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *q   = swap;
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p++;
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          q--;
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = last + 1;
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    outline->flags ^= FT_OUTLINE_REVERSE_FILL;
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Render( FT_Library         library,
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Outline*        outline,
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Raster_Params*  params )
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error     error;
6070a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_Bool      update = FALSE;
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Renderer  renderer;
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ListNode  node;
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !library )
613a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Library_Handle );
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline || !params )
616a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    renderer = library->cur_renderer;
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    node     = library->renderers.head;
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    params->source = (void*)outline;
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
623a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_ERR( Cannot_Render_Glyph );
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( renderer )
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = renderer->raster_render( renderer->raster, params );
627a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* is unsupported by the current renderer for this glyph image */
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* format                                                      */
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now, look for another renderer that supports the same */
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* format                                                */
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     &node );
6380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      update   = TRUE;
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if we changed the current renderer for the glyph image format */
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we need to select it as the next current one                  */
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error && update && renderer )
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Set_Renderer( library, renderer, 0, 0 );
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Get_Bitmap( FT_Library        library,
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Outline*       outline,
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         const FT_Bitmap  *abitmap )
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Raster_Params  params;
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !abitmap )
661a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* other checks are delayed to FT_Outline_Render() */
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    params.target = abitmap;
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    params.flags  = 0;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY  ||
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         abitmap->pixel_mode == FT_PIXEL_MODE_LCD   ||
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      params.flags |= FT_RASTER_FLAG_AA;
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Outline_Render( library, outline, &params );
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in freetype.h */
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Vector_Transform( FT_Vector*        vector,
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       const FT_Matrix*  matrix )
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  xz, yz;
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !vector || !matrix )
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    xz = FT_MulFix( vector->x, matrix->xx ) +
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_MulFix( vector->y, matrix->xy );
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    yz = FT_MulFix( vector->x, matrix->yx ) +
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_MulFix( vector->y, matrix->yy );
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vector->x = xz;
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vector->y = yz;
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Transform( const FT_Outline*  outline,
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        const FT_Matrix*   matrix )
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec;
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit;
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline || !matrix )
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec   = outline->points;
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    limit = vec + outline->n_points;
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; vec < limit; vec++ )
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector_Transform( vec, matrix );
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last )  \
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  do {                                                     \
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (first) = ( c > 0 ) ? (outline)->points +              \
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            (outline)->contours[c - 1] + 1 \
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        : (outline)->points;               \
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (last) = (outline)->points + (outline)->contours[c];   \
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } while ( 0 )
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Is a point in some contour?                     */
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                 */
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* We treat every point of the contour as if it    */
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* it were ON.  That is, we allow false positives, */
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* but disallow false negatives.  (XXX really?)    */
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Bool
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_contour_has( FT_Outline*  outline,
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Short     c,
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Vector*   point )
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  first;
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  last;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  a;
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  b;
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     n = 0;
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( a = first; a <= last; a++ )
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  x;
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  intersect;
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      b = ( a == last ) ? first : a + 1;
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      intersect = ( a->y - point->y ) ^ ( b->y - point->y );
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* a and b are on the same side */
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( intersect >= 0 )
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( intersect == 0 && a->y == point->y )
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( a->x <= point->x && b->x >= point->x ) ||
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               ( a->x >= point->x && b->x <= point->x ) )
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            return 1;
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( x < point->x )
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        n++;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( x == point->x )
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 1;
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
782e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    return n & 1;
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Bool
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_contour_enclosed( FT_Outline*  outline,
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UShort    c )
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  first;
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  last;
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Short    i;
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < outline->n_contours; i++ )
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( i != c && ft_contour_has( outline, i, first ) )
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  pt;
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( pt = first + 1; pt <= last; pt++ )
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( !ft_contour_has( outline, i, pt ) )
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            return 0;
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 1;
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This version differs from the public one in that each */
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* part (contour not enclosed in another contour) of the */
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* outline is checked for orientation.  This is          */
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* necessary for some buggy CJK fonts.                   */
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Orientation
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_outline_get_orientation( FT_Outline*  outline )
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Short        i;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*      first;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*      last;
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Orientation  orient = FT_ORIENTATION_NONE;
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = outline->points;
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < outline->n_contours; i++, first = last + 1 )
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector*  point;
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector*  xmin_point;
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos      xmin;
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last = outline->points + outline->contours[i];
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip degenerate contours */
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( last < first + 2 )
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ft_contour_enclosed( outline, i ) )
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      xmin       = first->x;
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      xmin_point = first;
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = first + 1; point <= last; point++ )
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->x < xmin )
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          xmin       = point->x;
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          xmin_point = point;
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check the orientation of the contour */
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*      prev;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*      next;
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Orientation  o;
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        prev = ( xmin_point == first ) ? last : xmin_point - 1;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next = ( xmin_point == last ) ? first : xmin_point + 1;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          o = FT_ORIENTATION_POSTSCRIPT;
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          o = FT_ORIENTATION_TRUETYPE;
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( orient == FT_ORIENTATION_NONE )
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          orient = o;
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( orient != o )
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return FT_ORIENTATION_NONE;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return orient;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Embolden( FT_Outline*  outline,
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Pos       strength )
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
893a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Outline_EmboldenXY( outline, strength, strength );
894a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
895a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
896a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
897a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* documentation is in ftoutln.h */
898a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
899a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_EXPORT_DEF( FT_Error )
900a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_Outline_EmboldenXY( FT_Outline*  outline,
901a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         FT_Pos       xstrength,
902a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         FT_Pos       ystrength )
903a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  points;
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_prev, v_first, v_next, v_cur;
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      c, n, first;
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      orientation;
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline )
911a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
913a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    xstrength /= 2;
914a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    ystrength /= 2;
915a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( xstrength == 0 && ystrength == 0 )
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return FT_Err_Ok;
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    orientation = FT_Outline_Get_Orientation( outline );
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( orientation == FT_ORIENTATION_NONE )
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( outline->n_contours )
922a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        return FT_THROW( Invalid_Argument );
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return FT_Err_Ok;
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    points = outline->points;
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = 0;
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( c = 0; c < outline->n_contours; c++ )
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
932a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Vector  in, out, shift;
933a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Fixed   l_in, l_out, l, q, d;
934a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      int        last = outline->contours[c];
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_first = points[first];
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_prev  = points[last];
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_cur   = v_first;
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
941a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* compute incoming normalized vector */
942a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      in.x = v_cur.x - v_prev.x;
943a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      in.y = v_cur.y - v_prev.y;
944a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      l_in = FT_Vector_Length( &in );
945a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( l_in )
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
947a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        in.x = FT_DivFix( in.x, l_in );
948a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        in.y = FT_DivFix( in.y, l_in );
949a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
951a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      for ( n = first; n <= last; n++ )
952a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n < last )
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_next = points[n + 1];
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_next = v_first;
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
958a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* compute outgoing normalized vector */
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        out.x = v_next.x - v_cur.x;
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        out.y = v_next.y - v_cur.y;
961a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        l_out = FT_Vector_Length( &out );
962a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( l_out )
963a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
964a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          out.x = FT_DivFix( out.x, l_out );
965a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          out.y = FT_DivFix( out.y, l_out );
966a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
968a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
970a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* shift only if turn is less than ~160 degrees */
971a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( d > -0xF000L )
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
973a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          d = d + 0x10000L;
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
975a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* shift components are aligned along lateral bisector */
976a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* and directed according to the outline orientation.  */
977a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          shift.x = in.y + out.y;
978a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          shift.y = in.x + out.x;
979a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
980a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( orientation == FT_ORIENTATION_TRUETYPE )
981a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            shift.x = -shift.x;
982a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          else
983a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            shift.y = -shift.y;
984a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
985a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* restrict shift magnitude to better handle collapsing segments */
986a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
987a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( orientation == FT_ORIENTATION_TRUETYPE )
988a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            q = -q;
989a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
990a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          l = FT_MIN( l_in, l_out );
991a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
992a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
993a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) )
994a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            shift.x = FT_MulDiv( shift.x, xstrength, d );
995a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          else
996a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            shift.x = FT_MulDiv( shift.x, l, q );
997a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
998a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
999a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) )
1000a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            shift.y = FT_MulDiv( shift.y, ystrength, d );
1001a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          else
1002a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            shift.y = FT_MulDiv( shift.y, l, q );
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1004a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        else
1005a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          shift.x = shift.y = 0;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1007a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        outline->points[n].x = v_cur.x + xstrength + shift.x;
1008a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        outline->points[n].y = v_cur.y + ystrength + shift.y;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1010a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        in    = out;
1011a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        l_in  = l_out;
1012a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        v_cur = v_next;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = last + 1;
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Err_Ok;
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in ftoutln.h */
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Orientation )
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Outline_Get_Orientation( FT_Outline*  outline )
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1027a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_BBox     cbox;
1028a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Int      xshift, yshift;
1029a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Vector*  points;
1030a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Vector   v_prev, v_cur;
1031a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Int      c, n, first;
1032a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Pos      area = 0;
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline || outline->n_points <= 0 )
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return FT_ORIENTATION_TRUETYPE;
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We use the nonzero winding rule to find the orientation.       */
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Since glyph outlines behave much more `regular' than arbitrary */
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* cubic or quadratic curves, this test deals with the polygon    */
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* only which is spanned up by the control points.                */
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1043a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Outline_Get_CBox( outline, &cbox );
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1045a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
1046a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    xshift = FT_MAX( xshift, 0 );
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1048a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14;
1049a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    yshift = FT_MAX( yshift, 0 );
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1051a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    points = outline->points;
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1053a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    first = 0;
1054a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( c = 0; c < outline->n_contours; c++ )
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1056a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Int  last = outline->contours[c];
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1059a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      v_prev = points[last];
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1061a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      for ( n = first; n <= last; n++ )
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1063a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        v_cur = points[n];
1064a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
1065a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                ( ( v_cur.x + v_prev.x ) >> xshift );
1066a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        v_prev = v_cur;
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1069a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      first = last + 1;
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1072a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( area > 0 )
1073a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_ORIENTATION_POSTSCRIPT;
1074a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    else if ( area < 0 )
1075a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_ORIENTATION_TRUETYPE;
1076a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    else
1077a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_ORIENTATION_NONE;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
1082