1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner/*  aflatin2.c                                                             */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
59c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*    Auto-fitter hinting routines for latin writing system (body).        */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  Copyright 2003-2013 by                                                 */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include FT_ADVANCES_H
20295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
21727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "afglobal.h"
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin.h"
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin2.h"
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h"
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afwarp.h"
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
32aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*************************************************************************/
33aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                       */
34aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
35aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
36aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* messages during execution.                                            */
37aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                       */
38aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#undef  FT_COMPONENT
39aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#define FT_COMPONENT  trace_aflatin2
40aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
41aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
44aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                    AF_Dimension   dim );
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_link_segments( AF_GlyphHints  hints,
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 AF_Dimension   dim );
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  /*****            L A T I N   G L O B A L   M E T R I C S            *****/
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
60727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                 FT_Face          face )
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scan the array of segments in each direction */
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_GlyphHintsRec  hints[1];
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_init( hints, face->memory );
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->axis[AF_DIMENSION_VERT].width_count = 0;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Error             error;
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt              glyph_index;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      int                  dim;
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinMetricsRec   dummy[1];
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Scaler            scaler = &dummy->root.scaler;
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      glyph_index = FT_Get_Char_Index(
80ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                      face,
819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                      metrics->root.style_class->standard_char );
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph_index == 0 )
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error || face->glyph->outline.n_points <= 0 )
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ZERO( dummy );
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dummy->units_per_em = metrics->units_per_em;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->x_scale     = scaler->y_scale = 0x10000L;
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->x_delta     = scaler->y_delta = 0;
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->face        = face;
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->render_mode = FT_RENDER_MODE_NORMAL;
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->flags       = 0;
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
100aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      error = af_glyph_hints_reload( hints, &face->glyph->outline );
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinAxis  axis    = &metrics->axis[dim];
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_AxisHints  axhints = &hints->axis[dim];
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Segment    seg, limit, link;
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt       num_widths = 0;
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_latin2_hints_compute_segments( hints,
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                 (AF_Dimension)dim );
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_hints_link_segments( hints,
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      (AF_Dimension)dim );
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg   = axhints->segments;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        limit = seg + axhints->num_segments;
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; seg < limit; seg++ )
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          link = seg->link;
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* we only consider stem segments there! */
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( link && link->link == seg && link > seg )
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  dist;
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = seg->pos - link->pos;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 0 )
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = -dist;
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( num_widths < AF_LATIN_MAX_WIDTHS )
13841371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier              axis->widths[num_widths++].org = dist;
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_sort_widths( num_widths, axis->widths );
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->width_count = num_widths;
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinAxis  axis = &metrics->axis[dim];
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        stdw;
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        stdw = ( axis->width_count > 0 )
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 ? axis->widths[0].org
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 : AF_LATIN_CONSTANT( metrics, 50 );
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* let's try 20% of the smallest width */
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->edge_distance_threshold = stdw / 5;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->standard_width          = stdw;
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->extra_light             = 0;
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_done( hints );
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LATIN_MAX_TEST_CHARACTERS  12
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
172aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
173aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                        [AF_LATIN_MAX_TEST_CHARACTERS+1] =
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "THEZOCQS",
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "HEZLOCUS",
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "fijkdbh",
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "xzroesc",
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "xzroesc",
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "pqgjy"
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init_blues( AF_LatinMetrics  metrics,
186aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                FT_Face          face )
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_flats;
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_rounds;
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        bb;
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinBlue  blue;
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_GlyphSlot  glyph = face->glyph;
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
199aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* we compute the blues simply by loading each character from the     */
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
201aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
203727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_TRACE5(( "blue zones computation\n"
204727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                "======================\n\n" ));
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  p     = af_latin2_blue_chars[bb];
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_ref;
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_shoot;
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
214727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_TRACE5(( "blue zone %d:\n", bb ));
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_flats  = 0;
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_rounds = 0;
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; p < limit && *p; p++ )
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt     glyph_index;
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int      best_point, best_y, best_first, best_last;
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  points;
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool     round;
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* load the character in the face -- skip unknown or empty ones */
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( glyph_index == 0 )
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error || glyph->outline.n_points <= 0 )
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now compute min or max point indices and coordinates */
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = glyph->outline.points;
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_point  = -1;
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_y      = 0;  /* make compiler happy */
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_first  = 0;  /* ditto */
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_last   = 0;  /* ditto */
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  nn;
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  first = 0;
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  last  = -1;
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  old_best_point = best_point;
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  pp;
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            last = glyph->outline.contours[nn];
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* Avoid single-point contours since they are never rasterized. */
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* In some fonts, they correspond to mark attachment points     */
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* which are way outside of the glyph's real outline.           */
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( last == first )
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                continue;
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( AF_LATIN_IS_TOP_BLUE( bb ) )
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              for ( pp = first; pp <= last; pp++ )
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( best_point < 0 || points[pp].y > best_y )
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                {
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_point = pp;
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_y     = points[pp].y;
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                }
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              for ( pp = first; pp <= last; pp++ )
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( best_point < 0 || points[pp].y < best_y )
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                {
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_point = pp;
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_y     = points[pp].y;
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                }
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( best_point != old_best_point )
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              best_first = first;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              best_last  = last;
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
288727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          FT_TRACE5(( "  %c  %d", *p, best_y ));
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now check whether the point belongs to a straight or round   */
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* segment; we first need to find in which contour the extremum */
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* lies, then inspect its previous and next points              */
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
295727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          FT_Pos  best_x = points[best_point].x;
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  start, end, prev, next;
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist;
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now look for the previous and next points that are not on the */
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* same Y coordinate.  Threshold the `closeness'...              */
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          start = end = best_point;
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
306727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            prev = start - 1;
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( prev < best_first )
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              prev = best_last;
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
310727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            dist = FT_ABS( points[prev].y - best_y );
311727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            /* accept a small distance or a small angle (both values are */
312727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
313727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            if ( dist > 5 )
314727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
315727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                break;
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start = prev;
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( start != best_point );
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
323727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            next = end + 1;
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( next > best_last )
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next = best_first;
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
327727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            dist = FT_ABS( points[next].y - best_y );
328727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            if ( dist > 5 )
329727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
330727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                break;
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end = next;
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( end != best_point );
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now, set the `round' flag depending on the segment's kind */
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          round = FT_BOOL(
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
341727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( round )
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rounds[num_rounds++] = best_y;
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          flats[num_flats++]   = best_y;
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 && num_rounds == 0 )
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we couldn't find a single glyph to compute this blue zone,
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we will simply ignore it then
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         */
356727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_TRACE5(( "  empty\n" ));
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we have computed the contents of the `rounds' and `flats' tables, */
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now determine the reference and overshoot position of the blue -- */
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we simply take the median value after a simple sort               */
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_rounds, rounds );
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_flats,  flats );
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue       = & axis->blues[axis->blue_count];
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_ref   = & blue->ref.org;
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_shoot = & blue->shoot.org;
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->blue_count++;
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 )
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( num_rounds == 0 )
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = flats[num_flats / 2];
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   = flats[num_flats / 2];
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* there are sometimes problems: if the overshoot position of top     */
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones is under its reference position, or the opposite for bottom  */
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones.  We must thus check everything there and correct the errors */
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *blue_shoot != *blue_ref )
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   ref      = *blue_ref;
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   shoot    = *blue_shoot;
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool  over_ref = FT_BOOL( shoot > ref );
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
399727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        {
400727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          *blue_ref   =
401727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          *blue_shoot = ( shoot + ref ) / 2;
402727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
403727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          FT_TRACE5(( "  [overshoot smaller than reference,"
404727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                      " taking mean value]\n" ));
405727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        }
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue->flags = 0;
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( AF_LATIN_IS_TOP_BLUE( bb ) )
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags |= AF_LATIN_BLUE_TOP;
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
413ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease       * The following flag is used later to adjust the y and x scales
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * in order to optimize the pixel grid alignment of the top of small
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * letters.
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
417ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) )
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
420727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_TRACE5(( "    -> reference = %ld\n"
421727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  "       overshoot = %ld\n",
422727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  *blue_ref, *blue_shoot ));
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return;
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
429295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_LOCAL_DEF( void )
430295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  af_latin2_metrics_check_digits( AF_LatinMetrics  metrics,
431295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                  FT_Face          face )
432295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
433295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   i;
434295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Bool   started = 0, same_width = 1;
435295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Fixed  advance, old_advance = 0;
436295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
437295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
438295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* check whether all ASCII digits have the same advance width; */
439295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* digit `0' is 0x30 in all supported charmaps                 */
440295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    for ( i = 0x30; i <= 0x39; i++ )
441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
442295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_UInt  glyph_index;
443295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
444295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
445295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      glyph_index = FT_Get_Char_Index( face, i );
446295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( glyph_index == 0 )
447295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
448295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
449295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( FT_Get_Advance( face, glyph_index,
450295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_SCALE         |
451295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_HINTING       |
452295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_IGNORE_TRANSFORM,
453295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           &advance ) )
454295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
455295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
456295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( started )
457295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
458295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( advance != old_advance )
459295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
460295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          same_width = 0;
461295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          break;
462295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
463295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
464295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
465295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
466295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        old_advance = advance;
467295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        started     = 1;
468295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
469295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
470295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
471295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    metrics->root.digits_have_same_width = same_width;
472295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
473295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
474295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init( AF_LatinMetrics  metrics,
477aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                          FT_Face          face )
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
479727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error    error  = FT_Err_Ok;
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CharMap  oldmap = face->charmap;
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     ee;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Encoding  latin_encodings[] =
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_UNICODE,
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_APPLE_ROMAN,
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_STANDARD,
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_LATIN_1,
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_NONE  /* end of list */
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->units_per_em = face->units_per_EM;
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do we have a latin charmap in there? */
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Select_Charmap( face, latin_encodings[ee] );
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !error )
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
505727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      af_latin2_metrics_init_widths( metrics, face );
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_metrics_init_blues( metrics, face );
507295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      af_latin2_metrics_check_digits( metrics, face );
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Set_Charmap( face, oldmap );
511727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_scale_dim( AF_LatinMetrics  metrics,
517aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Scaler        scaler,
518aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Dimension     dim )
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        delta;
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt       nn;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->x_scale;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->x_delta;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->y_scale;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->y_delta;
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis = &metrics->axis[dim];
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( axis->org_scale == scale && axis->org_delta == delta )
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_scale = scale;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_delta = delta;
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * correct Y scale to optimize the alignment of the top of small
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * letters to the pixel grid
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinAxis  vaxis = &metrics->axis[AF_DIMENSION_VERT];
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinBlue  blue = NULL;
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < vaxis->blue_count; nn++ )
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue = &vaxis->blues[nn];
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( blue )
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
566727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_Pos   scaled;
567727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_Pos   threshold;
568727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_Pos   fitted;
569727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_UInt  limit;
570727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_UInt  ppem;
571727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
572727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
573727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
574727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
575727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        limit     = metrics->root.globals->increase_x_height;
576727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        threshold = 40;
577727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
578727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        /* if the `increase-x-height' property is active, */
579727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        /* we round up much more often                    */
580727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        if ( limit                                 &&
581727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease             ppem <= limit                         &&
582727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease             ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
583727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          threshold = 52;
584727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
585727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        fitted = ( scaled + threshold ) & ~63;
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
588aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( scaled != fitted )
589aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scale = FT_MulDiv( scale, fitted, scaled );
591aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "== scaled x-top = %.2g"
592aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      "  fitted = %.2g, scaling = %.4g\n",
593aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      scaled / 64.0, fitted / 64.0,
594aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      ( fitted * 1.0 ) / scaled ));
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->scale = scale;
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->delta = delta;
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_scale = scale;
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_delta = delta;
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_scale = scale;
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_delta = delta;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scale the standard widths */
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < axis->width_count; nn++ )
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  width = axis->widths + nn;
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->cur = FT_MulFix( width->org, scale );
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->fit = width->cur;
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* an extra-light axis corresponds to a standard width that is */
625aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* smaller than 5/8 pixels                                     */
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->extra_light =
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* scale the blue zones */
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < axis->blue_count; nn++ )
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = &axis->blues[nn];
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        dist;
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.fit   = blue->ref.cur;
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.fit = blue->shoot.cur;
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a blue zone is only active if it is less than 3/4 pixels tall */
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist <= 48 && dist >= -48 )
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  delta1, delta2;
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta1 = blue->shoot.org - blue->ref.org;
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = delta1;
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = FT_MulFix( delta2, scale );
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta2 < 32 )
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 0;
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta2 < 64 )
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = FT_PIX_ROUND( delta2 );
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->shoot.fit = blue->ref.fit + delta2;
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
670aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( ">> activating blue zone %d:"
671aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      "  ref.cur=%.2g ref.fit=%.2g"
672aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      "  shoot.cur=%.2g shoot.fit=%.2g\n",
673aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
674aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->flags |= AF_LATIN_BLUE_ACTIVE;
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_scale( AF_LatinMetrics  metrics,
685aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                           AF_Scaler        scaler )
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.render_mode = scaler->render_mode;
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.face        = scaler->face;
689727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    metrics->root.scaler.flags       = scaler->flags;
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****           L A T I N   G L Y P H   A N A L Y S I S             *****/
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  SORT_SEGMENTS
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
708aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                    AF_Dimension   dim )
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory        = hints->memory;
712727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error      error         = FT_Err_Ok;
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment       = NULL;
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SegmentRec seg0;
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour       = hints->contours;
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour_limit = contour + hints->num_contours;
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  major_dir, segment_dir;
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ZERO( &seg0 );
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.score = 32000;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.flags = AF_EDGE_NORMAL;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    major_dir   = (AF_Direction)FT_ABS( axis->major_dir );
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment_dir = major_dir;
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_segments = 0;
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* set up (u,v) in each point */
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fx;
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fy;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fy;
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fx;
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do each contour separately */
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point   =  contour[0];
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  start   =  point;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  last    =  point->prev;
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point == last )  /* skip singletons -- just in case */
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* already on an edge ?, backtrack to find its start */
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ABS( point->in_dir ) == major_dir )
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->prev;
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( point->in_dir == start->in_dir )
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->prev;
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else  /* otherwise, find first segment start, if any */
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( FT_ABS( point->out_dir ) != major_dir )
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == start )
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto NextContour;
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = point;
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for  (;;)
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first;
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    min_u, min_v, max_u, max_v;
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* we're at the start of a new segment */
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           point->in_dir != point->out_dir );
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = point;
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min_u = max_u = point->u;
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min_v = max_v = point->v;
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->next;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( point->out_dir == first->out_dir )
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->u < min_u )
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min_u = point->u;
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->u > max_u )
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            max_u = point->u;
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->v < min_v )
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min_v = point->v;
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->v > max_v )
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max_v = point->v;
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* record new segment */
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_axis_hints_new_segment( axis, memory, &segment );
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment[0]         = seg0;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->dir       = first->out_dir;
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->first     = first;
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->last      = point;
828727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        segment->pos       = (FT_Short)( ( min_u + max_u ) >> 1 );
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->min_coord = (FT_Short) min_v;
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->max_coord = (FT_Short) max_v;
831727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        segment->height    = (FT_Short)( max_v - min_v );
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a segment is round if it doesn't have successive */
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* on-curve points.                                 */
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  pt   = first;
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  last = point;
838727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          AF_Flags  f0   = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Flags  f1;
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment->flags &= ~AF_EDGE_ROUND;
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; pt != last; f0 = f1 )
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pt = pt->next;
847727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( !f0 && !f1 )
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( pt == last )
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segment->flags |= AF_EDGE_ROUND;
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       /* this can happen in the case of a degenerate contour
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        * e.g. a 2-point vertical contour
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        */
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point == start )
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to the start of the next segment, if any */
864727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        while ( FT_ABS( point->out_dir ) != major_dir )
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == start )
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto NextContour;
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NextContour:
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    } /* contours */
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now slightly increase the height of segments when this makes */
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sense -- this is used to better detect and ignore serifs     */
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments     = axis->segments;
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments_end = segments + axis->num_segments;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( segment = segments; segment < segments_end; segment++ )
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first   = segment->first;
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  last    = segment->last;
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  p;
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    first_v = first->v;
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    last_v  = last->v;
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first == last )
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_v < last_v )
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < first_v )
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( first_v - p->v ) >> 1 ) );
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > last_v )
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - last_v ) >> 1 ) );
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > first_v )
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - first_v ) >> 1 ) );
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < last_v )
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( last_v - p->v ) >> 1 ) );
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#ifdef AF_SORT_SEGMENTS
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   /* place all segments with a negative direction to the start
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    * of the array, used to speed up segment linking later...
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    */
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments = axis->segments;
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     count    = axis->num_segments;
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     ii, jj;
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
932727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      for ( ii = 0; ii < count; ii++ )
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( segments[ii].dir > 0 )
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
936727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          for ( jj = ii + 1; jj < count; jj++ )
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( segments[jj].dir < 0 )
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              AF_SegmentRec  tmp;
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
942727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              tmp          = segments[ii];
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segments[ii] = segments[jj];
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segments[jj] = tmp;
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( jj == count )
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->mid_segments = ii;
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_link_segments( AF_GlyphHints  hints,
966aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                 AF_Dimension   dim )
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_mid   = segments + axis->mid_segments;
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        len_threshold, len_score;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg1, seg2;
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( len_threshold == 0 )
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      len_threshold = 1;
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_mid; seg1++ )
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now compare each segment to the others */
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the fake segments are introduced to hint the metrics -- */
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we must never link them to anything                     */
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segments; seg2 < segment_limit; seg2++ )
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  pos1 = seg1->pos;
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  pos2 = seg2->pos;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist = pos2 - pos1;
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 0 )
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  min = seg1->min_coord;
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  max = seg1->max_coord;
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  len, score;
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( min < seg2->min_coord )
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = seg2->min_coord;
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( max > seg2->max_coord )
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = seg2->max_coord;
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            len = max - min;
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( len >= len_threshold )
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              score = dist + len_score / len;
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg1->score )
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->score = score;
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->link  = seg2;
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg2->score )
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->score = score;
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->link  = seg1;
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
10430a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#if 0
10440a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    }
10450a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now, compute the `serif' segments */
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      seg2 = seg1->link;
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg2 )
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg2->link != seg1 )
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->link  = 0;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->serif = seg2->link;
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_edges( AF_GlyphHints  hints,
1066aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                 AF_Dimension   dim )
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis   = &hints->axis[dim];
1069727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error      error  = FT_Err_Ok;
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory = hints->memory;
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  up_dir;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        edge_distance_threshold;
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        segment_length_threshold;
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges = 0;
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         : hints->y_scale;
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          : AF_DIR_RIGHT;
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We want to ignore very small (mostly serif) segments, we do that
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  by ignoring those that whose length is less than a given fraction
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  of the standard width. If there is no standard width, we ignore
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  those that are less than a given size in pixels
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  also, unlink serif segments that are linked to segments farther
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  than 50% of the standard width
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( laxis->width_count > 0 )
1103727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        segment_length_threshold = ( laxis->standard_width * 10 ) >> 4;
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      segment_length_threshold = 0;
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We will begin by generating a sorted table of edges for the       */
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* current direction.  To do so, we simply scan each segment and try */
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* to find an edge in our table that corresponds to its position.    */
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* If no edge is found, we create and insert a new edge in the       */
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sorted table.  Otherwise, we simply add the segment to the edge's */
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* list which will be processed in the second step to compute the    */
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* edge's properties.                                                */
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Note that the edges table is sorted along the segment/edge        */
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* position.                                                         */
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         scale );
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( edge_distance_threshold > 64 / 4 )
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge_distance_threshold = 64 / 4;
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge_distance_threshold = FT_DivFix( edge_distance_threshold,
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         scale );
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg = segments; seg < segment_limit; seg++ )
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  found = 0;
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int   ee;
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg->height < segment_length_threshold )
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A special case for serif edges: If they are smaller than */
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* 1.5 pixels we ignore them.                               */
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg->serif )
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  dist = seg->serif->pos - seg->pos;
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1149727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1150727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        if ( dist < 0 )
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1153727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        if ( dist >= laxis->standard_width >> 1 )
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* unlink this serif, it is too distant from its reference stem */
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg->serif = NULL;
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( 2*seg->height < 3 * segment_length_threshold )
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* look for an edge corresponding to the segment */
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ee = 0; ee < axis->num_edges; ee++ )
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge  edge = axis->edges + ee;
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   dist;
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = seg->pos - edge->fpos;
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 0 )
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < edge_distance_threshold && edge->dir == seg->dir )
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          found = edge;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !found )
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge;
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* insert a new edge in the list and */
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* sort according to the position    */
1187aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
1188aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                        memory, &edge );
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* add the segment to the new edge's list */
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ZERO( edge );
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->first    = seg;
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->last     = seg;
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->fpos     = seg->pos;
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir      = seg->dir;
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next = seg;
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if an edge was found, simply add the segment to the edge's */
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* list                                                       */
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next         = found->first;
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last->edge_next = seg;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last            = seg;
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
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    /* Good, we will now compute each edge's properties according to     */
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* segments found on its position.  Basically, these are:            */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - edge's main direction                                          */
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - stem edge, serif edge or both (which defaults to stem then)    */
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - rounded edge, straight or both (which defaults to straight)    */
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - link for edge                                                  */
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, set the `edge' field in each segment -- this is */
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* required in order to compute edge links                       */
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * Note that removing this loop and setting the `edge' field of each
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * segment directly in the code above slows down execution speed for
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * some reasons on platforms like the Sun.
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edges      = axis->edges;
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge_limit = edges + axis->num_edges;
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge;
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg )
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg->edge = edge;
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg       = seg->edge_next;
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( seg != edge->first );
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now, compute each edge properties */
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_round    = 0;  /* does it contain round segments?    */
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_straight = 0;  /* does it contain straight segments? */
1256aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  ups         = 0;  /* number of upwards segments         */
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  downs       = 0;  /* number of downwards segments       */
1259aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Bool  is_serif;
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for roundness of segment */
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->flags & AF_EDGE_ROUND )
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_round++;
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_straight++;
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1275aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for segment direction */
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->dir == up_dir )
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ups   += seg->max_coord-seg->min_coord;
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            downs += seg->max_coord-seg->min_coord;
1281aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for links -- if seg->serif is set, then seg->link must */
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* be ignored                                                   */
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          is_serif = (FT_Bool)( seg->serif               &&
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge         &&
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge != edge );
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge     edge2;
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Segment  seg2;
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge2 = edge->link;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg2  = seg->link;
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg2  = seg->serif;
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = edge->serif;
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edge2 )
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  edge_delta;
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  seg_delta;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge_delta = edge->fpos - edge2->fpos;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edge_delta < 0 )
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge_delta = -edge_delta;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg_delta = seg->pos - seg2->pos;
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < 0 )
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg_delta = -seg_delta;
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < edge_delta )
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge2 = seg2->edge;
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = seg2->edge;
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->serif   = edge2;
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2->flags |= AF_EDGE_SERIF;
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->link  = edge2;
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg = seg->edge_next;
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( seg != edge->first );
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the round/straight flags */
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags = AF_EDGE_NORMAL;
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_round > 0 && is_round >= is_straight )
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->flags |= AF_EDGE_ROUND;
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the edge's main direction */
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir = AF_DIR_NONE;
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ups > downs )
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)up_dir;
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups < downs )
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)-up_dir;
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups == downs )
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = 0;  /* both up and down! */
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* gets rid of serifs if link is set                */
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* XXX: This gets rid of many unpleasant artefacts! */
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*      Example: the `c' in cour.pfa at size 13     */
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif && edge->link )
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->serif = 0;
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_detect_features( AF_GlyphHints  hints,
1373aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   AF_Dimension   dim )
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = af_latin2_hints_compute_segments( hints, dim );
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_hints_link_segments( hints, dim );
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_compute_edges( hints, dim );
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
1391aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                      AF_LatinMetrics  metrics )
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
139341371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    AF_AxisHints  axis       = &hints->axis[AF_DIMENSION_VERT];
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge       = axis->edges;
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edge + axis->num_edges;
139641371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    AF_LatinAxis  latin      = &metrics->axis[AF_DIMENSION_VERT];
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale      = latin->scale;
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        best_dist0;  /* initial threshold */
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute the initial threshold as a fraction of the EM size */
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( best_dist0 > 64 / 2 )
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      best_dist0 = 64 / 2;
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute which blue zones are active, i.e. have their scaled */
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* size < 3/4 pixels                                           */
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* for each horizontal edge search the blue zone which is closest */
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; edge < edge_limit; edge++ )
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    bb;
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  best_blue = NULL;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos    best_dist = best_dist0;
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = latin->blues + bb;
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool       is_top_blue, is_major_dir;
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* skip inactive blue zones (i.e., those that are too small) */
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, check for right edges -- if it is a bottom */
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* zone, check for left edges                                      */
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                                 */
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* of course, that's for TrueType                                  */
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, the edge must be against the major    */
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction; if it is a bottom zone, it must be in the major */
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction                                                  */
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_top_blue ^ is_major_dir )
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos     dist;
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Width   compare;
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if it's a rounded edge, compare it to the overshoot position */
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if it's a flat edge, compare it to the reference position    */
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND )
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            compare = &blue->shoot;
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            compare = &blue->ref;
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = edge->fpos - compare->org;
1451727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( dist < 0 )
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = -dist;
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = FT_MulFix( dist, scale );
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < best_dist )
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_dist = dist;
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_blue = compare;
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now, compare it to the overshoot position if the edge is     */
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* rounded, and if the edge is over the reference position of a */
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* top zone, or under the reference position of a bottom zone   */
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_top_blue ^ is_under_ref )
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              blue = latin->blues + bb;
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = edge->fpos - blue->shoot.org;
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 0 )
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = -dist;
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = FT_MulFix( dist, scale );
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < best_dist )
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_dist = dist;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_blue = & blue->shoot;
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( best_blue )
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->blue_edge = best_blue;
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_init( AF_GlyphHints    hints,
1497aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        AF_LatinMetrics  metrics )
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Render_Mode  mode;
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32       scaler_flags, other_flags;
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Face         face = metrics->root.scaler.face;
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  correct x_scale and y_scale if needed, since they may have
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  been modified `af_latin2_metrics_scale_dim' above
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute flags depending on render mode, etc. */
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mode = metrics->root.scaler.render_mode;
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1518aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaler_flags = hints->scaler_flags;
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    other_flags  = 0;
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of vertical stems for the monochrome and
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  horizontal LCD rendering targets only.
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of horizontal stems for the monochrome and
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  vertical LCD rendering targets only.
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_VERT_SNAP;
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We adjust stems to full pixels only if we don't use the `light' mode.
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode != FT_RENDER_MODE_LIGHT )
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO )
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_MONO;
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  In `light' hinting mode we disable horizontal hinting completely.
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We also do it if the face is italic.
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1555727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( mode == FT_RENDER_MODE_LIGHT                      ||
1556727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease         ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = scaler_flags;
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->other_flags  = other_flags;
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****        L A T I N   G L Y P H   G R I D - F I T T I N G        *****/
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* snap a given width in scaled coordinates to one of the */
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* current standard widths                                */
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_snap_width( AF_Width  widths,
1579aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        FT_Int    count,
1580aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        FT_Pos    width )
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     n;
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  best      = 64 + 32 + 2;
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  reference = width;
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  scaled;
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < count; n++ )
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  w;
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  dist;
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      w = widths[n].cur;
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = width - w;
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < 0 )
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = -dist;
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < best )
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best      = dist;
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        reference = w;
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaled = FT_PIX_ROUND( reference );
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( width >= reference )
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width < scaled + 48 )
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width > scaled - 48 )
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return width;
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compute the snapped width of a given stem */
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_compute_stem_width( AF_GlyphHints  hints,
1626aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                AF_Dimension   dim,
1627aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                FT_Pos         width,
1628aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                AF_Edge_Flags  base_flags,
1629aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                AF_Edge_Flags  stem_flags )
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis     axis     = & metrics->axis[dim];
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos           dist     = width;
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           sign     = 0;
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1637727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( base_flags );
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          axis->extra_light                      )
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return width;
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dist < 0 )
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -width;
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sign = 1;
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( (  vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* smooth hinting process: very lightly quantize the stem width */
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* leave the widths of serifs alone */
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Done_Width;
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( ( base_flags & AF_EDGE_ROUND ) )
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 80 )
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( dist < 56 )
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = 56;
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( axis->width_count > 0 )
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* compare to standard width */
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( axis->width_count > 0 )
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = dist - axis->widths[0].cur;
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 40 )
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = axis->widths[0].cur;
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 48 )
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = 48;
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Done_Width;
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 3 * 64 )
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta  = dist & 63;
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist  &= -64;
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 10 )
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 32 )
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 10;
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 54 )
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 54;
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 32 ) & ~63;
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* strong hinting process: snap the stem width to integer pixels */
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  org_dist = dist;
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( vertical )
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* in the case of vertical hinting, always round */
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the stem heights to integer pixels            */
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist >= 64 )
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 16 ) & ~63;
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_HINTS_DO_MONO( hints ) )
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* monochrome horizontal hinting: snap widths to integer pixels */
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* with a different threshold                                   */
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 64 )
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = 64;
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for horizontal anti-aliased hinting, we adopt a more subtle */
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* approach: we strengthen small stems, round stems whose size */
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 48 )
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 64 ) >> 1;
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( dist < 128 )
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* We only round to an integer width if the corresponding */
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* distortion is less than 1/4 pixel.  Otherwise this     */
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* makes everything worse since the diagonals, which are  */
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* not hinted, appear a lot bolder or thinner than the    */
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* vertical stems.                                        */
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  delta;
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 22 ) & ~63;
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = dist - org_dist;
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( delta < 0 )
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta = -delta;
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1768727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            if ( delta >= 16 )
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = org_dist;
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 48 )
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = ( dist + 64 ) >> 1;
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* round otherwise to prevent color fringes in LCD mode */
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Done_Width:
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( sign )
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -dist;
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dist;
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* align one stem edge relative to the previous stem edge */
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_align_linked_edge( AF_GlyphHints  hints,
1794aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Dimension   dim,
1795aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Edge        base_edge,
1796aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Edge        stem_edge )
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  dist = stem_edge->opos - base_edge->opos;
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  fitted_width = af_latin2_compute_stem_width(
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hints, dim, dist,
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)base_edge->flags,
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)stem_edge->flags );
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stem_edge->pos = base_edge->pos + fitted_width;
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1808aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
1809aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                "dist was %.2f, now %.2f\n",
1810aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
1811aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_align_serif_edge( AF_GlyphHints  hints,
1817aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                              AF_Edge        base,
1818aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                              AF_Edge        serif )
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( hints );
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1822727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    serif->pos = base->pos + ( serif->opos - base->opos );
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                    E D G E   H I N T I N G                      ****/
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hint_edges( AF_GlyphHints  hints,
1839aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        AF_Dimension   dim )
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis       = &hints->axis[dim];
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges      = axis->edges;
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edges + axis->num_edges;
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge;
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       anchor     = 0;
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        has_serifs = 0;
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        anchor_drift = 0;
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1851aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "==== hinting %s edges =====\n",
1852aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we begin by aligning all stems relative to the blue zone */
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if needed -- that's only for horizontal edges            */
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Width  blue;
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge1, edge2;
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue  = edge->blue_edge;
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1 = NULL;
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2 = edge->link;
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( blue )
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge;
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( edge2 && edge2->blue_edge )
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue  = edge2->blue_edge;
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge2;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2 = edge;
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !edge1 )
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1886aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
1887aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    "was (%.2f)\n",
1888aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
1889aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge1->pos / 64.0 ));
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->pos    = blue->fit;
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->flags |= AF_EDGE_DONE;
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2 && !edge2->blue_edge )
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->flags |= AF_EDGE_DONE;
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !anchor )
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor = edge;
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1904727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          anchor_drift = ( anchor->pos - anchor->opos );
1905727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( edge2 )
1906727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            anchor_drift = ( anchor_drift +
1907727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                             ( edge2->pos - edge2->opos ) ) >> 1;
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now we will align all stem edges, trying to maintain the */
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relative order of stems in the glyph                     */
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( edge = edges; edge < edge_limit; edge++ )
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge2;
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge->flags & AF_EDGE_DONE )
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip all non-stem edges */
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge2 = edge->link;
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !edge2 )
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        has_serifs++;
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now align the stem */
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* this should not happen, but it's better to be safe */
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge2->blue_edge )
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1935aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_align_linked_edge( hints, dim, edge2, edge );
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !anchor )
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  org_len, org_center, cur_len;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  cur_pos1, error1, error2, u_off, d_off;
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len = edge2->opos - edge->opos;
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin2_compute_stem_width(
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    hints, dim, org_len,
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge->flags,
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge2->flags );
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len <= 64 )
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = d_off = 32;
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = 38;
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          d_off = 26;
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len < 96 )
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_center = edge->opos + ( org_len >> 1 );
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos1   = FT_PIX_ROUND( org_center );
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error1 = org_center - ( cur_pos1 - u_off );
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < 0 )
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error1 = -error1;
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error2 = org_center - ( cur_pos1 + d_off );
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error2 < 0 )
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error2 = -error2;
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < error2 )
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 -= u_off;
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 += d_off;
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos  = cur_pos1 - cur_len / 2;
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->pos = edge->pos + cur_len;
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1986aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
1987aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    " snapped to (%.2f) (%.2f)\n",
1988aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge-edges, edge->opos / 64.0,
1989aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge2-edges, edge2->opos / 64.0,
1990aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge->pos / 64.0, edge2->pos / 64.0 ));
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        anchor = edge;
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_align_linked_edge( hints, dim, edge, edge2 );
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1999727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        anchor_drift = ( ( anchor->pos - anchor->opos ) +
2000727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                         ( edge2->pos - edge2->opos ) ) >> 1;
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2002aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   org_pos, org_len, org_center, cur_center, cur_len;
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   org_left, org_right;
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_pos    = edge->opos + anchor_drift;
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len    = edge2->opos - edge->opos;
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_center = org_pos + ( org_len >> 1 );
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin2_compute_stem_width(
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   hints, dim, org_len,
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge->flags,
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge2->flags );
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2019727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        org_left  = org_pos + ( ( org_len - cur_len ) >> 1 );
2020727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2022aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
2023aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    org_left / 64.0, org_right / 64.0 ));
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_center = org_center;
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2->flags & AF_EDGE_DONE )
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2028aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "\n" ));
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge2->pos - cur_len;
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         /* we want to compare several displacement, and choose
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          * the one that increases fitness while minimizing
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          * distortion as well
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          */
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos   displacements[6], scores[6], org, fit, delta;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  count = 0;
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* note: don't even try to fit tiny stems */
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( cur_len < 32 )
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2043aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "tiny stem\n" ));
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto AlignStem;
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if the span is within a single pixel, don't touch it */
2048727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) )
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2050aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "single pixel stem\n" ));
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto AlignStem;
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2054727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          if ( cur_len <= 96 )
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* we want to avoid the absolute worst case which is
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * when the left and right edges of the span each represent
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * about 50% of the gray. we'd better want to change this
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * to 25/75%, since this is much more pleasant to the eye with
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * very acceptable distortion
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            */
2062727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            FT_Pos  frac_left  = org_left  & 63;
2063727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            FT_Pos  frac_right = org_right & 63;
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( frac_left  >= 22 && frac_left  <= 42 &&
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 frac_right >= 22 && frac_right <= 42 )
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              org = frac_left;
2069727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              fit = ( org <= 32 ) ? 16 : 48;
2070727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              delta = FT_ABS( fit - org );
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              displacements[count] = fit - org;
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scores[count++]      = delta;
2073727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              org = frac_right;
2076727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              fit = ( org <= 32 ) ? 16 : 48;
2077727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              delta = FT_ABS( fit - org );
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              displacements[count] = fit - org;
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scores[count++]     = delta;
2080727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* snapping the left edge to the grid */
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org   = org_left;
2086727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          fit   = FT_PIX_ROUND( org );
2087727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          delta = FT_ABS( fit - org );
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          displacements[count] = fit - org;
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scores[count++]      = delta;
2090727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* snapping the right edge to the grid */
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org   = org_right;
2094727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          fit   = FT_PIX_ROUND( org );
2095727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          delta = FT_ABS( fit - org );
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          displacements[count] = fit - org;
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scores[count++]      = delta;
2098727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now find the best displacement */
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  best_score = scores[0];
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  best_disp  = displacements[0];
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt nn;
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2106727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            for ( nn = 1; nn < count; nn++ )
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2108727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              if ( scores[nn] < best_score )
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_score = scores[nn];
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_disp  = displacements[nn];
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_center = org_center + best_disp;
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2117aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "\n" ));
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AlignStem:
2121727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        edge->pos  = cur_center - ( cur_len >> 1 );
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->pos = edge->pos + cur_len;
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2124aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
2125aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    " snapped to (%.2f) and (%.2f),"
2126aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    " org_len=%.2f cur_len=%.2f\n",
2127aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge-edges, edge->opos / 64.0,
2128aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge2-edges, edge2->opos / 64.0,
2129aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge->pos / 64.0, edge2->pos / 64.0,
2130aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    org_len / 64.0, cur_len / 64.0 ));
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags  |= AF_EDGE_DONE;
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2137aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
2138aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make sure that lowercase m's maintain their symmetry */
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* In general, lowercase m's have six vertical edges if they are sans */
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* serif, or twelve if they are with serifs.  This implementation is  */
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* based on that assumption, and seems to work very well with most    */
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* faces.  However, if for a certain face this assumption is not      */
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* true, the m is just rendered like before.  In addition, any stem   */
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* correction will only be applied to symmetrical glyphs (even if the */
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* glyph is not an m), so the potential for unwanted distortion is    */
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relatively low.                                                    */
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We don't handle horizontal edges since we can't easily assure that */
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the third (lowest) stem aligns with the base line; it might end up */
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* one pixel higher or lower.                                         */
2158295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
2160295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2161295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  n_edges = edge_limit - edges;
2162295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2163295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2164aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2166aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        AF_Edge  edge1, edge2, edge3;
2167aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        FT_Pos   dist1, dist2, span, delta;
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2170aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( n_edges == 6 )
2171aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2172aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge1 = edges;
2173aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge2 = edges + 2;
2174aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3 = edges + 4;
2175aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2176aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        else
2177aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2178aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge1 = edges + 1;
2179aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge2 = edges + 5;
2180aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3 = edges + 9;
2181aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2183aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        dist1 = edge2->opos - edge1->opos;
2184aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        dist2 = edge3->opos - edge2->opos;
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2186aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        span = dist1 - dist2;
2187aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( span < 0 )
2188aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          span = -span;
2189aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
2190aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( span < 8 )
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2192aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
2193aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3->pos -= delta;
2194aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( edge3->link )
2195aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            edge3->link->pos -= delta;
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2197aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          /* move the serifs along with the stem */
2198aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( n_edges == 12 )
2199aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          {
2200aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            ( edges + 8 )->pos -= delta;
2201aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            ( edges + 11 )->pos -= delta;
2202aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          }
2203aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
2204aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3->flags |= AF_EDGE_DONE;
2205aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( edge3->link )
2206aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            edge3->link->flags |= AF_EDGE_DONE;
2207aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2211295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( has_serifs || !anchor )
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  now hint the remaining edges (serifs and single) in order
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  to complete our processing
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = 1000;
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif )
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = edge->serif->opos - edge->opos;
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < 64 + 16 )
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin2_align_serif_edge( hints, edge->serif, edge );
2238aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
2239aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      " aligned to (%.2f)\n",
2240aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->opos / 64.0,
2241aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge->serif - edges, edge->serif->opos / 64.0,
2242aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge->pos / 64.0 ));
2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( !anchor )
2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2246aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
2247aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      " snapped to (%.2f)\n",
2248aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor    = edge;
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Edge  before, after;
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( before = edge - 1; before >= edges; before-- )
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->flags & AF_EDGE_DONE )
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( after = edge + 1; after < edge_limit; after++ )
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( after->flags & AF_EDGE_DONE )
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( before >= edges && before < edge   &&
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               after < edge_limit && after > edge )
2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
22680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( after->opos == before->opos )
22690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos;
22700a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            else
22710a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos +
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_MulDiv( edge->opos - before->opos,
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->pos - before->pos,
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->opos - before->opos );
2275aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
2276aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        " from %d (opos=%.2f)\n",
2277aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        edge-edges, edge->opos / 64.0, edge->pos / 64.0,
2278aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        before - edges, before->opos / 64.0 ));
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2282aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            edge->pos = anchor->pos +
2283aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2285aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
2286aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        " snapped to (%.2f)\n",
2287aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge + 1 < edge_limit        &&
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge[1].flags & AF_EDGE_DONE &&
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge->pos > edge[1].pos      )
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[1].pos;
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_apply( AF_GlyphHints    hints,
2307aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                         FT_Outline*      outline,
2308aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                         AF_LatinMetrics  metrics )
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int       dim;
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2314aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    error = af_glyph_hints_reload( hints, outline );
2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* analyze glyph outline */
2319aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         AF_HINTS_DO_HORIZONTAL( hints ) )
2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_HORIZONTAL( hints ) )
2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_VERTICAL( hints ) )
2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_hints_compute_blue_edges( hints, metrics );
2338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* grid-fit the outline */
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
2342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2343aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ &&
2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_WarperRec  warper;
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Fixed      scale;
2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        delta;
2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_warper_compute( &warper, hints, dim, &scale, &delta );
2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_scale_dim( hints, dim, scale, delta );
2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_hint_edges( hints, (AF_Dimension)dim );
2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
2363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_save( hints, outline );
2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****              L A T I N   S C R I P T   C L A S S              *****/
2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2383ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  AF_DEFINE_WRITING_SYSTEM_CLASS(
2384ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    af_latin2_writing_system_class,
2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2386ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    AF_WRITING_SYSTEM_LATIN2,
2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
238841371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    sizeof ( AF_LatinMetricsRec ),
2389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
23909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,
23919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,
23929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    (AF_WritingSystem_DoneMetricsFunc) NULL,
2393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
23949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    (AF_WritingSystem_InitHintsFunc)   af_latin2_hints_init,
23959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    (AF_WritingSystem_ApplyHintsFunc)  af_latin2_hints_apply
2396ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  )
2397ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
2398ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
2400