afhints.c revision fb6b5b10aaa74b8c8974714b41bac35bdd1c772d
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/*                                                                         */
7fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki/*  Copyright 2003-2015 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    {
48fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->segments == NULL )
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,
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Memory     memory,
103727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                          AF_Edge      *anedge )
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
105727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error  error = FT_Err_Ok;
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge   edge  = NULL;
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge   edges;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
110fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( axis->num_edges < AF_EDGES_EMBEDDED )
111fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
112fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->edges == NULL )
113fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
114fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        axis->edges     = axis->embedded.edges;
115fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        axis->max_edges = AF_EDGES_EMBEDDED;
116fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
117fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
118fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( axis->num_edges >= axis->max_edges )
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  old_max = axis->max_edges;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  new_max = old_max;
122295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( old_max >= big_max )
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
127727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Out_Of_Memory );
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      new_max += ( new_max >> 2 ) + 4;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( new_max < old_max || new_max > big_max )
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        new_max = big_max;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
135fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->edges == axis->embedded.edges )
136fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
137fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( FT_NEW_ARRAY( axis->edges, new_max ) )
138fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          goto Exit;
139fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ft_memcpy( axis->edges, axis->embedded.edges,
140fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                   sizeof ( axis->embedded.edges ) );
141fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
142fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      else
143fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
144fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
145fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          goto Exit;
146fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->max_edges = new_max;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edges = axis->edges;
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge  = edges + axis->num_edges;
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( edge > edges )
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge[-1].fpos < fpos )
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we want the edge with same position and minor direction */
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* to appear before those in the major one in the list     */
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge[-1].fpos == fpos && dir == axis->major_dir )
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge[0] = edge[-1];
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge--;
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges++;
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
171727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    *anedge = edge;
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
176aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef FT_DEBUG_AUTOFIT
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1780a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include FT_CONFIG_STANDARD_LIBRARY_H
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
180ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* The dump functions are used in the `ftgrid' demo program, too. */
181ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#define AF_DUMP( varformat )          \
182ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          do                          \
183ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {                           \
184ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            if ( to_stdout )          \
185ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              printf varformat;       \
186ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            else                      \
187ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              FT_TRACE7( varformat ); \
188ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          } while ( 0 )
189ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
190ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const char*
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_dir_str( AF_Direction  dir )
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    const char*  result;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( dir )
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_UP:
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "up";
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_DOWN:
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "down";
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_LEFT:
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "left";
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case AF_DIR_RIGHT:
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "right";
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = "none";
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
219fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define AF_INDEX_NUM( ptr, base )  (int)( (ptr) ? ( (ptr) - (base) ) : -1 )
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
222aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
223aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
224aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
226ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_points( AF_GlyphHints  hints,
227ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                              FT_Bool        to_stdout )
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points = hints->points;
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  limit  = points + hints->num_points;
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  point;
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
234fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    AF_DUMP(( "Table of points:\n" ));
235fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
236fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( hints->num_points )
237fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      AF_DUMP(( "  [ index |  xorg |  yorg | xscale | yscale"
238fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                " |  xfit |  yfit |  flags ]\n" ));
239fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else
240fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      AF_DUMP(( "  (none)\n" ));
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( point = points; point < limit; point++ )
243ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
244fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                " | %5.2f | %5.2f | %c ]\n",
245fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                AF_INDEX_NUM( point, points ),
246ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->fx,
247ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->fy,
248ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->ox / 64.0,
249ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->oy / 64.0,
250ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->x / 64.0,
251ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                point->y / 64.0,
252fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' '));
253ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    AF_DUMP(( "\n" ));
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
255aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
256aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
257aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const char*
261fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  af_edge_flags_to_string( FT_UInt  flags )
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static char  temp[32];
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int          pos = 0;
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( flags & AF_EDGE_ROUND )
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( temp + pos, "round", 5 );
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pos += 5;
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( flags & AF_EDGE_SERIF )
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( pos > 0 )
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        temp[pos++] = ' ';
2760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( temp + pos, "serif", 5 );
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pos += 5;
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( pos == 0 )
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return "normal";
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
282727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    temp[pos] = '\0';
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return temp;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
288aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Dump the array of linked segments. */
289aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
290aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
291aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
292aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
294ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_segments( AF_GlyphHints  hints,
295ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                FT_Bool        to_stdout )
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  dimension;
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dimension = 1; dimension >= 0; dimension-- )
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_AxisHints  axis     = &hints->axis[dimension];
303727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_Point      points   = hints->points;
304727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_Edge       edges    = axis->edges;
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    segments = axis->segments;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    limit    = segments + axis->num_segments;
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment    seg;
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
310ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "Table of %s segments:\n",
311ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                dimension == AF_DIMENSION_HORZ ? "vertical"
312ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                               : "horizontal" ));
313727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( axis->num_segments )
314ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ index |  pos  |  dir  | from"
315ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " |  to  | link | serif | edge"
316ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | height | extra |    flags    ]\n" ));
317727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
318ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  (none)\n" ));
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < limit; seg++ )
321ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ %5d | %5.2g | %5s | %4d"
322ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | %4d | %4d | %5d | %4d"
323ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | %6d | %5d | %11s ]\n",
324fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  AF_INDEX_NUM( seg, segments ),
325ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  dimension == AF_DIMENSION_HORZ
326ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                               ? (int)seg->first->ox / 64.0
327ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                               : (int)seg->first->oy / 64.0,
328ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_dir_str( (AF_Direction)seg->dir ),
329ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->first, points ),
330ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->last, points ),
331ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->link, segments ),
332ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->serif, segments ),
333ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( seg->edge, edges ),
334ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg->height,
335ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  seg->height - ( seg->max_coord - seg->min_coord ),
336fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  af_edge_flags_to_string( seg->flags ) ));
337ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "\n" ));
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
340aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
341aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
342aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
343aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
344aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
345aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Fetch number of segments. */
346aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
347aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
348aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
349aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
350aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  FT_Error
351aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
352aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   FT_Int         dimension,
353aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   FT_Int*        num_segments )
354aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  {
355aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Dimension  dim;
356aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_AxisHints  axis;
357aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
358aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
359aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
360aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
361aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    axis          = &hints->axis[dim];
362aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    *num_segments = axis->num_segments;
363aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
364727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
365aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
366aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
367aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
368aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
369aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
370aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
371aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Fetch offset of segments into user supplied offset array. */
372aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
373aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
374aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
375aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
376aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  FT_Error
377aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
378aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                     FT_Int         dimension,
379aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                     FT_Int         idx,
3809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Pos        *offset,
3819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Bool       *is_blue,
3829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                     FT_Pos        *blue_offset )
383aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  {
384aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Dimension  dim;
385aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_AxisHints  axis;
386aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Segment    seg;
387aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
388aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
389aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    if ( !offset )
390727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
391aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
392aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
393aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
394aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    axis = &hints->axis[dim];
395aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
396aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    if ( idx < 0 || idx >= axis->num_segments )
397727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
398aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
3999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    seg      = &axis->segments[idx];
4009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    *offset  = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
4019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                            : seg->first->oy;
4029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( seg->edge )
4039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
4049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
4059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *is_blue = FALSE;
4069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( *is_blue )
4089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *blue_offset = seg->edge->blue_edge->cur;
4099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
4109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *blue_offset = 0;
411aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
412727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
413aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
414aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
415aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
416aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
417aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
419aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Dump the array of linked edges. */
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
421aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
422aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  extern "C" {
423aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  void
425ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  af_glyph_hints_dump_edges( AF_GlyphHints  hints,
426ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                             FT_Bool        to_stdout )
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  dimension;
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dimension = 1; dimension >= 0; dimension-- )
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_AxisHints  axis  = &hints->axis[dimension];
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       edges = axis->edges;
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       limit = edges + axis->num_edges;
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge       edge;
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
441aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner       *        since they have a constant X coordinate.
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
443ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "Table of %s edges:\n",
444ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                dimension == AF_DIMENSION_HORZ ? "vertical"
445ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                                               : "horizontal" ));
446727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( axis->num_edges )
447ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ index |  pos  |  dir  | link"
448ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | serif | blue | opos  |  pos  |    flags    ]\n" ));
449727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
450ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  (none)\n" ));
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < limit; edge++ )
453ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        AF_DUMP(( "  [ %5d | %5.2g | %5s | %4d"
454ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  " | %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
455fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  AF_INDEX_NUM( edge, edges ),
456ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  (int)edge->opos / 64.0,
457ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  af_dir_str( (AF_Direction)edge->dir ),
458ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( edge->link, edges ),
459ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  AF_INDEX_NUM( edge->serif, edges ),
460ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->blue_edge ? 'y' : 'n',
461ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->opos / 64.0,
462ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                  edge->pos / 64.0,
463fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  af_edge_flags_to_string( edge->flags ) ));
464ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      AF_DUMP(( "\n" ));
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
467aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef __cplusplus
468aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  }
469aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
471ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#undef AF_DUMP
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
473aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* !FT_DEBUG_AUTOFIT */
474aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
475aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
476aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Compute the direction value of a given vector. */
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( AF_Direction )
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_direction_compute( FT_Pos  dx,
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Pos  dy )
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        ll, ss;  /* long and short arm lengths */
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  dir;     /* candidate direction        */
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dy >= dx )
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy >= -dx )
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_UP;
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dy;
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dx;
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_LEFT;
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = -dx;
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dy;
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else /* dy < dx */
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy >= -dx )
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_RIGHT;
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ll  = dx;
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dy;
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dir = AF_DIR_DOWN;
512fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ll  = -dy;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ss  = dx;
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
517fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* return no direction if arm lengths do not differ enough       */
518727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */
519fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* the long arm is never negative                                */
520fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( ll <= 14 * FT_ABS( ss ) )
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dir = AF_DIR_NONE;
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dir;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_init( AF_GlyphHints  hints,
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Memory      memory )
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
531fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* no need to initialize the embedded items */
532fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_MEM_ZERO( hints, sizeof ( *hints ) - sizeof ( hints->embedded ) );
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->memory = memory;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_done( AF_GlyphHints  hints )
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
540fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Memory  memory;
541727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int        dim;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( !( hints && hints->memory ) )
545727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return;
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
547fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    memory = hints->memory;
548fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
549727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /*
550727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     *  note that we don't need to free the segment and edge
551727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     *  buffers since they are really within the hints->points array
552727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease     */
553727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
554727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
555727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      AF_AxisHints  axis = &hints->axis[dim];
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
558727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->num_segments = 0;
559727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->max_segments = 0;
560fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->segments != axis->embedded.segments )
561fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FREE( axis->segments );
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
563727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->num_edges = 0;
564727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      axis->max_edges = 0;
565fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( axis->edges != axis->embedded.edges )
566fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FREE( axis->edges );
567727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
569fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( hints->contours != hints->embedded.contours )
570fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_FREE( hints->contours );
571727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->max_contours = 0;
572727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->num_contours = 0;
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
574fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( hints->points != hints->embedded.points )
575fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_FREE( hints->points );
576727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->max_points = 0;
577fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    hints->num_points = 0;
578727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
579727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    hints->memory = NULL;
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
583aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Reset metrics. */
584aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
5869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_glyph_hints_rescale( AF_GlyphHints    hints,
5879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                          AF_StyleMetrics  metrics )
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->metrics      = metrics;
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = metrics->scaler.flags;
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
594aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Recompute all AF_Point in AF_GlyphHints from the definitions */
595aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* in a source outline.                                         */
596aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_reload( AF_GlyphHints  hints,
599aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                         FT_Outline*    outline )
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
601727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error   = FT_Err_Ok;
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   points;
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    old_max, new_max;
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   x_scale = hints->x_scale;
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed   y_scale = hints->y_scale;
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos     x_delta = hints->x_delta;
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos     y_delta = hints->y_delta;
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory  = hints->memory;
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_points   = 0;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_contours = 0;
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[0].num_segments = 0;
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[0].num_edges    = 0;
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[1].num_segments = 0;
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[1].num_edges    = 0;
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
619aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* first of all, reallocate the contours array if necessary */
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_max = (FT_UInt)outline->n_contours;
621fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    old_max = (FT_UInt)hints->max_contours;
622fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
623fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( new_max <= AF_CONTOURS_EMBEDDED )
624fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
625fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( hints->contours == NULL )
626fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
627fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->contours     = hints->embedded.contours;
628fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->max_contours = AF_CONTOURS_EMBEDDED;
629fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
630fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
631fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( new_max > old_max )
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
633fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( hints->contours == hints->embedded.contours )
634fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->contours = NULL;
635fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
636fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
641fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      hints->max_contours = (FT_Int)new_max;
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  then reallocate the points arrays if necessary --
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  note that we reserve two additional point positions, used to
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  hint metrics appropriately
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    new_max = (FT_UInt)( outline->n_points + 2 );
650fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    old_max = (FT_UInt)hints->max_points;
651fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
652fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( new_max <= AF_POINTS_EMBEDDED )
653fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
654fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( hints->points == NULL )
655fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
656fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->points     = hints->embedded.points;
657fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->max_points = AF_POINTS_EMBEDDED;
658fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
659fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
660fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    else if ( new_max > old_max )
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
662fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( hints->points == hints->embedded.points )
663fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        hints->points = NULL;
664fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
665fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
670fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      hints->max_points = (FT_Int)new_max;
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_points   = outline->n_points;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->num_contours = outline->n_contours;
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We can't rely on the value of `FT_Outline.flags' to know the fill   */
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* direction used for a glyph, given that some fonts are broken (e.g., */
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the Arphic ones).  We thus recompute it each time we need to.       */
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = x_scale;
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = y_scale;
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = x_delta;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = y_delta;
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->xmin_delta = 0;
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->xmax_delta = 0;
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    points = hints->points;
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( hints->num_points == 0 )
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point;
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point_limit = points + hints->num_points;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute coordinates & Bezier flags, next and prev */
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  vec           = outline->points;
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char*       tag           = outline->tags;
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point    end           = points + outline->contours[0];
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point    prev          = end;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int      contour_index = 0;
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( point = points; point < point_limit; point++, vec++, tag++ )
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
7179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point->in_dir  = (FT_Char)AF_DIR_NONE;
7189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point->out_dir = (FT_Char)AF_DIR_NONE;
7199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->fx = (FT_Short)vec->x;
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->fy = (FT_Short)vec->y;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          switch ( FT_CURVE_TAG( *tag ) )
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case FT_CURVE_TAG_CONIC:
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags = AF_FLAG_CONIC;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case FT_CURVE_TAG_CUBIC:
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags = AF_FLAG_CUBIC;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          default:
734aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            point->flags = AF_FLAG_NONE;
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->prev = prev;
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev->next  = point;
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev        = point;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == end )
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ++contour_index < outline->n_contours )
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
745aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich              end  = points + outline->contours[contour_index];
746aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich              prev = end;
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
752aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* set up the contours array */
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point*  contour       = hints->contours;
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point*  contour_limit = contour + hints->num_contours;
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        short*     end           = outline->contours;
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        short      idx           = 0;
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; contour < contour_limit; contour++, end++ )
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          contour[0] = points + idx;
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          idx        = (short)( end[0] + 1 );
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
7689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
7699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Compute directions of `in' and `out' vectors.
7709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *
7719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Note that distances between points that are very near to each
7729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  other are accumulated.  In other words, the auto-hinter
7739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  prepends the small vectors between near points to the first
7749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  non-near vector.  All intermediate points are tagged as
7759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  weak; the directions are adjusted also to be equal to the
7769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  accumulated one.
7779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
7789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /* value 20 in `near_limit' is heuristic */
780ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
781ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        FT_Int   near_limit   = 20 * units_per_em / 2048;
7829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_Int   near_limit2  = 2 * near_limit - 1;
783ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
7849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        AF_Point*  contour;
7859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        AF_Point*  contour_limit = hints->contours + hints->num_contours;
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
7879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( contour = hints->contours; contour < contour_limit; contour++ )
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
7909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          AF_Point  first = *contour;
7919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          AF_Point  next, prev, curr;
7929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
7939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          FT_Pos  out_x, out_y;
7949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
7969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* since the first point of a contour could be part of a */
7979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* series of near points, go backwards to find the first */
7989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* non-near point and adjust `first'                     */
7999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          point = first;
8019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          prev  = first->prev;
8029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          while ( prev != first )
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
8059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = point->fx - prev->fx;
8069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = point->fy - prev->fy;
8079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /*
8099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  We use Taxicab metrics to measure the vector length.
8109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *
8119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  Note that the accumulated distances so far could have the
8129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  opposite direction of the distance measured here.  For this
8139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  reason we use `near_limit2' for the comparison to get a
8149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             *  non-near point even in the worst case.
8159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod             */
8169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
8179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              break;
8189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            point = prev;
8209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            prev  = prev->prev;
8219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
822ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* adjust first point */
8249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          first = point;
825ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* now loop over all points of the contour to get */
8279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /* `in' and `out' vector directions               */
828ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          curr  = first;
830ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          /*
8329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  We abuse the `u' and `v' fields to store index deltas to the
8339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  next and previous non-near point, respectively.
8349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *
8359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  To avoid problems with not having non-near points, we point to
8369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *  `first' by default as the next non-near point.
8379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           *
8389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod           */
8399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          curr->u  = (FT_Pos)( first - curr );
8409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          first->v = -curr->u;
841ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          out_x = 0;
8439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          out_y = 0;
844ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
845fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          next = first;
846fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          do
8479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          {
8489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Direction  out_dir;
849ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
850ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
851fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            point = next;
8529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next = point->next;
853ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x += next->fx - point->fx;
8559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y += next->fy - point->fy;
8569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
8589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
8599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              next->flags |= AF_FLAG_WEAK_INTERPOLATION;
8609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              continue;
861ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
862ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
8639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->u = (FT_Pos)( next - curr );
8649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next->v = -curr->u;
8659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_dir = af_direction_compute( out_x, out_y );
8679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* adjust directions for all points inbetween; */
8699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* the loop also updates position of `curr'    */
8709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->out_dir = (FT_Char)out_dir;
8719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            for ( curr = curr->next; curr != next; curr = curr->next )
8729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
8739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              curr->in_dir  = (FT_Char)out_dir;
8749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              curr->out_dir = (FT_Char)out_dir;
8759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
8769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            next->in_dir = (FT_Char)out_dir;
8779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            curr->u  = (FT_Pos)( first - curr );
8799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            first->v = -curr->u;
8809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = 0;
8829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = 0;
883fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
884fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          } while ( next != first );
8859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
8889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  The next step is to `simplify' an outline's topology so that we
8899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  can identify local extrema more reliably: A series of
8909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  non-horizontal or non-vertical vectors pointing into the same
8919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  quadrant are handled as a single, long vector.  From a
8929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  topological point of the view, the intermediate points are of no
8939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  interest and thus tagged as weak.
8949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( point = points; point < point_limit; point++ )
8979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
8989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
8999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            continue;
900ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->in_dir  == AF_DIR_NONE &&
9029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod               point->out_dir == AF_DIR_NONE )
903ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {
9049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            /* check whether both vectors point into the same quadrant */
9059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            FT_Pos  in_x, in_y;
9079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            FT_Pos  out_x, out_y;
9089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Point  next_u = point + point->u;
9109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            AF_Point  prev_v = point + point->v;
9119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
912ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
9139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            in_x = point->fx - prev_v->fx;
9149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            in_y = point->fy - prev_v->fy;
9159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_x = next_u->fx - point->fx;
9179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            out_y = next_u->fy - point->fy;
9189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 )
9209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
9219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              /* yes, so tag current point as weak */
9229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              /* and update index deltas           */
9239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              point->flags |= AF_FLAG_WEAK_INTERPOLATION;
9259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              prev_v->u = (FT_Pos)( next_u - prev_v );
9279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              next_u->v = -prev_v->u;
9289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
9299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
9309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
9329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        /*
9339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  Finally, check for remaining weak points.  Everything else not
9349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  collected in edges so far is then implicitly classified as strong
9359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         *  points.
9369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         */
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
9389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        for ( point = points; point < point_limit; point++ )
9399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
9409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
9419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            continue;
942aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
943727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( point->flags & AF_FLAG_CONTROL )
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
945ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            /* control points are always weak */
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          Is_Weak_Point:
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( point->out_dir == point->in_dir )
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point->out_dir != AF_DIR_NONE )
952ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            {
953ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              /* current point lies on a horizontal or          */
954ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease              /* vertical segment (but doesn't start or end it) */
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Is_Weak_Point;
956ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
958ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            {
9599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              AF_Point  next_u = point + point->u;
9609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              AF_Point  prev_v = point + point->v;
9619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              if ( ft_corner_is_flat( point->fx  - prev_v->fx,
9649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      point->fy  - prev_v->fy,
9659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      next_u->fx - point->fx,
9669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                      next_u->fy - point->fy ) )
9679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              {
9689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* either the `in' or the `out' vector is much more  */
9699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* dominant than the other one, so tag current point */
9709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                /* as weak and update index deltas                   */
9719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                prev_v->u = (FT_Pos)( next_u - prev_v );
9739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                next_u->v = -prev_v->u;
9749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
9759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                goto Is_Weak_Point;
9769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              }
977ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            }
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( point->in_dir == -point->out_dir )
980ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          {
981ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease            /* current point forms a spike */
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Is_Weak_Point;
983ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease          }
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
993aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Store the hinted outline in an FT_Outline structure. */
994aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_save( AF_GlyphHints  hints,
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Outline*    outline )
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point    point = hints->points;
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point    limit = point + hints->num_points;
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec   = outline->points;
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tag   = outline->tags;
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; point < limit; point++, vec++, tag++ )
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->x = point->x;
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->y = point->y;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point->flags & AF_FLAG_CONIC )
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_CONIC;
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( point->flags & AF_FLAG_CUBIC )
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_CUBIC;
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag[0] = FT_CURVE_TAG_ON;
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                     EDGE POINT GRID-FITTING
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1027aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Align all points of an edge to the same coordinate value, */
1028aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* either horizontally or vertically.                        */
1029aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    AF_Dimension   dim )
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = & hints->axis[dim];
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < segment_limit; seg++ )
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge = seg->edge;
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  point, first, last;
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge == NULL )
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = seg->first;
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last  = seg->last;
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = first;
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->x      = edge->pos;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= AF_FLAG_TOUCH_X;
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg = segments; seg < segment_limit; seg++ )
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge = seg->edge;
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  point, first, last;
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge == NULL )
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = seg->first;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last  = seg->last;
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = first;
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->y      = edge->pos;
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= AF_FLAG_TOUCH_Y;
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                    STRONG POINT INTERPOLATION
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1102aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Hint the strong points -- this is equivalent to the TrueType `IP' */
1103aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* hinting instruction.                                              */
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      AF_Dimension   dim )
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point      points      = hints->points;
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point      point_limit = points + hints->num_points;
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis        = &hints->axis[dim];
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges       = axis->edges;
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit  = edges + axis->num_edges;
1114fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt       touch_flag;
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_X;
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag  = AF_FLAG_TOUCH_Y;
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( edges < edge_limit )
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point;
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge   edge;
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  u, ou, fu;  /* point position */
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & touch_flag )
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if this point is candidate to weak interpolation, we       */
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* interpolate it after all strong points have been processed */
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1140fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) )
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dim == AF_DIMENSION_VERT )
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u  = point->fy;
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ou = point->oy;
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u  = point->fx;
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ou = point->ox;
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fu = u;
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* is the point before the first edge? */
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge  = edges;
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = edge->fpos - u;
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta >= 0 )
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = edge->pos - ( edge->opos - ou );
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Store_Point;
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* is the point after the last edge? */
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge  = edge_limit - 1;
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = u - edge->fpos;
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta >= 0 )
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = edge->pos + ( ou - edge->opos );
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Store_Point;
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1175295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_PtrDist  min, max, mid;
1176aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          FT_Pos      fpos;
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* find enclosing edges */
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min = 0;
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max = edge_limit - edges;
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
1184aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* for a small number of edges, a linear search is better */
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( max <= 8 )
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1187295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            FT_PtrDist  nn;
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1189aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( nn = 0; nn < max; nn++ )
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edges[nn].fpos >= u )
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                break;
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edges[nn].fpos == u )
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              u = edges[nn].pos;
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Store_Point;
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min = nn;
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          while ( min < max )
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid  = ( max + min ) >> 1;
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge = edges + mid;
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            fpos = edge->fpos;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( u < fpos )
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = mid;
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else if ( u > fpos )
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = mid + 1;
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* we are on the edge */
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              u = edge->pos;
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Store_Point;
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1221aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* point is not on an edge */
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge  before = edges + min - 1;
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge  after  = edges + min + 0;
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* assert( before && after && before != after ) */
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->scale == 0 )
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              before->scale = FT_DivFix( after->pos - before->pos,
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         after->fpos - before->fpos );
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            u = before->pos + FT_MulFix( fu - before->fpos,
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         before->scale );
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      Store_Point:
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* save the point position */
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dim == AF_DIMENSION_HORZ )
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->x = u;
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->y = u;
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->flags |= touch_flag;
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****************************************************************
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *                    WEAK POINT INTERPOLATION
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   *
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   ****************************************************************/
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1257aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Shift the original coordinates of all points between `p1' and */
1258aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* `p2' to get hinted coordinates, using the same difference as  */
1259aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* given by `ref'.                                               */
1260aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_iup_shift( AF_Point  p1,
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                AF_Point  p2,
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                AF_Point  ref )
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  p;
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos    delta = ref->u - ref->v;
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1269aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( delta == 0 )
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( p = p1; p < ref; p++ )
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p->u = p->v + delta;
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( p = ref + 1; p <= p2; p++ )
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p->u = p->v + delta;
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1281aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Interpolate the original coordinates of all points between `p1' and  */
1282aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the       */
1283aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* reference points.  The `u' and `v' members are the current and       */
1284aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* original coordinate values, respectively.                            */
1285aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                      */
1286aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Details can be found in the TrueType bytecode specification.         */
1287aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_iup_interp( AF_Point  p1,
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  p2,
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  ref1,
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 AF_Point  ref2 )
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  p;
1295fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Pos    u, v1, v2, u1, u2, d1, d2;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p1 > p2 )
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1301fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( ref1->v > ref2->v )
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1303fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      p    = ref1;
1304fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      ref1 = ref2;
1305fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      ref2 = p;
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1308fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    v1 = ref1->v;
1309fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    v2 = ref2->v;
1310fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    u1 = ref1->u;
1311fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    u2 = ref2->u;
1312fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    d1 = u1 - v1;
1313fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    d2 = u2 - v2;
1314fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1315fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( u1 == u2 || v1 == v2 )
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( u <= v1 )
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( u >= v2 )
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d2;
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1326fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          u = u1;
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1333fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_Fixed  scale = FT_DivFix( u2 - u1, v2 - v1 );
1334fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1335fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( p = p1; p <= p2; p++ )
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u = p->v;
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1340fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( u <= v1 )
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u += d1;
1342fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        else if ( u >= v2 )
1343fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          u += d2;
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1345fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          u = u1 + FT_MulFix( u - v1, scale );
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p->u = u;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1353aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
1354aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* hinting instruction.                                             */
1355aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    AF_Dimension   dim )
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   points        = hints->points;
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   point_limit   = points + hints->num_points;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*  contour       = hints->contours;
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*  contour_limit = contour + hints->num_contours;
1364fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    touch_flag;
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   point;
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   end_point;
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point   first_point;
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* PASS 1: Move segment points to edge positions */
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_X;
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->x;
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->ox;
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      touch_flag = AF_FLAG_TOUCH_Y;
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->y;
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->oy;
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  first_touched, last_touched;
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point       = *contour;
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end_point   = point->prev;
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_point = point;
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* find first touched point */
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point > end_point )  /* no touched point in contour */
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NextContour;
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & touch_flag )
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_touched = point;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1418aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_ASSERT( point <= end_point                 &&
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   ( point->flags & touch_flag ) != 0 );
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1421aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* skip any touched neighbours */
1422aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        while ( point < end_point                    &&
1423aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                ( point[1].flags & touch_flag ) != 0 )
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point++;
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_touched = point;
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* find the next touched point, if any */
1429aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        point++;
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point > end_point )
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto EndContour;
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( point->flags & touch_flag ) != 0 )
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point++;
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* interpolate between last_touched and point */
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_iup_interp( last_touched + 1, point - 1,
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       last_touched, point );
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    EndContour:
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* special case: only one point was touched */
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( last_touched == first_touched )
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_iup_shift( first_point, end_point, first_touched );
1450aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else /* interpolate the last part */
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( last_touched < end_point )
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_iup_interp( last_touched + 1, end_point,
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         last_touched, first_touched );
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_touched > points )
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_iup_interp( first_point, first_touched - 1,
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         last_touched, first_touched );
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NextContour:
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now save the interpolated values back to x/y */
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->x = point->u;
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < point_limit; point++ )
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->y = point->u;
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1480aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
1481aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1482aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Apply (small) warp scale and warp delta for given dimension. */
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            AF_Dimension   dim,
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Fixed       scale,
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Pos         delta )
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points       = hints->points;
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  points_limit = points + hints->num_points;
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point  point;
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < points_limit; point++ )
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->x = FT_MulFix( point->fx, scale ) + delta;
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = points; point < points_limit; point++ )
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->y = FT_MulFix( point->fy, scale ) + delta;
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1507aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* AF_CONFIG_OPTION_USE_WARPER */
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
1510