1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  pshalgo.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    PostScript hinting algorithm (body).                                 */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
79c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  Copyright 2001-2010, 2012-2014 by                                      */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used        */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified and distributed under the terms of the FreeType project       */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_CALC_H
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "pshalgo.h"
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "pshnterr.h"
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_pshalgo2
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  PSH_Hint_Table  ps_debug_hint_table = 0;
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  PSH_HintFunc    ps_debug_hint_func  = 0;
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  PSH_Glyph       ps_debug_glyph      = 0;
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  COMPUTE_INFLEXS  /* compute inflection points to optimize `S' */
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          /* and similar glyphs                        */
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  STRONGER         /* slightly increase the contrast of smooth  */
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          /* hinting                                   */
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                  BASIC HINTS RECORDINGS                       *****/
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* return true if two stem hints overlap */
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Int
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_overlap( PSH_Hint  hint1,
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    PSH_Hint  hint2 )
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return hint1->org_pos + hint1->org_len >= hint2->org_pos &&
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           hint2->org_pos + hint2->org_len >= hint1->org_pos;
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* destroy hints table */
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_done( PSH_Hint_Table  table,
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Memory       memory )
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( table->zones );
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->num_zones = 0;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->zone      = 0;
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( table->sort );
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( table->hints );
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->num_hints   = 0;
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->max_hints   = 0;
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->sort_global = 0;
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* deactivate all hints in a table */
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_deactivate( PSH_Hint_Table  table )
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count = table->max_hints;
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Hint  hint  = table->hints;
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, hint++ )
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_hint_deactivate( hint );
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hint->order = -1;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* internal function to record a new hint */
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_record( PSH_Hint_Table  table,
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_UInt         idx )
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Hint  hint = table->hints + idx;
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx >= table->max_hints )
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
106295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx ));
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* ignore active hints */
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( psh_hint_is_active( hint ) )
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_hint_activate( hint );
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now scan the current active hint set to check */
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* whether `hint' overlaps with another hint     */
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Hint*  sorted = table->sort_global;
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    count  = table->num_hints;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Hint   hint2;
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hint->parent = 0;
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count--, sorted++ )
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint2 = sorted[0];
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( psh_hint_overlap( hint, hint2 ) )
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint->parent = hint2;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table->num_hints < table->max_hints )
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      table->sort_global[table->num_hints++] = hint;
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
140295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE0(( "psh_hint_table_record: too many sorted hints!  BUG!\n" ));
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_record_mask( PSH_Hint_Table  table,
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              PS_Mask         hint_mask )
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int    mask = 0, val = 0;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  cursor = hint_mask->bytes;
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   idx, limit;
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    limit = hint_mask->num_bits;
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( idx = 0; idx < limit; idx++ )
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( mask == 0 )
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        val  = *cursor++;
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mask = 0x80;
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( val & mask )
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_hint_table_record( table, idx );
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mask >>= 1;
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* create hints table */
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_init( PSH_Hint_Table  table,
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       PS_Hint_Table   hints,
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       PS_Mask_Table   hint_masks,
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       PS_Mask_Table   counter_masks,
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Memory       memory )
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count;
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( counter_masks );
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count = hints->num_hints;
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* allocate our tables */
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( table->sort,  2 * count     ) ||
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( table->hints,     count     ) ||
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->max_hints   = count;
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->sort_global = table->sort + count;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->num_hints   = 0;
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->num_zones   = 0;
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->zone        = 0;
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* initialize the `table->hints' array */
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Hint  write = table->hints;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PS_Hint   read  = hints->hints;
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count--, write++, read++ )
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        write->org_pos = read->pos;
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        write->org_len = read->len;
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        write->flags   = read->flags;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we now need to determine the initial `parent' stems; first  */
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* activate the hints that are given by the initial hint masks */
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( hint_masks )
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PS_Mask  mask = hint_masks->masks;
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count             = hint_masks->num_masks;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      table->hint_masks = hint_masks;
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count--, mask++ )
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_hint_table_record_mask( table, mask );
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* finally, do a linear parse in case some hints were left alone */
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table->num_hints != table->max_hints )
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  idx;
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
233295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE0(( "psh_hint_table_init: missing/incorrect hint masks\n" ));
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count = table->max_hints;
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( idx = 0; idx < count; idx++ )
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_hint_table_record( table, idx );
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_activate_mask( PSH_Hint_Table  table,
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                PS_Mask         hint_mask )
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int    mask = 0, val = 0;
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  cursor = hint_mask->bytes;
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   idx, limit, count;
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    limit = hint_mask->num_bits;
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count = 0;
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_hint_table_deactivate( table );
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( idx = 0; idx < limit; idx++ )
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( mask == 0 )
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        val  = *cursor++;
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mask = 0x80;
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( val & mask )
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        PSH_Hint  hint = &table->hints[idx];
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !psh_hint_is_active( hint ) )
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt     count2;
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PSH_Hint*  sort = table->sort;
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PSH_Hint   hint2;
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( count2 = count; count2 > 0; count2--, sort++ )
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint2 = sort[0];
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( psh_hint_overlap( hint, hint2 ) )
285295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner              FT_TRACE0(( "psh_hint_table_activate_mask:"
286295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                          " found overlapping hints\n" ))
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          count2 = 0;
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( count2 == 0 )
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            psh_hint_activate( hint );
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( count < table->max_hints )
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              table->sort[count++] = hint;
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
298295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner              FT_TRACE0(( "psh_hint_tableactivate_mask:"
299295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                          " too many active hints\n" ));
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mask >>= 1;
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table->num_hints = count;
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now, sort the hints; they are guaranteed to not overlap */
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* so we can compare their "org_pos" field directly        */
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int     i1, i2;
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Hint   hint1, hint2;
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Hint*  sort = table->sort;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* a simple bubble sort will do, since in 99% of cases, the hints */
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* will be already sorted -- and the sort will be linear          */
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i1 = 1; i1 < (FT_Int)count; i1++ )
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint1 = sort[i1];
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( i2 = i1 - 1; i2 >= 0; i2-- )
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint2 = sort[i2];
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( hint2->org_pos < hint1->org_pos )
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          sort[i2 + 1] = hint2;
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          sort[i2]     = hint1;
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****               HINTS GRID-FITTING AND OPTIMIZATION             *****/
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_dimension_quantize_len( PSH_Dimension  dim,
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Pos         len,
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Bool        do_snapping )
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( len <= 64 )
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      len = 64;
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  delta = len - dim->stdw.widths[0].cur;
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( delta < 0 )
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = -delta;
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( delta < 40 )
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        len = dim->stdw.widths[0].cur;
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( len < 48 )
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len = 48;
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( len < 3 * 64 )
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = ( len & 63 );
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        len  &= -64;
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < 10 )
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len += delta;
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( delta < 32 )
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len += 10;
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( delta < 54 )
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len += 54;
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len += delta;
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        len = FT_PIX_ROUND( len );
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( do_snapping )
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      len = FT_PIX_ROUND( len );
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return  len;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ps_simple_scale( PSH_Hint_Table  table,
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Fixed        scale,
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Fixed        delta,
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Int          dimension )
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
404727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UInt  count;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( count = 0; count < table->max_hints; count++ )
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
409727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      PSH_Hint  hint = table->hints + count;
410727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hint->cur_len = FT_MulFix( hint->org_len, scale );
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ps_debug_hint_func )
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ps_debug_hint_func( hint, dimension );
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_HINTER */
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Fixed
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_snap_stem_side_delta( FT_Fixed  pos,
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_Fixed  len )
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed  delta1 = FT_PIX_ROUND( pos ) - pos;
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed  delta2 = FT_PIX_ROUND( pos + len ) - pos - len;
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) )
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return delta1;
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return delta2;
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_align( PSH_Hint     hint,
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  PSH_Globals  globals,
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Int       dimension,
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  PSH_Glyph    glyph )
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension  dim   = &globals->dimension[dimension];
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       scale = dim->scale_mult;
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       delta = dim->scale_delta;
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !psh_hint_is_fitted( hint ) )
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  len = FT_MulFix( hint->org_len, scale );
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int            do_snapping;
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos            fit_len;
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_AlignmentRec  align;
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* ignore stem alignments when requested through the hint flags */
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( dimension == 1 && !glyph->do_vert_hints ) )
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = pos;
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_len = len;
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_hint_set_fitted( hint );
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return;
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* perform stem snapping when requested - this is necessary
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * for monochrome and LCD hinting modes only
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    ( dimension == 1 && glyph->do_vert_snapping );
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hint->cur_len = fit_len = len;
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check blue zones for horizontal stems */
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      align.align     = PSH_BLUE_ALIGN_NONE;
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      align.align_bot = align.align_top = 0;
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dimension == 1 )
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_blues_snap_stem( &globals->blues,
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hint->org_pos + hint->org_len,
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hint->org_pos,
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             &align );
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      switch ( align.align )
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case PSH_BLUE_ALIGN_TOP:
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the top of the stem is aligned against a blue zone */
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = align.align_top - fit_len;
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case PSH_BLUE_ALIGN_BOT:
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the bottom of the stem is aligned against a blue zone */
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = align.align_bot;
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* both edges of the stem are aligned against blue zones */
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = align.align_bot;
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_len = align.align_top - align.align_bot;
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      default:
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PSH_Hint  parent = hint->parent;
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( parent )
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  par_org_center, par_cur_center;
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  cur_org_center, cur_delta;
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* ensure that parent is already fitted */
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( !psh_hint_is_fitted( parent ) )
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_hint_align( parent, globals, dimension, glyph );
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* keep original relation between hints, this is, use the */
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* scaled distance between the centers of the hints to    */
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* compute the new position                               */
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            par_org_center = parent->org_pos + ( parent->org_len >> 1 );
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 );
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_org_center = hint->org_pos   + ( hint->org_len   >> 1 );
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pos       = par_cur_center + cur_delta - ( len >> 1 );
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint->cur_pos = pos;
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint->cur_len = fit_len;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* Stem adjustment tries to snap stem widths to standard
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * ones.  This is important to prevent unpleasant rounding
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * artefacts.
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           */
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( glyph->do_stem_adjust )
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( len <= 64 )
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* the stem is less than one pixel; we will center it
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               * around the nearest pixel center
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               */
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( len >= 32 )
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* This is a special case where we also widen the stem
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * and align it to the pixel grid.
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *   stem_center          = pos + (len/2)
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *   nearest_pixel_center = FT_ROUND(stem_center-32)+32
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *   new_pos              = nearest_pixel_center-32
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *                        = FT_ROUND(stem_center-32)
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *                        = FT_FLOOR(stem_center-32+32)
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *                        = FT_FLOOR(stem_center)
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *   new_len              = 64
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 */
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                pos = FT_PIX_FLOOR( pos + ( len >> 1 ) );
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                len = 64;
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              else if ( len > 0 )
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* This is a very small stem; we simply align it to the
565727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 * pixel grid, trying to find the minimum displacement.
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * left               = pos
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * right              = pos + len
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * left_nearest_edge  = ROUND(pos)
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * right_nearest_edge = ROUND(right)
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * if ( ABS(left_nearest_edge - left) <=
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *      ABS(right_nearest_edge - right) )
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *    new_pos = left
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 * else
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 *    new_pos = right
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 */
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Pos  left_nearest  = FT_PIX_ROUND( pos );
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Pos  right_nearest = FT_PIX_ROUND( pos + len );
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Pos  left_disp     = left_nearest - pos;
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Pos  right_disp    = right_nearest - ( pos + len );
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( left_disp < 0 )
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  left_disp = -left_disp;
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( right_disp < 0 )
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  right_disp = -right_disp;
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( left_disp <= right_disp )
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  pos = left_nearest;
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                else
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  pos = right_nearest;
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              else
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* this is a ghost stem; we simply round it */
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                pos = FT_PIX_ROUND( pos );
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              len = psh_dimension_quantize_len( dim, len, 0 );
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now that we have a good hinted stem width, try to position */
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* the stem along a pixel grid integer coordinate             */
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len );
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint->cur_len = len;
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( do_snapping )
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos = hint->cur_pos;
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        len = hint->cur_len;
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( len < 64 )
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len = 64;
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          len = FT_PIX_ROUND( len );
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        switch ( align.align )
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case PSH_BLUE_ALIGN_TOP:
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint->cur_pos = align.align_top - len;
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint->cur_len = len;
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case PSH_BLUE_ALIGN_BOT:
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint->cur_len = len;
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* don't touch */
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          default:
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint->cur_len = len;
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( len & 64 )
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32;
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              pos = FT_PIX_ROUND( pos + ( len >> 1 ) );
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint->cur_pos = pos - ( len >> 1 );
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            hint->cur_len = len;
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_hint_set_fitted( hint );
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ps_debug_hint_func )
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ps_debug_hint_func( hint, dimension );
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0  /* not used for now, experimental */
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  *  A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  *  of stems
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  */
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_align_light( PSH_Hint     hint,
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        PSH_Globals  globals,
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Int       dimension,
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        PSH_Glyph    glyph )
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension  dim   = &globals->dimension[dimension];
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       scale = dim->scale_mult;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       delta = dim->scale_delta;
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !psh_hint_is_fitted( hint ) )
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  len = FT_MulFix( hint->org_len, scale );
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  fit_len;
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_AlignmentRec  align;
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* ignore stem alignments when requested through the hint flags */
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( dimension == 1 && !glyph->do_vert_hints ) )
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = pos;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_len = len;
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_hint_set_fitted( hint );
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return;
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      fit_len = len;
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      hint->cur_len = fit_len;
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check blue zones for horizontal stems */
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      align.align = PSH_BLUE_ALIGN_NONE;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      align.align_bot = align.align_top = 0;
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dimension == 1 )
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_blues_snap_stem( &globals->blues,
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hint->org_pos + hint->org_len,
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hint->org_pos,
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             &align );
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      switch ( align.align )
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case PSH_BLUE_ALIGN_TOP:
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the top of the stem is aligned against a blue zone */
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = align.align_top - fit_len;
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case PSH_BLUE_ALIGN_BOT:
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the bottom of the stem is aligned against a blue zone */
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = align.align_bot;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* both edges of the stem are aligned against blue zones */
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_pos = align.align_bot;
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        hint->cur_len = align.align_top - align.align_bot;
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      default:
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PSH_Hint  parent = hint->parent;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( parent )
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  par_org_center, par_cur_center;
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  cur_org_center, cur_delta;
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* ensure that parent is already fitted */
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( !psh_hint_is_fitted( parent ) )
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_hint_align_light( parent, globals, dimension, glyph );
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            par_org_center = parent->org_pos + ( parent->org_len / 2 );
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_org_center = hint->org_pos   + ( hint->org_len   / 2 );
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pos       = par_cur_center + cur_delta - ( len >> 1 );
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* Stems less than one pixel wide are easy -- we want to
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * make them as dark as possible, so they must fall within
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * one pixel.  If the stem is split between two pixels
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * then snap the edge that is nearer to the pixel boundary
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * to the pixel boundary.
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           */
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( len <= 64 )
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ( pos + len + 63 ) / 64  != pos / 64 + 1 )
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              pos += psh_hint_snap_stem_side_delta ( pos, len );
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* Position stems other to minimize the amount of mid-grays.
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * There are, in general, two positions that do this,
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * illustrated as A) and B) below.
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           *
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           *   +                   +                   +                   +
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           *
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * A)             |--------------------------------|
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * B)   |--------------------------------|
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * C)       |--------------------------------|
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           *
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * Position A) (split the excess stem equally) should be better
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * for stems of width N + f where f < 0.5.
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           *
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * Position B) (split the deficiency equally) should be better
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * for stems of width N + f where f > 0.5.
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           *
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * It turns out though that minimizing the total number of lit
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * pixels is also important, so position C), with one edge
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * aligned with a pixel boundary is actually preferable
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * to A).  There are also more possibile positions for C) than
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * for A) or B), so it involves less distortion of the overall
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           * character shape.
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           */
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else /* len > 64 */
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Fixed  frac_len = len & 63;
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Fixed  center = pos + ( len >> 1 );
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Fixed  delta_a, delta_b;
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ( len / 64 ) & 1 )
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta_a = FT_PIX_FLOOR( center ) + 32 - center;
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta_b = FT_PIX_ROUND( center ) - center;
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta_a = FT_PIX_ROUND( center ) - center;
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta_b = FT_PIX_FLOOR( center ) + 32 - center;
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* We choose between B) and C) above based on the amount
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             * of fractinal stem width; for small amounts, choose
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             * C) always, for large amounts, B) always, and inbetween,
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             * pick whichever one involves less stem movement.
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             */
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( frac_len < 32 )
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              pos += psh_hint_snap_stem_side_delta ( pos, len );
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else if ( frac_len < 48 )
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Fixed  side_delta = psh_hint_snap_stem_side_delta ( pos,
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                                     len );
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) )
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                pos += side_delta;
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              else
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                pos += delta_b;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              pos += delta_b;
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          hint->cur_pos = pos;
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }  /* switch */
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_hint_set_fitted( hint );
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ps_debug_hint_func )
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ps_debug_hint_func( hint, dimension );
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_align_hints( PSH_Hint_Table  table,
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              PSH_Globals     globals,
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Int          dimension,
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              PSH_Glyph       glyph )
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Hint       hint;
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt        count;
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension  dim   = &globals->dimension[dimension];
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       scale = dim->scale_mult;
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       delta = dim->scale_delta;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ps_debug_no_vert_hints && dimension == 0 )
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ps_simple_scale( table, scale, delta, dimension );
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ps_debug_no_horz_hints && dimension == 1 )
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ps_simple_scale( table, scale, delta, dimension );
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_HINTER*/
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hint  = table->hints;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count = table->max_hints;
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, hint++ )
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_hint_align( hint, globals, dimension, glyph );
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                POINTS INTERPOLATION ROUTINES                  *****/
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_ZONE_MIN  -3200000L
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_ZONE_MAX  +3200000L
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define xxDEBUG_ZONES
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_ZONES
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
9010a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include FT_CONFIG_STANDARD_LIBRARY_H
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_print_zone( PSH_Zone  zone )
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             zone->scale / 65536.0,
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             zone->delta / 64.0,
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             zone->min,
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             zone->max );
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define psh_print_zone( x )  do { } while ( 0 )
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_ZONES */
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                    HINTER GLYPH MANAGEMENT                    *****/
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  psh_corner_is_flat      ft_corner_is_flat
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  psh_corner_orientation  ft_corner_orientation
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Int )
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_corner_is_flat( FT_Pos  x_in,
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Pos  y_in,
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Pos  x_out,
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Pos  y_out )
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  ax = x_in;
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  ay = y_in;
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  d_in, d_out, d_corner;
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ax < 0 )
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ax = -ax;
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ay < 0 )
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ay = -ay;
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d_in = ax + ay;
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ax = x_out;
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ax < 0 )
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ax = -ax;
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ay = y_out;
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ay < 0 )
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ay = -ay;
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d_out = ax + ay;
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ax = x_out + x_in;
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ax < 0 )
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ax = -ax;
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ay = y_out + y_in;
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ay < 0 )
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ay = -ay;
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d_corner = ax + ay;
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Int
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_corner_orientation( FT_Pos  in_x,
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Pos  in_y,
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Pos  out_x,
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_Pos  out_y )
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int  result;
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* deal with the trivial cases quickly */
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( in_y == 0 )
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( in_x >= 0 )
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = out_y;
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = -out_y;
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( in_x == 0 )
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( in_y >= 0 )
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = -out_x;
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = out_x;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( out_y == 0 )
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( out_x >= 0 )
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = in_y;
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = -in_y;
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( out_x == 0 )
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( out_y >= 0 )
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = -in_x;
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result =  in_x;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else /* general case */
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      long long  delta = (long long)in_x * out_y - (long long)in_y * out_x;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( delta == 0 )
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = 0;
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = 1 - 2 * ( delta < 0 );
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* !1 */
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef COMPUTE_INFLEXS
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compute all inflex points in a given glyph */
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_compute_inflections( PSH_Glyph  glyph )
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  n;
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < glyph->num_contours; n++ )
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  first, start, end, before, after;
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos     in_x, in_y, out_x, out_y;
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int     orient_prev, orient_cur;
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int     finished = 0;
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we need at least 4 points to create an inflection point */
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph->contours[n].count < 4 )
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute first segment in contour */
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = glyph->contours[n].start;
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = end = first;
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end = end->next;
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( end == first )
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Skip;
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        in_x = end->org_u - start->org_u;
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        in_y = end->org_v - start->org_v;
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( in_x == 0 && in_y == 0 );
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* extend the segment start whenever possible */
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      before = start;
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          start  = before;
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          before = before->prev;
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( before == first )
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Skip;
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          out_x = start->org_u - before->org_u;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          out_y = start->org_v - before->org_v;
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( out_x == 0 && out_y == 0 );
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y );
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( orient_prev == 0 );
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = start;
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      in_x  = out_x;
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      in_y  = out_y;
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now, process all segments in the contour */
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* first, extend current segment's end whenever possible */
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        after = end;
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end   = after;
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            after = after->next;
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( after == first )
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              finished = 1;
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            out_x = after->org_u - end->org_u;
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            out_y = after->org_v - end->org_v;
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( out_x == 0 && out_y == 0 );
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y );
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( orient_cur == 0 );
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ( orient_cur ^ orient_prev ) < 0 )
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            psh_point_set_inflex( start );
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start = start->next;
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          while ( start != end );
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          psh_point_set_inflex( start );
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start       = end;
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end         = after;
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        orient_prev = orient_cur;
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        in_x        = out_x;
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        in_y        = out_y;
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( !finished );
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Skip:
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* COMPUTE_INFLEXS */
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_done( PSH_Glyph  glyph )
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = glyph->memory;
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_hint_table_done( &glyph->hint_tables[1], memory );
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_hint_table_done( &glyph->hint_tables[0], memory );
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( glyph->points );
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( glyph->contours );
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->num_points   = 0;
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->num_contours = 0;
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->memory = 0;
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_compute_dir( FT_Pos  dx,
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Pos  dy )
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  ax, ay;
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     result = PSH_DIR_NONE;
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    ax = FT_ABS( dx );
1165727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    ay = FT_ABS( dy );
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ay * 12 < ax )
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* |dy| <<< |dx|  means a near-horizontal segment */
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT;
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( ax * 12 < ay )
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* |dx| <<< |dy|  means a near-vertical segment */
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* load outline point coordinates into hinter glyph */
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_load_points( PSH_Glyph  glyph,
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Int     dimension )
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec   = glyph->outline->points;
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point   point = glyph->points;
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     count = glyph->num_points;
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, point++, vec++ )
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point->flags2 = 0;
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point->hint   = NULL;
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dimension == 0 )
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->org_u = vec->x;
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->org_v = vec->y;
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->org_u = vec->y;
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->org_v = vec->x;
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point->org_x = vec->x;
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point->org_y = vec->y;
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* save hinted point coordinates back to outline */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_save_points( PSH_Glyph  glyph,
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Int     dimension )
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     n;
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point   point = glyph->points;
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  vec   = glyph->outline->points;
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tags  = glyph->outline->tags;
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < glyph->num_points; n++ )
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dimension == 0 )
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        vec[n].x = point->cur_u;
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        vec[n].y = point->cur_u;
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_strong( point ) )
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dimension == 0 )
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->cur_x   = point->cur_u;
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->flags_x = point->flags2 | point->flags;
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->cur_y   = point->cur_u;
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->flags_y = point->flags2 | point->flags;
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point++;
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_init( PSH_Glyph    glyph,
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Outline*  outline,
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  PS_Hints     ps_hints,
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  PSH_Globals  globals )
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error   error;
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory;
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* clear all fields */
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MEM_ZERO( glyph, sizeof ( *glyph ) );
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    memory = glyph->memory = globals->memory;
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* allocate and setup points + contours arrays */
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( glyph->points,   outline->n_points   ) ||
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->num_points   = outline->n_points;
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->num_contours = outline->n_contours;
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt      first = 0, next, n;
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point    points  = glyph->points;
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Contour  contour = glyph->contours;
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < glyph->num_contours; n++ )
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int     count;
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        PSH_Point  point;
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next  = outline->contours[n] + 1;
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        count = next - first;
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        contour->start = points + first;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        contour->count = (FT_UInt)count;
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( count > 0 )
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = points + first;
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->prev    = points + next - 1;
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->contour = contour;
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; count > 1; count-- )
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point[0].next = point + 1;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point[1].prev = point;
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point++;
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->contour = contour;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->next = points + first;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        contour++;
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = next;
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point   points = glyph->points;
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point   point  = points;
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Vector*  vec    = outline->points;
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     n;
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < glyph->num_points; n++, point++ )
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  n_prev = (FT_Int)( point->prev - points );
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  n_next = (FT_Int)( point->next - points );
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  dxi, dyi, dxo, dyo;
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags = PSH_POINT_OFF;
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dxi = vec[n].x - vec[n_prev].x;
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dyi = vec[n].y - vec[n_prev].y;
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dxo = vec[n_next].x - vec[n].x;
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dyo = vec[n_next].y - vec[n].y;
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* detect smooth points */
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags & PSH_POINT_OFF )
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->flags |= PSH_POINT_SMOOTH;
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( point->dir_in == point->dir_out )
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->dir_out != PSH_DIR_NONE           ||
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               psh_corner_is_flat( dxi, dyi, dxo, dyo ) )
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->flags |= PSH_POINT_SMOOTH;
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->outline = outline;
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph->globals = globals;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef COMPUTE_INFLEXS
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_glyph_load_points( glyph, 0 );
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_glyph_compute_inflections( glyph );
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* COMPUTE_INFLEXS */
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now deal with hints tables */
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = psh_hint_table_init( &glyph->hint_tables [0],
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 &ps_hints->dimension[0].hints,
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 &ps_hints->dimension[0].masks,
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 &ps_hints->dimension[0].counters,
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 memory );
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = psh_hint_table_init( &glyph->hint_tables [1],
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 &ps_hints->dimension[1].hints,
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 &ps_hints->dimension[1].masks,
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 &ps_hints->dimension[1].counters,
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 memory );
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compute all extrema in a glyph for a given dimension */
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_compute_extrema( PSH_Glyph  glyph )
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  n;
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, compute all local extrema */
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < glyph->num_contours; n++ )
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  first = glyph->contours[n].start;
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  point, before, after;
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph->contours[n].count == 0 )
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point  = first;
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      before = point;
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        before = before->prev;
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( before == first )
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Skip;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( before->org_u == point->org_u );
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = point = before->next;
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        after = point;
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          after = after->next;
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( after == first )
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Next;
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( after->org_u == point->org_u );
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( before->org_u < point->org_u )
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( after->org_u < point->org_u )
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* local maximum */
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Extremum;
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else /* before->org_u > point->org_u */
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( after->org_u > point->org_u )
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* local minimum */
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          Extremum:
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            do
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_point_set_extremum( point );
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point = point->next;
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            } while ( point != after );
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        before = after->prev;
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point  = after;
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } /* for  */
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Next:
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* for each extremum, determine its direction along the */
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* orthogonal axis                                      */
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < glyph->num_points; n++ )
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  point, before, after;
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point  = &glyph->points[n];
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      before = point;
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      after  = point;
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_extremum( point ) )
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          before = before->prev;
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( before == point )
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Skip;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( before->org_v == point->org_v );
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          after = after->next;
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( after == point )
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Skip;
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( after->org_v == point->org_v );
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( before->org_v < point->org_v &&
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           after->org_v  > point->org_v )
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_point_set_positive( point );
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( before->org_v > point->org_v &&
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                after->org_v  < point->org_v )
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_point_set_negative( point );
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Skip:
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* major_dir is the direction for points on the bottom/left of the stem; */
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Points on the top/right of the stem will have a direction of          */
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* -major_dir.                                                           */
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_hint_table_find_strong_points( PSH_Hint_Table  table,
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     PSH_Point       point,
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_UInt         count,
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_Int          threshold,
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_Int          major_dir )
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Hint*  sort      = table->sort;
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    num_hints = table->num_hints;
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, point++ )
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int  point_dir = 0;
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  org_u     = point->org_u;
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_strong( point ) )
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point_dir = point->dir_in;
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point_dir = point->dir_out;
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point_dir )
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point_dir == major_dir )
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  nn;
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < num_hints; nn++ )
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            PSH_Hint  hint = sort[nn];
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos    d    = org_u - hint->org_pos;
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( d < threshold && -d < threshold )
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_point_set_strong( point );
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->flags2 |= PSH_POINT_EDGE_MIN;
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->hint    = hint;
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( point_dir == -major_dir )
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  nn;
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < num_hints; nn++ )
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            PSH_Hint  hint = sort[nn];
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos    d    = org_u - hint->org_pos - hint->org_len;
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( d < threshold && -d < threshold )
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_point_set_strong( point );
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->flags2 |= PSH_POINT_EDGE_MAX;
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->hint    = hint;
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( psh_point_is_extremum( point ) )
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* treat extrema as special cases for stem edge alignment */
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt  nn, min_flag, max_flag;
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( major_dir == PSH_DIR_HORIZONTAL )
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min_flag = PSH_POINT_POSITIVE;
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max_flag = PSH_POINT_NEGATIVE;
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min_flag = PSH_POINT_NEGATIVE;
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max_flag = PSH_POINT_POSITIVE;
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->flags2 & min_flag )
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < num_hints; nn++ )
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            PSH_Hint  hint = sort[nn];
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos    d    = org_u - hint->org_pos;
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( d < threshold && -d < threshold )
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->flags2 |= PSH_POINT_EDGE_MIN;
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->hint    = hint;
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_point_set_strong( point );
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( point->flags2 & max_flag )
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < num_hints; nn++ )
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            PSH_Hint  hint = sort[nn];
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos    d    = org_u - hint->org_pos - hint->org_len;
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( d < threshold && -d < threshold )
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->flags2 |= PSH_POINT_EDGE_MAX;
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->hint    = hint;
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              psh_point_set_strong( point );
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->hint == NULL )
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < num_hints; nn++ )
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            PSH_Hint  hint = sort[nn];
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( org_u >= hint->org_pos                 &&
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                org_u <= hint->org_pos + hint->org_len )
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->hint = hint;
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 1 */
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* the accepted shift for strong points in fractional pixels */
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_STRONG_THRESHOLD  32
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* the maximum shift value in font units */
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_STRONG_THRESHOLD_MAXIMUM  30
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* find strong points in a glyph */
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_find_strong_points( PSH_Glyph  glyph,
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_Int     dimension )
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* a point is `strong' if it is located on a stem edge and       */
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* has an `in' or `out' tangent parallel to the hint's direction */
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Hint_Table  table     = &glyph->hint_tables[dimension];
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PS_Mask         mask      = table->hint_masks->masks;
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt         num_masks = table->hint_masks->num_masks;
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt         first     = 0;
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int          major_dir = dimension == 0 ? PSH_DIR_VERTICAL
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               : PSH_DIR_HORIZONTAL;
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension   dim       = &glyph->globals->dimension[dimension];
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed        scale     = dim->scale_mult;
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int          threshold;
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale );
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM )
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      threshold = PSH_STRONG_THRESHOLD_MAXIMUM;
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* process secondary hints to `selected' points */
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_masks > 1 && glyph->num_points > 0 )
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1692aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      /* the `endchar' op can reduce the number of points */
1693aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      first = mask->end_point > glyph->num_points
1694aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                ? glyph->num_points
1695aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                : mask->end_point;
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mask++;
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; num_masks > 1; num_masks--, mask++ )
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt  next;
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int   count;
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1703aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        next  = mask->end_point > glyph->num_points
1704aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                  ? glyph->num_points
1705aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                  : mask->end_point;
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        count = next - first;
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( count > 0 )
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PSH_Point  point = glyph->points + first;
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          psh_hint_table_activate_mask( table, mask );
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          psh_hint_table_find_strong_points( table, point, count,
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             threshold, major_dir );
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = next;
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* process primary hints for all points */
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_masks == 1 )
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    count = glyph->num_points;
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  point = glyph->points;
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_hint_table_activate_mask( table, table->hint_masks->masks );
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_hint_table_find_strong_points( table, point, count,
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         threshold, major_dir );
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now, certain points may have been attached to a hint and */
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* not marked as strong; update their flags then            */
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    count = glyph->num_points;
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  point = glyph->points;
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count--, point++ )
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->hint && !psh_point_is_strong( point ) )
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          psh_point_set_strong( point );
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* find points in a glyph which are in a blue zone and have `in' or */
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `out' tangents parallel to the horizontal axis                   */
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_find_blue_points( PSH_Blues  blues,
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              PSH_Glyph  glyph )
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Blue_Table  table;
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Blue_Zone   zone;
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt         glyph_count = glyph->num_points;
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt         blue_count;
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point       point = glyph->points;
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; glyph_count > 0; glyph_count--, point++ )
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  y;
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check tangents */
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !PSH_DIR_COMPARE( point->dir_in,  PSH_DIR_HORIZONTAL ) &&
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) )
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip strong points */
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_strong( point ) )
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      y = point->org_u;
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* look up top zones */
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      table      = &blues->normal_top;
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_count = table->count;
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      zone       = table->zones;
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; blue_count > 0; blue_count--, zone++ )
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta = y - zone->org_bottom;
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < -blues->blue_fuzz )
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( y <= zone->org_top + blues->blue_fuzz )
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( blues->no_overshoots || delta <= blues->blue_threshold )
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = zone->cur_bottom;
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            psh_point_set_strong( point );
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            psh_point_set_fitted( point );
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* look up bottom zones */
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      table      = &blues->normal_bottom;
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_count = table->count;
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      zone       = table->zones + blue_count - 1;
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; blue_count > 0; blue_count--, zone-- )
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta = zone->org_top - y;
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < -blues->blue_fuzz )
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( y >= zone->org_bottom - blues->blue_fuzz )
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( blues->no_overshoots || delta < blues->blue_threshold )
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = zone->cur_top;
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            psh_point_set_strong( point );
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            psh_point_set_fitted( point );
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* interpolate strong points with the help of hinted coordinates */
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_interpolate_strong_points( PSH_Glyph  glyph,
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                       FT_Int     dimension )
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension  dim   = &glyph->globals->dimension[dimension];
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       scale = dim->scale_mult;
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt        count = glyph->num_points;
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point      point = glyph->points;
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, point++ )
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Hint  hint = point->hint;
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( hint )
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( psh_point_is_edge_min( point ) )
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->cur_u = hint->cur_pos;
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( psh_point_is_edge_max( point ) )
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->cur_u = hint->cur_pos + hint->cur_len;
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = point->org_u - hint->org_pos;
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta <= 0 )
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta >= hint->org_len )
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = hint->cur_pos + hint->cur_len +
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_MulFix( delta - hint->org_len, scale );
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18637f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner          else /* hint->org_len > 0 */
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = hint->cur_pos +
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_MulDiv( delta, hint->cur_len,
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        hint->org_len );
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_point_set_fitted( point );
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  PSH_MAX_STRONG_INTERNAL  16
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_interpolate_normal_points( PSH_Glyph  glyph,
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                       FT_Int     dimension )
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first technique: a point is strong if it is a local extremum */
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension  dim    = &glyph->globals->dimension[dimension];
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       scale  = dim->scale_mult;
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory      memory = glyph->memory;
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point*     strongs     = NULL;
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point      strongs_0[PSH_MAX_STRONG_INTERNAL];
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt        num_strongs = 0;
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point      points = glyph->points;
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point      points_end = points + glyph->num_points;
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Point      point;
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first count the number of strong points */
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( point = points; point < points_end; point++ )
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_strong( point ) )
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        num_strongs++;
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_strongs == 0 )  /* nothing to do here */
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* allocate an array to store a list of points, */
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* stored in increasing org_u order             */
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      strongs = strongs_0;
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Error  error;
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW_ARRAY( strongs, num_strongs ) )
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return;
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_strongs = 0;
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( point = points; point < points_end; point++ )
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point*  insert;
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !psh_point_is_strong( point ) )
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( insert = strongs + num_strongs; insert > strongs; insert-- )
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( insert[-1]->org_u <= point->org_u )
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        insert[0] = insert[-1];
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      insert[0] = point;
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_strongs++;
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now try to interpolate all normal points */
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( point = points; point < points_end; point++ )
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_strong( point ) )
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* sometimes, some local extrema are smooth points */
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( psh_point_is_smooth( point ) )
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->dir_in == PSH_DIR_NONE   ||
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             point->dir_in != point->dir_out )
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !psh_point_is_extremum( point ) &&
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             !psh_point_is_inflex( point )   )
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->flags &= ~PSH_POINT_SMOOTH;
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* find best enclosing point coordinates then interpolate */
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        PSH_Point   before, after;
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt     nn;
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( nn = 0; nn < num_strongs; nn++ )
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( strongs[nn]->org_u > point->org_u )
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( nn == 0 )  /* point before the first strong point */
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          after = strongs[0];
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point->cur_u = after->cur_u +
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_MulFix( point->org_u - after->org_u,
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      scale );
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          before = strongs[nn - 1];
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = num_strongs; nn > 0; nn-- )
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( strongs[nn - 1]->org_u < point->org_u )
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( nn == num_strongs )  /* point is after last strong point */
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            before = strongs[nn - 1];
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = before->cur_u +
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_MulFix( point->org_u - before->org_u,
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        scale );
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  u;
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            after = strongs[nn];
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* now interpolate point between before and after */
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            u = point->org_u;
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( u == before->org_u )
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->cur_u = before->cur_u;
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else if ( u == after->org_u )
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->cur_u = after->cur_u;
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              point->cur_u = before->cur_u +
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_MulDiv( u - before->org_u,
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          after->cur_u - before->cur_u,
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          after->org_u - before->org_u );
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_point_set_fitted( point );
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( strongs != strongs_0 )
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( strongs );
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 1 */
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* interpolate other points */
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  psh_glyph_interpolate_other_points( PSH_Glyph  glyph,
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      FT_Int     dimension )
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Dimension  dim          = &glyph->globals->dimension[dimension];
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       scale        = dim->scale_mult;
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed       delta        = dim->scale_delta;
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Contour    contour      = glyph->contours;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt        num_contours = glyph->num_contours;
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_contours > 0; num_contours--, contour++ )
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  start = contour->start;
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Point  first, next, point;
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    fit_count;
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* count the number of strong points in this contour */
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next      = start + contour->count;
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      fit_count = 0;
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first     = 0;
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( point = start; point < next; point++ )
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( psh_point_is_fitted( point ) )
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( !first )
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            first = point;
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fit_count++;
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if there are less than 2 fitted points in the contour, we */
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* simply scale and eventually translate the contour points  */
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( fit_count < 2 )
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( fit_count == 1 )
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = first->cur_u - FT_MulFix( first->org_u, scale );
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( point = start; point < next; point++ )
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point != first )
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Next_Contour;
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* there are more than 2 strong points in this contour; we */
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* need to interpolate weak points between them            */
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = first;
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* skip consecutive fitted points */
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          next = first->next;
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( next == start )
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Next_Contour;
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( !psh_point_is_fitted( next ) )
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          first = next;
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* find next fitted point after unfitted one */
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          next = next->next;
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( psh_point_is_fitted( next ) )
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now interpolate between them */
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos    org_a, org_ab, cur_a, cur_ab;
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos    org_c, org_ac, cur_c;
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Fixed  scale_ab;
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( first->org_u <= next->org_u )
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            org_a  = first->org_u;
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_a  = first->cur_u;
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            org_ab = next->org_u - org_a;
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_ab = next->cur_u - cur_a;
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            org_a  = next->org_u;
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_a  = next->cur_u;
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            org_ab = first->org_u - org_a;
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_ab = first->cur_u - cur_a;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scale_ab = 0x10000L;
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( org_ab > 0 )
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            scale_ab = FT_DivFix( cur_ab, org_ab );
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = first->next;
2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            org_c  = point->org_u;
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            org_ac = org_c - org_a;
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( org_ac <= 0 )
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* on the left of the interpolation zone */
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cur_c = cur_a + FT_MulFix( org_ac, scale );
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else if ( org_ac >= org_ab )
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* on the right on the interpolation zone */
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* within the interpolation zone */
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point->cur_u = cur_c;
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point = point->next;
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( point != next );
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* keep going until all points in the contours have been processed */
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = next;
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( first != start );
2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Next_Contour:
2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                     HIGH-LEVEL INTERFACE                      *****/
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Error
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ps_hints_apply( PS_Hints        ps_hints,
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Outline*     outline,
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  PSH_Globals     globals,
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Render_Mode  hint_mode )
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_GlyphRec  glyphrec;
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PSH_Glyph     glyph = &glyphrec;
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory;
2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        dimension;
2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* something to do? */
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points == 0 || outline->n_contours == 0 )
2193727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_Err_Ok;
2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    memory = globals->memory;
2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ps_debug_glyph )
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      psh_glyph_done( ps_debug_glyph );
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( ps_debug_glyph );
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW( glyph ) )
2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return error;
2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ps_debug_glyph = glyph;
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_HINTER */
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = psh_glyph_init( glyph, outline, ps_hints, globals );
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* try to optimize the y_scale so that the top of non-capital letters
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * is aligned on a pixel boundary whenever possible
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Dimension  dim_x = &glyph->globals->dimension[0];
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PSH_Dimension  dim_y = &glyph->globals->dimension[1];
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  x_scale = dim_x->scale_mult;
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  y_scale = dim_y->scale_mult;
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  old_x_scale = x_scale;
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  old_y_scale = y_scale;
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  scaled;
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  fitted;
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Bool  rescale = FALSE;
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      fitted = FT_PIX_ROUND( scaled );
2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( fitted != 0 && scaled != fitted )
2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rescale = TRUE;
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        y_scale = FT_MulDiv( y_scale, fitted, scaled );
2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( fitted < scaled )
2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          x_scale -= x_scale / 50;
2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph->do_horz_hints = 1;
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph->do_vert_hints = 1;
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         hint_mode == FT_RENDER_MODE_LCD  );
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO  ||
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         hint_mode == FT_RENDER_MODE_LCD_V );
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph->do_stem_adjust   = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dimension = 0; dimension < 2; dimension++ )
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* load outline coordinates into glyph */
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_load_points( glyph, dimension );
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* compute local extrema */
2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_compute_extrema( glyph );
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* compute aligned stem/hints positions */
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_hint_table_align_hints( &glyph->hint_tables[dimension],
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    glyph->globals,
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    dimension,
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    glyph );
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* find strong points, align them, then interpolate others */
2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_find_strong_points( glyph, dimension );
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dimension == 1 )
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          psh_glyph_find_blue_points( &globals->blues, glyph );
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_interpolate_strong_points( glyph, dimension );
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_interpolate_normal_points( glyph, dimension );
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_interpolate_other_points( glyph, dimension );
2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* save hinted coordinates back to outline */
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        psh_glyph_save_points( glyph, dimension );
2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( rescale )
2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          psh_globals_set_scale( glyph->globals,
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 old_x_scale, old_y_scale, 0, 0 );
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef DEBUG_HINTER
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    psh_glyph_done( glyph );
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
2303