afhints.c revision 9c745321260bb728ab1cd1c8fd5f075854b2ad49
1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  afhints.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    Auto-fitter hinting routines (body).                                 */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
79c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  Copyright 2003-2007, 2009-2014 by                                      */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afhints.h"
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h"
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_CALC_H
22727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_INTERNAL_DEBUG_H
23727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
24727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
25727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*************************************************************************/
26727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*                                                                       */
27727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
28727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
29727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* messages during execution.                                            */
30727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*                                                                       */
31727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#undef  FT_COMPONENT
32727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_COMPONENT  trace_afhints
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
35aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Get new segment for given axis. */
36aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_axis_hints_new_segment( AF_AxisHints  axis,
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_Memory     memory,
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             AF_Segment   *asegment )
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
42727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error    error   = FT_Err_Ok;
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment  segment = NULL;
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( axis->num_segments >= axis->max_segments )
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  old_max = axis->max_segments;
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  new_max = old_max;
50295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( old_max >= big_max )
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
55727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Out_Of_Memory );
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      new_max += ( new_max >> 2 ) + 4;
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( new_max < old_max || new_max > big_max )
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        new_max = big_max;
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->max_segments = new_max;
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment = axis->segments + axis->num_segments++;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *asegment = segment;
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
77aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Get new edge for given axis, direction, and position. */
78aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL( FT_Error )
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_axis_hints_new_edge( AF_AxisHints  axis,
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Int        fpos,
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          AF_Direction  dir,
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Memory     memory,
84727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                          AF_Edge      *anedge )
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
86727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error  error = FT_Err_Ok;
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge   edge  = NULL;
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge   edges;
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( axis->num_edges >= axis->max_edges )
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  old_max = axis->max_edges;
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  new_max = old_max;
95295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( old_max >= big_max )
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
100727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Out_Of_Memory );
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      new_max += ( new_max >> 2 ) + 4;
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( new_max < old_max || new_max > big_max )
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        new_max = big_max;
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->max_edges = new_max;
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edges = axis->edges;
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge  = edges + axis->num_edges;
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( edge > edges )
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge[-1].fpos < fpos )
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we want the edge with same position and minor direction */
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* to appear before those in the major one in the list     */
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge[-1].fpos == fpos && dir == axis->major_dir )
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge[0] = edge[-1];
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge--;
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges++;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ZERO( edge );
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge->fpos = (FT_Short)fpos;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge->dir  = (FT_Char)dir;
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
138727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    *anedge = edge;
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
143aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef FT_DEBUG_AUTOFIT
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1450a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include FT_CONFIG_STANDARD_LIBRARY_H
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
147ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* The dump functions are used in the `ftgrid' demo program, too. */
148ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#define AF_DUMP( varformat )          \
149ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          do                          \
150ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {                           \
151ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            if ( to_stdout )          \
152ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              printf varformat;       \
153ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            else                      \
154ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              FT_TRACE7( varformat ); \
155ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          } while ( 0 )
156ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
157ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const char*
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_dir_str( AF_Direction  dir )
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    const char*  result;
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( dir )
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_UP:
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "up";
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_DOWN:
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "down";
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_LEFT:
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "left";
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_RIGHT:
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "right";
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "none";
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
189aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
190aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
191aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
193ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_points( AF_GlyphHints  hints,
194ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                              FT_Bool        to_stdout )
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points = hints->points;
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  limit  = points + hints->num_points;
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  point;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
201ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    AF_DUMP(( "Table of points:\n"
202ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              "  [ index |  xorg |  yorg | xscale | yscale"
203ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              " |  xfit |  yfit |  flags ]\n" ));
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( point = points; point < limit; point++ )
206ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
207ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
208ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point - points,
209ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->fx,
210ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->fy,
211ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->ox / 64.0,
212ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->oy / 64.0,
213ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->x / 64.0,
214ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->y / 64.0,
215ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
216ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
217ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
218ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                ( point->flags & AF_FLAG_EXTREMA_Y )          ? 'v' : ' ',
219ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                ( point->flags & AF_FLAG_ROUND_X )            ? '(' : ' ',
220ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                ( point->flags & AF_FLAG_ROUND_Y )            ? 'u' : ' '));
221ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    AF_DUMP(( "\n" ));
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
223aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
224aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
225aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const char*
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_edge_flags_to_string( AF_Edge_Flags  flags )
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static char  temp[32];
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int          pos = 0;
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( flags & AF_EDGE_ROUND )
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( temp + pos, "round", 5 );
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pos += 5;
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( flags & AF_EDGE_SERIF )
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( pos > 0 )
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        temp[pos++] = ' ';
2440a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( temp + pos, "serif", 5 );
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pos += 5;
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( pos == 0 )
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return "normal";
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
250727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    temp[pos] = '\0';
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return temp;
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
256aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Dump the array of linked segments. */
257aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
258aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
259aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
260aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
262ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_segments( AF_GlyphHints  hints,
263ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                FT_Bool        to_stdout )
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  dimension;
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dimension = 1; dimension >= 0; dimension-- )
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_AxisHints  axis     = &hints->axis[dimension];
271727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_Point      points   = hints->points;
272727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_Edge       edges    = axis->edges;
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    segments = axis->segments;
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    limit    = segments + axis->num_segments;
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    seg;
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
278ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "Table of %s segments:\n",
279ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                dimension == AF_DIMENSION_HORZ ? "vertical"
280ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                               : "horizontal" ));
281727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( axis->num_segments )
282ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ index |  pos  |  dir  | from"
283ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " |  to  | link | serif | edge"
284ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | height | extra |    flags    ]\n" ));
285727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
286ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  (none)\n" ));
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < limit; seg++ )
289ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ %5d | %5.2g | %5s | %4d"
290ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | %4d | %4d | %5d | %4d"
291ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | %6d | %5d | %11s ]\n",
292ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg - segments,
293ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  dimension == AF_DIMENSION_HORZ
294ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                               ? (int)seg->first->ox / 64.0
295ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                               : (int)seg->first->oy / 64.0,
296ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_dir_str( (AF_Direction)seg->dir ),
297ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->first, points ),
298ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->last, points ),
299ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->link, segments ),
300ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->serif, segments ),
301ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->edge, edges ),
302ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg->height,
303ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg->height - ( seg->max_coord - seg->min_coord ),
304ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) ));
305ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "\n" ));
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
308aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
309aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
310aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
311aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
312aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
313aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Fetch number of segments. */
314aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
315aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
316aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
317aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
318aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  FT_Error
319aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
320aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   FT_Int         dimension,
321aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   FT_Int*        num_segments )
322aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  {
323aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Dimension  dim;
324aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_AxisHints  axis;
325aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
326aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
327aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
328aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
329aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    axis          = &hints->axis[dim];
330aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    *num_segments = axis->num_segments;
331aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
332727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
333aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
334aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
335aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
336aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
337aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
338aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
339aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Fetch offset of segments into user supplied offset array. */
340aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
341aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
342aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
343aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
344aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  FT_Error
345aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
346aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                     FT_Int         dimension,
347aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                     FT_Int         idx,
3489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Pos        *offset,
3499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Bool       *is_blue,
3509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Pos        *blue_offset )
351aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  {
352aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Dimension  dim;
353aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_AxisHints  axis;
354aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Segment    seg;
355aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
356aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
357aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    if ( !offset )
358727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
359aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
360aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
361aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
362aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    axis = &hints->axis[dim];
363aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
364aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    if ( idx < 0 || idx >= axis->num_segments )
365727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
366aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
3679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    seg      = &axis->segments[idx];
3689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    *offset  = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
3699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                            : seg->first->oy;
3709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( seg->edge )
3719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
3729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
3739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *is_blue = FALSE;
3749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( *is_blue )
3769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *blue_offset = seg->edge->blue_edge->cur;
3779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
3789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *blue_offset = 0;
379aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
380727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
381aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
382aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
383aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
384aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
385aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
387aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Dump the array of linked edges. */
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
389aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
390aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
391aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
393ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_edges( AF_GlyphHints  hints,
394ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                             FT_Bool        to_stdout )
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  dimension;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dimension = 1; dimension >= 0; dimension-- )
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_AxisHints  axis  = &hints->axis[dimension];
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       edges = axis->edges;
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       limit = edges + axis->num_edges;
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       edge;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
409aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner       *        since they have a constant X coordinate.
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
411ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "Table of %s edges:\n",
412ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                dimension == AF_DIMENSION_HORZ ? "vertical"
413ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                               : "horizontal" ));
414727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( axis->num_edges )
415ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ index |  pos  |  dir  | link"
416ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | serif | blue | opos  |  pos  |    flags    ]\n" ));
417727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
418ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  (none)\n" ));
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < limit; edge++ )
421ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ %5d | %5.2g | %5s | %4d"
422ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
423ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge - edges,
424ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  (int)edge->opos / 64.0,
425ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_dir_str( (AF_Direction)edge->dir ),
426ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( edge->link, edges ),
427ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( edge->serif, edges ),
428ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->blue_edge ? 'y' : 'n',
429ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->opos / 64.0,
430ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->pos / 64.0,
431ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) ));
432ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "\n" ));
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
435aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
436aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
437aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
439ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#undef AF_DUMP
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
441aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* !FT_DEBUG_AUTOFIT */
442aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
443aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
444aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Compute the direction value of a given vector. */
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( AF_Direction )
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_direction_compute( FT_Pos  dx,
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Pos  dy )
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        ll, ss;  /* long and short arm lengths */
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  dir;     /* candidate direction        */
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dy >= dx )
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy >= -dx )
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_UP;
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dy;
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dx;
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_LEFT;
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = -dx;
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dy;
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else /* dy < dx */
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy >= -dx )
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_RIGHT;
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dx;
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dy;
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_DOWN;
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dy;
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dx;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
485727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* return no direction if arm lengths differ too much            */
486727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ss *= 14;
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_ABS( ll ) <= FT_ABS( ss ) )
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dir = AF_DIR_NONE;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dir;
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_init( AF_GlyphHints  hints,
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Memory      memory )
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ZERO( hints );
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->memory = memory;
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_done( AF_GlyphHints  hints )
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
507727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Memory  memory = hints->memory;
508727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int        dim;
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
511727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( !( hints && hints->memory ) )
512727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /*
515727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     *  note that we don't need to free the segment and edge
516727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     *  buffers since they are really within the hints->points array
517727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     */
518727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
519727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
520727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_AxisHints  axis = &hints->axis[dim];
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
523727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->num_segments = 0;
524727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->max_segments = 0;
525727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_FREE( axis->segments );
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
527727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->num_edges = 0;
528727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->max_edges = 0;
529727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_FREE( axis->edges );
530727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_FREE( hints->contours );
533727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->max_contours = 0;
534727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->num_contours = 0;
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_FREE( hints->points );
537727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->num_points = 0;
538727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->max_points = 0;
539727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
540727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->memory = NULL;
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Reset metrics. */
545aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
5479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_glyph_hints_rescale( AF_GlyphHints    hints,
5489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                          AF_StyleMetrics  metrics )
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->metrics      = metrics;
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = metrics->scaler.flags;
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
555aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Recompute all AF_Point in AF_GlyphHints from the definitions */
556aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* in a source outline.                                         */
557aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_reload( AF_GlyphHints  hints,
560aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                         FT_Outline*    outline )
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
562727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error   = FT_Err_Ok;
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   points;
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    old_max, new_max;
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   x_scale = hints->x_scale;
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   y_scale = hints->y_scale;
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos     x_delta = hints->x_delta;
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos     y_delta = hints->y_delta;
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory  = hints->memory;
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_points   = 0;
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_contours = 0;
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[0].num_segments = 0;
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[0].num_edges    = 0;
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[1].num_segments = 0;
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[1].num_edges    = 0;
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
580aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* first of all, reallocate the contours array if necessary */
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_max = (FT_UInt)outline->n_contours;
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    old_max = hints->max_contours;
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( new_max > old_max )
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
585aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->max_contours = new_max;
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  then reallocate the points arrays if necessary --
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  note that we reserve two additional point positions, used to
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  hint metrics appropriately
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_max = (FT_UInt)( outline->n_points + 2 );
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    old_max = hints->max_points;
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( new_max > old_max )
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
602aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->max_points = new_max;
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_points   = outline->n_points;
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_contours = outline->n_contours;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We can't rely on the value of `FT_Outline.flags' to know the fill   */
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* direction used for a glyph, given that some fonts are broken (e.g., */
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the Arphic ones).  We thus recompute it each time we need to.       */
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = x_scale;
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = y_scale;
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = x_delta;
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = y_delta;
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->xmin_delta = 0;
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->xmax_delta = 0;
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    points = hints->points;
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( hints->num_points == 0 )
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point;
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point_limit = points + hints->num_points;
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute coordinates & Bezier flags, next and prev */
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  vec           = outline->points;
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char*       tag           = outline->tags;
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point    end           = points + outline->contours[0];
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point    prev          = end;
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int      contour_index = 0;
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( point = points; point < point_limit; point++, vec++, tag++ )
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
6549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point->in_dir  = (FT_Char)AF_DIR_NONE;
6559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point->out_dir = (FT_Char)AF_DIR_NONE;
6569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->fx = (FT_Short)vec->x;
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->fy = (FT_Short)vec->y;
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          switch ( FT_CURVE_TAG( *tag ) )
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case FT_CURVE_TAG_CONIC:
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags = AF_FLAG_CONIC;
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case FT_CURVE_TAG_CUBIC:
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags = AF_FLAG_CUBIC;
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          default:
671aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            point->flags = AF_FLAG_NONE;
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->prev = prev;
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev->next  = point;
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev        = point;
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == end )
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ++contour_index < outline->n_contours )
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
682aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich              end  = points + outline->contours[contour_index];
683aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich              prev = end;
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
689aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* set up the contours array */
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point*  contour       = hints->contours;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point*  contour_limit = contour + hints->num_contours;
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        short*     end           = outline->contours;
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        short      idx           = 0;
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; contour < contour_limit; contour++, end++ )
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          contour[0] = points + idx;
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          idx        = (short)( end[0] + 1 );
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
7059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
7069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Compute directions of `in' and `out' vectors.
7079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *
7089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Note that distances between points that are very near to each
7099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  other are accumulated.  In other words, the auto-hinter
7109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  prepends the small vectors between near points to the first
7119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  non-near vector.  All intermediate points are tagged as
7129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  weak; the directions are adjusted also to be equal to the
7139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  accumulated one.
7149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
7159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /* value 20 in `near_limit' is heuristic */
717ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
718ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        FT_Int   near_limit   = 20 * units_per_em / 2048;
7199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_Int   near_limit2  = 2 * near_limit - 1;
720ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        AF_Point*  contour;
7229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        AF_Point*  contour_limit = hints->contours + hints->num_contours;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
7249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( contour = hints->contours; contour < contour_limit; contour++ )
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
7279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          AF_Point  first = *contour;
7289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          AF_Point  next, prev, curr;
7299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          FT_Pos  out_x, out_y;
7319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          FT_Bool  is_first;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
7359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* since the first point of a contour could be part of a */
7369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* series of near points, go backwards to find the first */
7379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* non-near point and adjust `first'                     */
7389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point = first;
7409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          prev  = first->prev;
7419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          while ( prev != first )
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
7449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = point->fx - prev->fx;
7459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = point->fy - prev->fy;
7469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /*
7489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  We use Taxicab metrics to measure the vector length.
7499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *
7509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  Note that the accumulated distances so far could have the
7519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  opposite direction of the distance measured here.  For this
7529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  reason we use `near_limit2' for the comparison to get a
7539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  non-near point even in the worst case.
7549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             */
7559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
7569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              break;
7579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            point = prev;
7599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            prev  = prev->prev;
7609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
761ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* adjust first point */
7639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          first = point;
764ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* now loop over all points of the contour to get */
7669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* `in' and `out' vector directions               */
767ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          curr  = first;
769ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /*
7719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  We abuse the `u' and `v' fields to store index deltas to the
7729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  next and previous non-near point, respectively.
7739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *
7749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  To avoid problems with not having non-near points, we point to
7759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  `first' by default as the next non-near point.
7769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *
7779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           */
7789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          curr->u  = (FT_Pos)( first - curr );
7799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          first->v = -curr->u;
780ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          out_x = 0;
7829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          out_y = 0;
783ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          is_first = 1;
785ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          for ( point = first;
7879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                point != first || is_first;
7889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                point = point->next )
7899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          {
7909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Direction  out_dir;
791ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
792ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            is_first = 0;
794ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next = point->next;
796ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x += next->fx - point->fx;
7989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y += next->fy - point->fy;
7999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
8019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
8029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              next->flags |= AF_FLAG_WEAK_INTERPOLATION;
8039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              continue;
804ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
805ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->u = (FT_Pos)( next - curr );
8079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next->v = -curr->u;
8089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_dir = af_direction_compute( out_x, out_y );
8109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* adjust directions for all points inbetween; */
8129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* the loop also updates position of `curr'    */
8139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->out_dir = (FT_Char)out_dir;
8149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            for ( curr = curr->next; curr != next; curr = curr->next )
8159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
8169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              curr->in_dir  = (FT_Char)out_dir;
8179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              curr->out_dir = (FT_Char)out_dir;
8189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
8199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next->in_dir = (FT_Char)out_dir;
8209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->u  = (FT_Pos)( first - curr );
8229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            first->v = -curr->u;
8239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = 0;
8259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = 0;
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
8279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
8309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  The next step is to `simplify' an outline's topology so that we
8319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  can identify local extrema more reliably: A series of
8329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  non-horizontal or non-vertical vectors pointing into the same
8339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  quadrant are handled as a single, long vector.  From a
8349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  topological point of the view, the intermediate points are of no
8359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  interest and thus tagged as weak.
8369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( point = points; point < point_limit; point++ )
8399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
8409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
8419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            continue;
842ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->in_dir  == AF_DIR_NONE &&
8449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod               point->out_dir == AF_DIR_NONE )
845ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {
8469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* check whether both vectors point into the same quadrant */
8479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            FT_Pos  in_x, in_y;
8499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            FT_Pos  out_x, out_y;
8509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Point  next_u = point + point->u;
8529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Point  prev_v = point + point->v;
8539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
854ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            in_x = point->fx - prev_v->fx;
8569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            in_y = point->fy - prev_v->fy;
8579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = next_u->fx - point->fx;
8599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = next_u->fy - point->fy;
8609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 )
8629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
8639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              /* yes, so tag current point as weak */
8649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              /* and update index deltas           */
8659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              point->flags |= AF_FLAG_WEAK_INTERPOLATION;
8679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              prev_v->u = (FT_Pos)( next_u - prev_v );
8699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              next_u->v = -prev_v->u;
8709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
8719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
8729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
8759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Finally, check for remaining weak points.  Everything else not
8769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  collected in edges so far is then implicitly classified as strong
8779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  points.
8789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( point = points; point < point_limit; point++ )
8819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
8829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
8839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            continue;
884aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
885727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( point->flags & AF_FLAG_CONTROL )
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
887ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            /* control points are always weak */
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          Is_Weak_Point:
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( point->out_dir == point->in_dir )
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point->out_dir != AF_DIR_NONE )
894ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            {
895ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              /* current point lies on a horizontal or          */
896ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              /* vertical segment (but doesn't start or end it) */
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Is_Weak_Point;
898ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
900ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            {
9019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              AF_Point  next_u = point + point->u;
9029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              AF_Point  prev_v = point + point->v;
9039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              if ( ft_corner_is_flat( point->fx  - prev_v->fx,
9069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      point->fy  - prev_v->fy,
9079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      next_u->fx - point->fx,
9089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      next_u->fy - point->fy ) )
9099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              {
9109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* either the `in' or the `out' vector is much more  */
9119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* dominant than the other one, so tag current point */
9129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* as weak and update index deltas                   */
9139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                prev_v->u = (FT_Pos)( next_u - prev_v );
9159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                next_u->v = -prev_v->u;
9169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                goto Is_Weak_Point;
9189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              }
919ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( point->in_dir == -point->out_dir )
922ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {
923ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            /* current point forms a spike */
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Is_Weak_Point;
925ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          }
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
935aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Store the hinted outline in an FT_Outline structure. */
936aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_save( AF_GlyphHints  hints,
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Outline*    outline )
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point    point = hints->points;
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point    limit = point + hints->num_points;
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec   = outline->points;
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tag   = outline->tags;
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; point < limit; point++, vec++, tag++ )
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->x = point->x;
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->y = point->y;
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point->flags & AF_FLAG_CONIC )
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_CONIC;
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( point->flags & AF_FLAG_CUBIC )
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_CUBIC;
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_ON;
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                     EDGE POINT GRID-FITTING
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
969aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Align all points of an edge to the same coordinate value, */
970aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* either horizontally or vertically.                        */
971aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    AF_Dimension   dim )
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = & hints->axis[dim];
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < segment_limit; seg++ )
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge = seg->edge;
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  point, first, last;
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge == NULL )
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = seg->first;
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last  = seg->last;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = first;
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->x      = edge->pos;
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= AF_FLAG_TOUCH_X;
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < segment_limit; seg++ )
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge = seg->edge;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  point, first, last;
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge == NULL )
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = seg->first;
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last  = seg->last;
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = first;
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->y      = edge->pos;
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= AF_FLAG_TOUCH_Y;
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                    STRONG POINT INTERPOLATION
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1044aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Hint the strong points -- this is equivalent to the TrueType `IP' */
1045aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* hinting instruction.                                              */
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      AF_Dimension   dim )
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point      points      = hints->points;
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point      point_limit = points + hints->num_points;
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis        = &hints->axis[dim];
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges       = axis->edges;
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit  = edges + axis->num_edges;
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Flags      touch_flag;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_X;
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag  = AF_FLAG_TOUCH_Y;
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( edges < edge_limit )
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point;
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge   edge;
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  u, ou, fu;  /* point position */
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & touch_flag )
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if this point is candidate to weak interpolation, we       */
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* interpolate it after all strong points have been processed */
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             !( point->flags & AF_FLAG_INFLECTION )         )
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dim == AF_DIMENSION_VERT )
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u  = point->fy;
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ou = point->oy;
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u  = point->fx;
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ou = point->ox;
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fu = u;
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* is the point before the first edge? */
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge  = edges;
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = edge->fpos - u;
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta >= 0 )
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = edge->pos - ( edge->opos - ou );
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Store_Point;
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* is the point after the last edge? */
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge  = edge_limit - 1;
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = u - edge->fpos;
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta >= 0 )
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = edge->pos + ( ou - edge->opos );
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Store_Point;
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1118295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_PtrDist  min, max, mid;
1119aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          FT_Pos      fpos;
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* find enclosing edges */
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min = 0;
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max = edge_limit - edges;
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
1127aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* for a small number of edges, a linear search is better */
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( max <= 8 )
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1130295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            FT_PtrDist  nn;
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1132aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( nn = 0; nn < max; nn++ )
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edges[nn].fpos >= u )
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                break;
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edges[nn].fpos == u )
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              u = edges[nn].pos;
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Store_Point;
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min = nn;
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          while ( min < max )
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid  = ( max + min ) >> 1;
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge = edges + mid;
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            fpos = edge->fpos;
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( u < fpos )
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = mid;
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else if ( u > fpos )
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = mid + 1;
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* we are on the edge */
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              u = edge->pos;
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Store_Point;
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* point is not on an edge */
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge  before = edges + min - 1;
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge  after  = edges + min + 0;
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* assert( before && after && before != after ) */
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->scale == 0 )
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              before->scale = FT_DivFix( after->pos - before->pos,
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         after->fpos - before->fpos );
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            u = before->pos + FT_MulFix( fu - before->fpos,
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         before->scale );
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      Store_Point:
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* save the point position */
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dim == AF_DIMENSION_HORZ )
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->x = u;
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->y = u;
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->flags |= touch_flag;
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                    WEAK POINT INTERPOLATION
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1200aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Shift the original coordinates of all points between `p1' and */
1201aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* `p2' to get hinted coordinates, using the same difference as  */
1202aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* given by `ref'.                                               */
1203aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_iup_shift( AF_Point  p1,
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                AF_Point  p2,
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                AF_Point  ref )
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  p;
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    delta = ref->u - ref->v;
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1212aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( delta == 0 )
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( p = p1; p < ref; p++ )
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p->u = p->v + delta;
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( p = ref + 1; p <= p2; p++ )
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p->u = p->v + delta;
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1224aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Interpolate the original coordinates of all points between `p1' and  */
1225aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the       */
1226aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* reference points.  The `u' and `v' members are the current and       */
1227aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* original coordinate values, respectively.                            */
1228aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                      */
1229aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Details can be found in the TrueType bytecode specification.         */
1230aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_iup_interp( AF_Point  p1,
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  p2,
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  ref1,
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  ref2 )
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  p;
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    u;
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    v1 = ref1->v;
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    v2 = ref2->v;
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    d1 = ref1->u - v1;
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    d2 = ref2->u - v2;
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p1 > p2 )
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( v1 == v2 )
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( u <= v1 )
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d2;
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( v1 < v2 )
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( u <= v1 )
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( u >= v2 )
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d2;
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( u <= v2 )
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d2;
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( u >= v1 )
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1299aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
1300aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* hinting instruction.                                             */
1301aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    AF_Dimension   dim )
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   points        = hints->points;
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   point_limit   = points + hints->num_points;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*  contour       = hints->contours;
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*  contour_limit = contour + hints->num_contours;
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Flags   touch_flag;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   point;
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   end_point;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   first_point;
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* PASS 1: Move segment points to edge positions */
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_X;
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->x;
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->ox;
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_Y;
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->y;
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->oy;
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  first_touched, last_touched;
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point       = *contour;
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end_point   = point->prev;
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_point = point;
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* find first touched point */
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point > end_point )  /* no touched point in contour */
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NextContour;
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & touch_flag )
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_touched = point;
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1364aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_ASSERT( point <= end_point                 &&
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   ( point->flags & touch_flag ) != 0 );
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1367aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* skip any touched neighbours */
1368aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        while ( point < end_point                    &&
1369aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                ( point[1].flags & touch_flag ) != 0 )
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point++;
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_touched = point;
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* find the next touched point, if any */
1375aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        point++;
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point > end_point )
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto EndContour;
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( point->flags & touch_flag ) != 0 )
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point++;
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* interpolate between last_touched and point */
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_iup_interp( last_touched + 1, point - 1,
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       last_touched, point );
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    EndContour:
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* special case: only one point was touched */
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( last_touched == first_touched )
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_iup_shift( first_point, end_point, first_touched );
1396aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else /* interpolate the last part */
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( last_touched < end_point )
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_iup_interp( last_touched + 1, end_point,
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         last_touched, first_touched );
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_touched > points )
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_iup_interp( first_point, first_touched - 1,
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         last_touched, first_touched );
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NextContour:
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now save the interpolated values back to x/y */
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->x = point->u;
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->y = point->u;
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1426aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
1427aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1428aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Apply (small) warp scale and warp delta for given dimension. */
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            AF_Dimension   dim,
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Fixed       scale,
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Pos         delta )
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points       = hints->points;
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points_limit = points + hints->num_points;
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  point;
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < points_limit; point++ )
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->x = FT_MulFix( point->fx, scale ) + delta;
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < points_limit; point++ )
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->y = FT_MulFix( point->fy, scale ) + delta;
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1453aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* AF_CONFIG_OPTION_USE_WARPER */
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
1456