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/*                                                                         */
7a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin/*  Copyright 2003-2017 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
46fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
47fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
48a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !axis->segments )
49fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
50fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        axis->segments     = axis->embedded.segments;
51fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        axis->max_segments = AF_SEGMENTS_EMBEDDED;
52fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
53fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
54fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( axis->num_segments >= axis->max_segments )
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  old_max = axis->max_segments;
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  new_max = old_max;
58295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( old_max >= big_max )
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
63727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Out_Of_Memory );
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      new_max += ( new_max >> 2 ) + 4;
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( new_max < old_max || new_max > big_max )
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        new_max = big_max;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
71fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->segments == axis->embedded.segments )
72fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
73fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( FT_NEW_ARRAY( axis->segments, new_max ) )
74fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          goto Exit;
75fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ft_memcpy( axis->segments, axis->embedded.segments,
76fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                   sizeof ( axis->embedded.segments ) );
77fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
78fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      else
79fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
80fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
81fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          goto Exit;
82fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->max_segments = new_max;
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment = axis->segments + axis->num_segments++;
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *asegment = segment;
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
95fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* Get new edge for given axis, direction, and position, */
96fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* without initializing the edge itself.                 */
97aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL( FT_Error )
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_axis_hints_new_edge( AF_AxisHints  axis,
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Int        fpos,
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          AF_Direction  dir,
102055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                          FT_Bool       top_to_bottom_hinting,
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Memory     memory,
104727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                          AF_Edge      *anedge )
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
106727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error  error = FT_Err_Ok;
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge   edge  = NULL;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge   edges;
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
111fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( axis->num_edges < AF_EDGES_EMBEDDED )
112fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
113a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !axis->edges )
114fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
115fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        axis->edges     = axis->embedded.edges;
116fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        axis->max_edges = AF_EDGES_EMBEDDED;
117fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
118fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
119fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( axis->num_edges >= axis->max_edges )
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  old_max = axis->max_edges;
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  new_max = old_max;
123295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( old_max >= big_max )
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
128727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Out_Of_Memory );
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      new_max += ( new_max >> 2 ) + 4;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( new_max < old_max || new_max > big_max )
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        new_max = big_max;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
136fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->edges == axis->embedded.edges )
137fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
138fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( FT_NEW_ARRAY( axis->edges, new_max ) )
139fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          goto Exit;
140fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ft_memcpy( axis->edges, axis->embedded.edges,
141fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                   sizeof ( axis->embedded.edges ) );
142fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
143fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      else
144fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
145fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
146fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          goto Exit;
147fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->max_edges = new_max;
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edges = axis->edges;
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge  = edges + axis->num_edges;
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( edge > edges )
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
157055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( top_to_bottom_hinting ? ( edge[-1].fpos > fpos )
158055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                 : ( edge[-1].fpos < fpos ) )
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we want the edge with same position and minor direction */
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* to appear before those in the major one in the list     */
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge[-1].fpos == fpos && dir == axis->major_dir )
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge[0] = edge[-1];
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge--;
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges++;
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
173727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    *anedge = edge;
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
178aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef FT_DEBUG_AUTOFIT
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1800a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include FT_CONFIG_STANDARD_LIBRARY_H
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* The dump functions are used in the `ftgrid' demo program, too. */
183ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#define AF_DUMP( varformat )          \
184ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          do                          \
185ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {                           \
186ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            if ( to_stdout )          \
187ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              printf varformat;       \
188ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            else                      \
189ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              FT_TRACE7( varformat ); \
190ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          } while ( 0 )
191ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
192ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const char*
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_dir_str( AF_Direction  dir )
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    const char*  result;
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( dir )
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_UP:
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "up";
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_DOWN:
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "down";
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_LEFT:
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "left";
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_RIGHT:
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "right";
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "none";
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
221fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define AF_INDEX_NUM( ptr, base )  (int)( (ptr) ? ( (ptr) - (base) ) : -1 )
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
224055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  static char*
225055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  af_print_idx( char* p,
226055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                int   idx )
227055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  {
228055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( idx == -1 )
229055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
230055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      p[0] = '-';
231055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      p[1] = '-';
232055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      p[2] = '\0';
233055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
234055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    else
235055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      ft_sprintf( p, "%d", idx );
236055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
237055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    return p;
238055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  }
239055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
240055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
241055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  static int
242055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  af_get_segment_index( AF_GlyphHints  hints,
243055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        int            point_idx,
244055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        int            dimension )
245055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  {
246055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_AxisHints  axis     = &hints->axis[dimension];
247055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Point      point    = hints->points + point_idx;
248055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Segment    segments = axis->segments;
249055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Segment    limit    = segments + axis->num_segments;
250055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Segment    segment;
251055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
252055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
253055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    for ( segment = segments; segment < limit; segment++ )
254055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
255055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( segment->first <= segment->last )
256055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      {
257055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( point >= segment->first && point <= segment->last )
258055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          break;
259055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      }
260055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      else
261055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      {
262055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_Point  p = segment->first;
263055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
264055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
265055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        for (;;)
266055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
267055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( point == p )
268055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            goto Exit;
269055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
270055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( p == segment->last )
271055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            break;
272055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
273055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          p = p->next;
274055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
275055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      }
276055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
277055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
278055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  Exit:
279055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( segment == limit )
280055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return -1;
281055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
282055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    return (int)( segment - segments );
283055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  }
284055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
285055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
286055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  static int
287055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  af_get_edge_index( AF_GlyphHints  hints,
288055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                     int            segment_idx,
289055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                     int            dimension )
290055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  {
291055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_AxisHints  axis    = &hints->axis[dimension];
292055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Edge       edges   = axis->edges;
293055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Segment    segment = axis->segments + segment_idx;
294055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
295055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
296055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
297055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  }
298055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
299055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
300aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
301aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
302aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
304ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_points( AF_GlyphHints  hints,
305ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                              FT_Bool        to_stdout )
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
307055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Point   points  = hints->points;
308055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Point   limit   = points + hints->num_points;
309055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Point*  contour = hints->contours;
310055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Point*  climit  = contour + hints->num_contours;
311055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    AF_Point   point;
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
314fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    AF_DUMP(( "Table of points:\n" ));
315fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
316fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( hints->num_points )
317055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      AF_DUMP(( "  index  hedge  hseg  vedge  vseg  flags "
318055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                "  xorg  yorg  xscale  yscale   xfit    yfit" ));
319fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else
320fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      AF_DUMP(( "  (none)\n" ));
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( point = points; point < limit; point++ )
323055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
324055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      int  point_idx     = AF_INDEX_NUM( point, points );
325055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      int  segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
326055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      int  segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
327055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
328055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      char  buf1[16], buf2[16], buf3[16], buf4[16];
329055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
330055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
331055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      /* insert extra newline at the beginning of a contour */
332055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( contour < climit && *contour == point )
333055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      {
334055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "\n" ));
335055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        contour++;
336055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      }
337055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
338055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      AF_DUMP(( "  %5d  %5s %5s  %5s %5s  %s"
339055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
340055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                point_idx,
341055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                af_print_idx( buf1,
342055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                              af_get_edge_index( hints, segment_idx_1, 1 ) ),
343055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                af_print_idx( buf2, segment_idx_1 ),
344055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                af_print_idx( buf3,
345055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                              af_get_edge_index( hints, segment_idx_0, 0 ) ),
346055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                af_print_idx( buf4, segment_idx_0 ),
347055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                ( point->flags & AF_FLAG_NEAR )
348055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  ? " near "
349055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  : ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
350055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    ? " weak "
351055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    : "strong",
352055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
353ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->fx,
354ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->fy,
355ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->ox / 64.0,
356ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->oy / 64.0,
357ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->x / 64.0,
358055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                point->y / 64.0 ));
359055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
360ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    AF_DUMP(( "\n" ));
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
362aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
363aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
364aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const char*
368fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  af_edge_flags_to_string( FT_UInt  flags )
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static char  temp[32];
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int          pos = 0;
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( flags & AF_EDGE_ROUND )
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( temp + pos, "round", 5 );
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pos += 5;
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( flags & AF_EDGE_SERIF )
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( pos > 0 )
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        temp[pos++] = ' ';
3830a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( temp + pos, "serif", 5 );
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pos += 5;
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( pos == 0 )
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return "normal";
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
389727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    temp[pos] = '\0';
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return temp;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Dump the array of linked segments. */
396aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
397aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
398aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
399aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
401ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_segments( AF_GlyphHints  hints,
402ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                FT_Bool        to_stdout )
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  dimension;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dimension = 1; dimension >= 0; dimension-- )
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_AxisHints  axis     = &hints->axis[dimension];
410727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_Point      points   = hints->points;
411727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_Edge       edges    = axis->edges;
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    segments = axis->segments;
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    limit    = segments + axis->num_segments;
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    seg;
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
416055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      char  buf1[16], buf2[16], buf3[16];
417055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
419ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "Table of %s segments:\n",
420ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                dimension == AF_DIMENSION_HORZ ? "vertical"
421ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                               : "horizontal" ));
422727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( axis->num_segments )
423055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "  index   pos   delta   dir   from   to "
424055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "  link  serif  edge"
425055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "  height  extra     flags\n" ));
426727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
427ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  (none)\n" ));
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < limit; seg++ )
430055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "  %5d  %5d  %5d  %5s  %4d  %4d"
431055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "  %4s  %5s  %4s"
432055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "  %6d  %5d  %11s\n",
433fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  AF_INDEX_NUM( seg, segments ),
434055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  seg->pos,
435055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  seg->delta,
436ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_dir_str( (AF_Direction)seg->dir ),
437ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->first, points ),
438ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->last, points ),
439055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
440055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ),
441055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ),
442055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ),
443055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
444ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg->height,
445ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg->height - ( seg->max_coord - seg->min_coord ),
446fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  af_edge_flags_to_string( seg->flags ) ));
447ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "\n" ));
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
450aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
451aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
452aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
453aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
454aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
455aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Fetch number of segments. */
456aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
457aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
458aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
459aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
460aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  FT_Error
461aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
462aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   FT_Int         dimension,
463aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   FT_Int*        num_segments )
464aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  {
465aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Dimension  dim;
466aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_AxisHints  axis;
467aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
468aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
469aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
470aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
471aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    axis          = &hints->axis[dim];
472aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    *num_segments = axis->num_segments;
473aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
474727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
475aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
476aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
477aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
478aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
479aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
480aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
481aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Fetch offset of segments into user supplied offset array. */
482aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
483aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
484aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
485aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
486aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  FT_Error
487aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
488aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                     FT_Int         dimension,
489aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                     FT_Int         idx,
4909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Pos        *offset,
4919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Bool       *is_blue,
4929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Pos        *blue_offset )
493aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  {
494aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Dimension  dim;
495aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_AxisHints  axis;
496aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Segment    seg;
497aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
498aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
499aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    if ( !offset )
500727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
501aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
502aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
503aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
504aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    axis = &hints->axis[dim];
505aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
506aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    if ( idx < 0 || idx >= axis->num_segments )
507727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
508aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
5099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    seg      = &axis->segments[idx];
5109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    *offset  = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
5119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                            : seg->first->oy;
5129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( seg->edge )
5139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
5149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
5159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *is_blue = FALSE;
5169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( *is_blue )
5189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *blue_offset = seg->edge->blue_edge->cur;
5199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
5209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *blue_offset = 0;
521aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
522727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
523aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
524aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
525aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
526aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
527aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
529aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Dump the array of linked edges. */
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
531aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
532aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
533aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
535ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_edges( AF_GlyphHints  hints,
536ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                             FT_Bool        to_stdout )
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  dimension;
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dimension = 1; dimension >= 0; dimension-- )
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_AxisHints  axis  = &hints->axis[dimension];
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       edges = axis->edges;
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       limit = edges + axis->num_edges;
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       edge;
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
548055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      char  buf1[16], buf2[16];
549055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
553aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner       *        since they have a constant X coordinate.
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
555055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( dimension == AF_DIMENSION_HORZ )
556055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
557055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "vertical",
558055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  65536.0 * 64.0 / hints->x_scale,
559055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  10.0 * hints->x_scale / 65536.0 / 64.0 ));
560055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      else
561055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
562055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "horizontal",
563055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  65536.0 * 64.0 / hints->y_scale,
564055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  10.0 * hints->y_scale / 65536.0 / 64.0 ));
565055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
566727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( axis->num_edges )
567055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "  index    pos     dir   link  serif"
568055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "  blue    opos     pos       flags\n" ));
569727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
570ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  (none)\n" ));
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < limit; edge++ )
573055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_DUMP(( "  %5d  %7.2f  %5s  %4s  %5s"
574055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  "    %c   %7.2f  %7.2f  %11s\n",
575fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  AF_INDEX_NUM( edge, edges ),
576ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  (int)edge->opos / 64.0,
577ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_dir_str( (AF_Direction)edge->dir ),
578055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ),
579055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ),
580055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
581ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->blue_edge ? 'y' : 'n',
582ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->opos / 64.0,
583ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->pos / 64.0,
584fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  af_edge_flags_to_string( edge->flags ) ));
585ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "\n" ));
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
588aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
589aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
590aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
592ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#undef AF_DUMP
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
594aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* !FT_DEBUG_AUTOFIT */
595aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
596aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
597aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Compute the direction value of a given vector. */
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( AF_Direction )
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_direction_compute( FT_Pos  dx,
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Pos  dy )
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        ll, ss;  /* long and short arm lengths */
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  dir;     /* candidate direction        */
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dy >= dx )
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy >= -dx )
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_UP;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dy;
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dx;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_LEFT;
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = -dx;
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dy;
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else /* dy < dx */
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy >= -dx )
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_RIGHT;
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dx;
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dy;
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_DOWN;
633fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ll  = -dy;
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dx;
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* return no direction if arm lengths do not differ enough       */
639727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */
640fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* the long arm is never negative                                */
641fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( ll <= 14 * FT_ABS( ss ) )
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dir = AF_DIR_NONE;
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dir;
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_init( AF_GlyphHints  hints,
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Memory      memory )
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
652fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* no need to initialize the embedded items */
653fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_MEM_ZERO( hints, sizeof ( *hints ) - sizeof ( hints->embedded ) );
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->memory = memory;
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_done( AF_GlyphHints  hints )
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
661fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Memory  memory;
662727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int        dim;
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
665727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( !( hints && hints->memory ) )
666727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
668fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    memory = hints->memory;
669fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
670727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /*
671727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     *  note that we don't need to free the segment and edge
672727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     *  buffers since they are really within the hints->points array
673727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     */
674727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
675727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
676727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_AxisHints  axis = &hints->axis[dim];
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
679727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->num_segments = 0;
680727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->max_segments = 0;
681fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->segments != axis->embedded.segments )
682fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FREE( axis->segments );
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
684727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->num_edges = 0;
685727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->max_edges = 0;
686fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->edges != axis->embedded.edges )
687fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FREE( axis->edges );
688727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
690fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( hints->contours != hints->embedded.contours )
691fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_FREE( hints->contours );
692727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->max_contours = 0;
693727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->num_contours = 0;
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
695fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( hints->points != hints->embedded.points )
696fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_FREE( hints->points );
697727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->max_points = 0;
698fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    hints->num_points = 0;
699727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
700727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->memory = NULL;
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
704aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Reset metrics. */
705aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
7079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_glyph_hints_rescale( AF_GlyphHints    hints,
7089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                          AF_StyleMetrics  metrics )
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->metrics      = metrics;
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = metrics->scaler.flags;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
715aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Recompute all AF_Point in AF_GlyphHints from the definitions */
716aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* in a source outline.                                         */
717aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_reload( AF_GlyphHints  hints,
720aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                         FT_Outline*    outline )
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
722727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error   = FT_Err_Ok;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   points;
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    old_max, new_max;
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   x_scale = hints->x_scale;
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   y_scale = hints->y_scale;
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos     x_delta = hints->x_delta;
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos     y_delta = hints->y_delta;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory  = hints->memory;
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_points   = 0;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_contours = 0;
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[0].num_segments = 0;
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[0].num_edges    = 0;
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[1].num_segments = 0;
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[1].num_edges    = 0;
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
740aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* first of all, reallocate the contours array if necessary */
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_max = (FT_UInt)outline->n_contours;
742fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    old_max = (FT_UInt)hints->max_contours;
743fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
744fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( new_max <= AF_CONTOURS_EMBEDDED )
745fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
746a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !hints->contours )
747fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
748fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->contours     = hints->embedded.contours;
749fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->max_contours = AF_CONTOURS_EMBEDDED;
750fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
751fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
752fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( new_max > old_max )
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
754fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( hints->contours == hints->embedded.contours )
755fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->contours = NULL;
756fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
757fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
762fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      hints->max_contours = (FT_Int)new_max;
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  then reallocate the points arrays if necessary --
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  note that we reserve two additional point positions, used to
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  hint metrics appropriately
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_max = (FT_UInt)( outline->n_points + 2 );
771fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    old_max = (FT_UInt)hints->max_points;
772fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
773fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( new_max <= AF_POINTS_EMBEDDED )
774fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
775a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !hints->points )
776fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
777fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->points     = hints->embedded.points;
778fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->max_points = AF_POINTS_EMBEDDED;
779fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
780fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
781fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( new_max > old_max )
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
783fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( hints->points == hints->embedded.points )
784fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->points = NULL;
785fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
786fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
791fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      hints->max_points = (FT_Int)new_max;
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_points   = outline->n_points;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_contours = outline->n_contours;
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We can't rely on the value of `FT_Outline.flags' to know the fill   */
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* direction used for a glyph, given that some fonts are broken (e.g., */
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the Arphic ones).  We thus recompute it each time we need to.       */
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = x_scale;
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = y_scale;
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = x_delta;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = y_delta;
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->xmin_delta = 0;
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->xmax_delta = 0;
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    points = hints->points;
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( hints->num_points == 0 )
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point_limit = points + hints->num_points;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
826055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      /* value 20 in `near_limit' is heuristic */
827055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
828055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_Int   near_limit   = 20 * units_per_em / 2048;
829055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute coordinates & Bezier flags, next and prev */
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  vec           = outline->points;
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char*       tag           = outline->tags;
835055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        FT_Short    endpoint      = outline->contours[0];
836055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        AF_Point    end           = points + endpoint;
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point    prev          = end;
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int      contour_index = 0;
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( point = points; point < point_limit; point++, vec++, tag++ )
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
843055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Pos  out_x, out_y;
844055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
845055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
8469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point->in_dir  = (FT_Char)AF_DIR_NONE;
8479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point->out_dir = (FT_Char)AF_DIR_NONE;
8489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->fx = (FT_Short)vec->x;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->fy = (FT_Short)vec->y;
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
854055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          end->fx = (FT_Short)outline->points[endpoint].x;
855055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          end->fy = (FT_Short)outline->points[endpoint].y;
856055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          switch ( FT_CURVE_TAG( *tag ) )
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case FT_CURVE_TAG_CONIC:
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags = AF_FLAG_CONIC;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case FT_CURVE_TAG_CUBIC:
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags = AF_FLAG_CUBIC;
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          default:
866aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            point->flags = AF_FLAG_NONE;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          out_x = point->fx - prev->fx;
870055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          out_y = point->fy - prev->fy;
871055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
872055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
873055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            prev->flags |= AF_FLAG_NEAR;
874055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->prev = prev;
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev->next  = point;
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev        = point;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == end )
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ++contour_index < outline->n_contours )
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
883055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              endpoint = outline->contours[contour_index];
884055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              end      = points + endpoint;
885055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              prev     = end;
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
891aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* set up the contours array */
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point*  contour       = hints->contours;
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point*  contour_limit = contour + hints->num_contours;
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        short*     end           = outline->contours;
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        short      idx           = 0;
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; contour < contour_limit; contour++, end++ )
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          contour[0] = points + idx;
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          idx        = (short)( end[0] + 1 );
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
9079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
9089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Compute directions of `in' and `out' vectors.
9099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *
9109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Note that distances between points that are very near to each
911055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin         *  other are accumulated.  In other words, the auto-hinter either
9129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  prepends the small vectors between near points to the first
913055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin         *  non-near vector, or the sum of small vector lengths exceeds a
914055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin         *  threshold, thus `grouping' the small vectors.  All intermediate
915055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin         *  points are tagged as weak; the directions are adjusted also to
916055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin         *  be equal to the accumulated one.
9179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
9189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
919055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        FT_Int  near_limit2 = 2 * near_limit - 1;
920ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        AF_Point*  contour;
9229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        AF_Point*  contour_limit = hints->contours + hints->num_contours;
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
9249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( contour = hints->contours; contour < contour_limit; contour++ )
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
9279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          AF_Point  first = *contour;
9289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          AF_Point  next, prev, curr;
9299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          FT_Pos  out_x, out_y;
9319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
9339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* since the first point of a contour could be part of a */
9349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* series of near points, go backwards to find the first */
9359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* non-near point and adjust `first'                     */
9369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point = first;
9389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          prev  = first->prev;
9399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          while ( prev != first )
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
9429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = point->fx - prev->fx;
9439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = point->fy - prev->fy;
9449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /*
9469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  We use Taxicab metrics to measure the vector length.
9479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *
9489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  Note that the accumulated distances so far could have the
9499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  opposite direction of the distance measured here.  For this
9509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  reason we use `near_limit2' for the comparison to get a
9519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  non-near point even in the worst case.
9529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             */
9539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
9549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              break;
9559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            point = prev;
9579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            prev  = prev->prev;
9589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
959ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* adjust first point */
9619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          first = point;
962ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* now loop over all points of the contour to get */
9649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* `in' and `out' vector directions               */
965ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
966055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          curr = first;
967ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /*
9699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  We abuse the `u' and `v' fields to store index deltas to the
9709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  next and previous non-near point, respectively.
9719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *
9729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  To avoid problems with not having non-near points, we point to
9739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  `first' by default as the next non-near point.
9749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *
9759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           */
9769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          curr->u  = (FT_Pos)( first - curr );
9779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          first->v = -curr->u;
978ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          out_x = 0;
9809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          out_y = 0;
981ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
982fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          next = first;
983fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          do
9849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          {
9859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Direction  out_dir;
986ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
987ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
988fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            point = next;
989055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            next  = point->next;
990ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x += next->fx - point->fx;
9929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y += next->fy - point->fy;
9939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
9959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
9969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              next->flags |= AF_FLAG_WEAK_INTERPOLATION;
9979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              continue;
998ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
999ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
10009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->u = (FT_Pos)( next - curr );
10019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next->v = -curr->u;
10029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_dir = af_direction_compute( out_x, out_y );
10049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* adjust directions for all points inbetween; */
10069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* the loop also updates position of `curr'    */
10079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->out_dir = (FT_Char)out_dir;
10089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            for ( curr = curr->next; curr != next; curr = curr->next )
10099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
10109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              curr->in_dir  = (FT_Char)out_dir;
10119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              curr->out_dir = (FT_Char)out_dir;
10129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
10139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next->in_dir = (FT_Char)out_dir;
10149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->u  = (FT_Pos)( first - curr );
10169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            first->v = -curr->u;
10179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = 0;
10199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = 0;
1020fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1021fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          } while ( next != first );
10229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
10249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
10259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  The next step is to `simplify' an outline's topology so that we
10269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  can identify local extrema more reliably: A series of
10279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  non-horizontal or non-vertical vectors pointing into the same
10289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  quadrant are handled as a single, long vector.  From a
10299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  topological point of the view, the intermediate points are of no
10309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  interest and thus tagged as weak.
10319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
10339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( point = points; point < point_limit; point++ )
10349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
10359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
10369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            continue;
1037ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
10389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->in_dir  == AF_DIR_NONE &&
10399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod               point->out_dir == AF_DIR_NONE )
1040ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {
10419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* check whether both vectors point into the same quadrant */
10429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            FT_Pos  in_x, in_y;
10449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            FT_Pos  out_x, out_y;
10459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Point  next_u = point + point->u;
10479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Point  prev_v = point + point->v;
10489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1049ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
10509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            in_x = point->fx - prev_v->fx;
10519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            in_y = point->fy - prev_v->fy;
10529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = next_u->fx - point->fx;
10549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = next_u->fy - point->fy;
10559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 )
10579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
10589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              /* yes, so tag current point as weak */
10599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              /* and update index deltas           */
10609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              point->flags |= AF_FLAG_WEAK_INTERPOLATION;
10629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              prev_v->u = (FT_Pos)( next_u - prev_v );
10649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              next_u->v = -prev_v->u;
10659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
10669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
10679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
10699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
10709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Finally, check for remaining weak points.  Everything else not
10719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  collected in edges so far is then implicitly classified as strong
10729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  points.
10739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
10759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( point = points; point < point_limit; point++ )
10769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
10779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
10789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            continue;
1079aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1080727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( point->flags & AF_FLAG_CONTROL )
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1082ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            /* control points are always weak */
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          Is_Weak_Point:
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( point->out_dir == point->in_dir )
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point->out_dir != AF_DIR_NONE )
1089ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            {
1090ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              /* current point lies on a horizontal or          */
1091ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              /* vertical segment (but doesn't start or end it) */
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Is_Weak_Point;
1093ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1095ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            {
10969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              AF_Point  next_u = point + point->u;
10979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              AF_Point  prev_v = point + point->v;
10989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
10999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
11009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              if ( ft_corner_is_flat( point->fx  - prev_v->fx,
11019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      point->fy  - prev_v->fy,
11029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      next_u->fx - point->fx,
11039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      next_u->fy - point->fy ) )
11049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              {
11059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* either the `in' or the `out' vector is much more  */
11069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* dominant than the other one, so tag current point */
11079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* as weak and update index deltas                   */
11089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
11099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                prev_v->u = (FT_Pos)( next_u - prev_v );
11109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                next_u->v = -prev_v->u;
11119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
11129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                goto Is_Weak_Point;
11139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              }
1114ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( point->in_dir == -point->out_dir )
1117ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {
1118ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            /* current point forms a spike */
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Is_Weak_Point;
1120ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          }
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1130aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Store the hinted outline in an FT_Outline structure. */
1131aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_save( AF_GlyphHints  hints,
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Outline*    outline )
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point    point = hints->points;
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point    limit = point + hints->num_points;
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec   = outline->points;
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tag   = outline->tags;
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; point < limit; point++, vec++, tag++ )
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->x = point->x;
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->y = point->y;
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point->flags & AF_FLAG_CONIC )
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_CONIC;
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( point->flags & AF_FLAG_CUBIC )
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_CUBIC;
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_ON;
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                     EDGE POINT GRID-FITTING
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Align all points of an edge to the same coordinate value, */
1165aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* either horizontally or vertically.                        */
1166aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    AF_Dimension   dim )
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = & hints->axis[dim];
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < segment_limit; seg++ )
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge = seg->edge;
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  point, first, last;
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1185a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( !edge )
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = seg->first;
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last  = seg->last;
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = first;
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->x      = edge->pos;
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= AF_FLAG_TOUCH_X;
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < segment_limit; seg++ )
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge = seg->edge;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  point, first, last;
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1211a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( !edge )
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = seg->first;
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last  = seg->last;
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = first;
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->y      = edge->pos;
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= AF_FLAG_TOUCH_Y;
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                    STRONG POINT INTERPOLATION
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1239aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Hint the strong points -- this is equivalent to the TrueType `IP' */
1240aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* hinting instruction.                                              */
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      AF_Dimension   dim )
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point      points      = hints->points;
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point      point_limit = points + hints->num_points;
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis        = &hints->axis[dim];
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges       = axis->edges;
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit  = edges + axis->num_edges;
1251fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt       touch_flag;
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_X;
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag  = AF_FLAG_TOUCH_Y;
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( edges < edge_limit )
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge   edge;
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  u, ou, fu;  /* point position */
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & touch_flag )
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if this point is candidate to weak interpolation, we       */
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* interpolate it after all strong points have been processed */
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) )
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dim == AF_DIMENSION_VERT )
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u  = point->fy;
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ou = point->oy;
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u  = point->fx;
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ou = point->ox;
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fu = u;
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* is the point before the first edge? */
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge  = edges;
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = edge->fpos - u;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta >= 0 )
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = edge->pos - ( edge->opos - ou );
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Store_Point;
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* is the point after the last edge? */
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge  = edge_limit - 1;
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = u - edge->fpos;
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta >= 0 )
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = edge->pos + ( ou - edge->opos );
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Store_Point;
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1312295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_PtrDist  min, max, mid;
1313aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          FT_Pos      fpos;
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* find enclosing edges */
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min = 0;
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max = edge_limit - edges;
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
1321aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* for a small number of edges, a linear search is better */
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( max <= 8 )
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1324295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            FT_PtrDist  nn;
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1326aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( nn = 0; nn < max; nn++ )
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edges[nn].fpos >= u )
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                break;
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edges[nn].fpos == u )
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              u = edges[nn].pos;
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Store_Point;
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min = nn;
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          while ( min < max )
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid  = ( max + min ) >> 1;
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge = edges + mid;
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            fpos = edge->fpos;
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( u < fpos )
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = mid;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else if ( u > fpos )
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = mid + 1;
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* we are on the edge */
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              u = edge->pos;
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Store_Point;
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1358aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* point is not on an edge */
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge  before = edges + min - 1;
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge  after  = edges + min + 0;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* assert( before && after && before != after ) */
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->scale == 0 )
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              before->scale = FT_DivFix( after->pos - before->pos,
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         after->fpos - before->fpos );
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            u = before->pos + FT_MulFix( fu - before->fpos,
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         before->scale );
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      Store_Point:
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* save the point position */
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dim == AF_DIMENSION_HORZ )
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->x = u;
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->y = u;
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->flags |= touch_flag;
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                    WEAK POINT INTERPOLATION
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1394aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Shift the original coordinates of all points between `p1' and */
1395aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* `p2' to get hinted coordinates, using the same difference as  */
1396aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* given by `ref'.                                               */
1397aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_iup_shift( AF_Point  p1,
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                AF_Point  p2,
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                AF_Point  ref )
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  p;
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    delta = ref->u - ref->v;
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1406aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( delta == 0 )
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( p = p1; p < ref; p++ )
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p->u = p->v + delta;
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( p = ref + 1; p <= p2; p++ )
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p->u = p->v + delta;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1418aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Interpolate the original coordinates of all points between `p1' and  */
1419aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the       */
1420aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* reference points.  The `u' and `v' members are the current and       */
1421aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* original coordinate values, respectively.                            */
1422aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                      */
1423aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Details can be found in the TrueType bytecode specification.         */
1424aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_iup_interp( AF_Point  p1,
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  p2,
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  ref1,
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  ref2 )
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  p;
1432fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Pos    u, v1, v2, u1, u2, d1, d2;
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p1 > p2 )
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1438fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( ref1->v > ref2->v )
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1440fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      p    = ref1;
1441fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      ref1 = ref2;
1442fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      ref2 = p;
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1445fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    v1 = ref1->v;
1446fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    v2 = ref2->v;
1447fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    u1 = ref1->u;
1448fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    u2 = ref2->u;
1449fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    d1 = u1 - v1;
1450fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    d2 = u2 - v2;
1451fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1452fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( u1 == u2 || v1 == v2 )
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( u <= v1 )
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( u >= v2 )
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d2;
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1463fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          u = u1;
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1470fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_Fixed  scale = FT_DivFix( u2 - u1, v2 - v1 );
1471fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1472fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1477fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( u <= v1 )
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1479fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        else if ( u >= v2 )
1480fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          u += d2;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1482fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          u = u1 + FT_MulFix( u - v1, scale );
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1490aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
1491aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* hinting instruction.                                             */
1492aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    AF_Dimension   dim )
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   points        = hints->points;
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   point_limit   = points + hints->num_points;
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*  contour       = hints->contours;
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*  contour_limit = contour + hints->num_contours;
1501fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    touch_flag;
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   point;
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   end_point;
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   first_point;
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* PASS 1: Move segment points to edge positions */
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_X;
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->x;
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->ox;
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_Y;
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->y;
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->oy;
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  first_touched, last_touched;
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point       = *contour;
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end_point   = point->prev;
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_point = point;
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* find first touched point */
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point > end_point )  /* no touched point in contour */
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NextContour;
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & touch_flag )
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_touched = point;
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1555aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_ASSERT( point <= end_point                 &&
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   ( point->flags & touch_flag ) != 0 );
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1558aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* skip any touched neighbours */
1559aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        while ( point < end_point                    &&
1560aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                ( point[1].flags & touch_flag ) != 0 )
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point++;
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_touched = point;
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* find the next touched point, if any */
1566aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        point++;
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point > end_point )
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto EndContour;
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( point->flags & touch_flag ) != 0 )
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point++;
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* interpolate between last_touched and point */
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_iup_interp( last_touched + 1, point - 1,
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       last_touched, point );
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    EndContour:
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* special case: only one point was touched */
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( last_touched == first_touched )
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_iup_shift( first_point, end_point, first_touched );
1587aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else /* interpolate the last part */
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( last_touched < end_point )
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_iup_interp( last_touched + 1, end_point,
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         last_touched, first_touched );
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_touched > points )
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_iup_interp( first_point, first_touched - 1,
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         last_touched, first_touched );
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NextContour:
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now save the interpolated values back to x/y */
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->x = point->u;
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->y = point->u;
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1617aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
1618aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1619aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Apply (small) warp scale and warp delta for given dimension. */
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            AF_Dimension   dim,
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Fixed       scale,
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Pos         delta )
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points       = hints->points;
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points_limit = points + hints->num_points;
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  point;
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < points_limit; point++ )
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->x = FT_MulFix( point->fx, scale ) + delta;
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < points_limit; point++ )
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->y = FT_MulFix( point->fy, scale ) + delta;
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1644aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* AF_CONFIG_OPTION_USE_WARPER */
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
1647