1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner/*  aflatin2.c                                                             */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    Auto-fitter hinting routines for latin script (body).                */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner/*  Copyright 2003-2011 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
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin.h"
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin2.h"
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h"
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afwarp.h"
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
30aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
31aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*************************************************************************/
32aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                       */
33aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
34aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
35aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* messages during execution.                                            */
36aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                       */
37aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#undef  FT_COMPONENT
38aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#define FT_COMPONENT  trace_aflatin2
39aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
40aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
43aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                    AF_Dimension   dim );
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_link_segments( AF_GlyphHints  hints,
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 AF_Dimension   dim );
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****            L A T I N   G L O B A L   M E T R I C S            *****/
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
59aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                 FT_Face          face,
60aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                 FT_ULong         charcode )
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
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph_index = FT_Get_Char_Index( face, charcode );
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph_index == 0 )
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error || face->glyph->outline.n_points <= 0 )
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ZERO( dummy );
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dummy->units_per_em = metrics->units_per_em;
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->x_scale     = scaler->y_scale = 0x10000L;
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->x_delta     = scaler->y_delta = 0;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->face        = face;
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->render_mode = FT_RENDER_MODE_NORMAL;
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->flags       = 0;
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
98aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      error = af_glyph_hints_reload( hints, &face->glyph->outline );
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinAxis  axis    = &metrics->axis[dim];
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_AxisHints  axhints = &hints->axis[dim];
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Segment    seg, limit, link;
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt       num_widths = 0;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_latin2_hints_compute_segments( hints,
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                 (AF_Dimension)dim );
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_hints_link_segments( hints,
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      (AF_Dimension)dim );
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg   = axhints->segments;
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        limit = seg + axhints->num_segments;
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; seg < limit; seg++ )
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          link = seg->link;
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* we only consider stem segments there! */
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( link && link->link == seg && link > seg )
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  dist;
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = seg->pos - link->pos;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 0 )
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = -dist;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( num_widths < AF_LATIN_MAX_WIDTHS )
13641371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier              axis->widths[num_widths++].org = dist;
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_sort_widths( num_widths, axis->widths );
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->width_count = num_widths;
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinAxis  axis = &metrics->axis[dim];
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        stdw;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        stdw = ( axis->width_count > 0 )
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 ? axis->widths[0].org
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 : AF_LATIN_CONSTANT( metrics, 50 );
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* let's try 20% of the smallest width */
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->edge_distance_threshold = stdw / 5;
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->standard_width          = stdw;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->extra_light             = 0;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_done( hints );
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LATIN_MAX_TEST_CHARACTERS  12
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
171aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                        [AF_LATIN_MAX_TEST_CHARACTERS+1] =
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "THEZOCQS",
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "HEZLOCUS",
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "fijkdbh",
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "xzroesc",
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "xzroesc",
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "pqgjy"
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init_blues( AF_LatinMetrics  metrics,
184aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                FT_Face          face )
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_flats;
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_rounds;
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        bb;
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinBlue  blue;
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_GlyphSlot  glyph = face->glyph;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
197aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* we compute the blues simply by loading each character from the     */
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
199aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
201aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "blue zones computation\n" ));
202aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "------------------------------------------------\n" ));
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  p     = af_latin2_blue_chars[bb];
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_ref;
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_shoot;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
212aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      FT_TRACE5(( "blue %3d: ", bb ));
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_flats  = 0;
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_rounds = 0;
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; p < limit && *p; p++ )
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt     glyph_index;
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int      best_point, best_y, best_first, best_last;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  points;
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool     round;
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
225aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "'%c'", *p ));
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          }
288aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "%5d", 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        {
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  start, end, prev, next;
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist;
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now look for the previous and next points that are not on the */
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* same Y coordinate.  Threshold the `closeness'...              */
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          start = end = best_point;
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            prev = start-1;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( prev < best_first )
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              prev = best_last;
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = points[prev].y - best_y;
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < -5 || dist > 5 )
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start = prev;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( start != best_point );
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            next = end+1;
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( next > best_last )
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next = best_first;
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = points[next].y - best_y;
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < -5 || dist > 5 )
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end = next;
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( end != best_point );
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now, set the `round' flag depending on the segment's kind */
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          round = FT_BOOL(
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( round )
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rounds[num_rounds++] = best_y;
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          flats[num_flats++]   = best_y;
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      FT_TRACE5(( "\n" ));
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 && num_rounds == 0 )
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we couldn't find a single glyph to compute this blue zone,
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we will simply ignore it then
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         */
353aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "empty\n" ));
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we have computed the contents of the `rounds' and `flats' tables, */
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now determine the reference and overshoot position of the blue -- */
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we simply take the median value after a simple sort               */
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_rounds, rounds );
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_flats,  flats );
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue       = & axis->blues[axis->blue_count];
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_ref   = & blue->ref.org;
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_shoot = & blue->shoot.org;
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->blue_count++;
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 )
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( num_rounds == 0 )
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = flats[num_flats / 2];
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   = flats[num_flats / 2];
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* there are sometimes problems: if the overshoot position of top     */
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones is under its reference position, or the opposite for bottom  */
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones.  We must thus check everything there and correct the errors */
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *blue_shoot != *blue_ref )
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   ref      = *blue_ref;
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   shoot    = *blue_shoot;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool  over_ref = FT_BOOL( shoot > ref );
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue->flags = 0;
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( AF_LATIN_IS_TOP_BLUE( bb ) )
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags |= AF_LATIN_BLUE_TOP;
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * The following flags is used later to adjust the y and x scales
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * in order to optimize the pixel grid alignment of the top of small
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * letters.
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( bb == AF_LATIN_BLUE_SMALL_TOP )
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
411aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return;
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
418295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_LOCAL_DEF( void )
419295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  af_latin2_metrics_check_digits( AF_LatinMetrics  metrics,
420295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                  FT_Face          face )
421295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
422295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   i;
423295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Bool   started = 0, same_width = 1;
424295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Fixed  advance, old_advance = 0;
425295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
426295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
427295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* check whether all ASCII digits have the same advance width; */
428295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* digit `0' is 0x30 in all supported charmaps                 */
429295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    for ( i = 0x30; i <= 0x39; i++ )
430295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
431295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_UInt  glyph_index;
432295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
433295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
434295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      glyph_index = FT_Get_Char_Index( face, i );
435295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( glyph_index == 0 )
436295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
437295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
438295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( FT_Get_Advance( face, glyph_index,
439295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_SCALE         |
440295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_HINTING       |
441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_IGNORE_TRANSFORM,
442295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           &advance ) )
443295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
444295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
445295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( started )
446295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
447295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( advance != old_advance )
448295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
449295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          same_width = 0;
450295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          break;
451295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
452295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
453295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
454295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
455295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        old_advance = advance;
456295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        started     = 1;
457295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
458295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
459295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
460295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    metrics->root.digits_have_same_width = same_width;
461295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
462295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
463295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init( AF_LatinMetrics  metrics,
466aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                          FT_Face          face )
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error = AF_Err_Ok;
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CharMap  oldmap = face->charmap;
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     ee;
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Encoding  latin_encodings[] =
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_UNICODE,
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_APPLE_ROMAN,
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_STANDARD,
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_LATIN_1,
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_NONE  /* end of list */
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->units_per_em = face->units_per_EM;
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do we have a latin charmap in there? */
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Select_Charmap( face, latin_encodings[ee] );
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !error )
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* For now, compute the standard width and height from the `o'. */
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_metrics_init_widths( metrics, face, 'o' );
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_metrics_init_blues( metrics, face );
497295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      af_latin2_metrics_check_digits( metrics, face );
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Set_Charmap( face, oldmap );
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return AF_Err_Ok;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_scale_dim( AF_LatinMetrics  metrics,
507aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Scaler        scaler,
508aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Dimension     dim )
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        delta;
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt       nn;
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->x_scale;
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->x_delta;
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->y_scale;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->y_delta;
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis = &metrics->axis[dim];
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( axis->org_scale == scale && axis->org_delta == delta )
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_scale = scale;
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_delta = delta;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * correct Y scale to optimize the alignment of the top of small
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * letters to the pixel grid
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinAxis  vaxis = &metrics->axis[AF_DIMENSION_VERT];
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinBlue  blue = NULL;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < vaxis->blue_count; nn++ )
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue = &vaxis->blues[nn];
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( blue )
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  fitted = ( scaled + 40 ) & ~63;
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
560aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( scaled != fitted )
561aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scale = FT_MulDiv( scale, fitted, scaled );
563aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "== scaled x-top = %.2g"
564aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      "  fitted = %.2g, scaling = %.4g\n",
565aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      scaled / 64.0, fitted / 64.0,
566aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      ( fitted * 1.0 ) / scaled ));
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->scale = scale;
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->delta = delta;
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_scale = scale;
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_delta = delta;
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_scale = scale;
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_delta = delta;
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scale the standard widths */
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < axis->width_count; nn++ )
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  width = axis->widths + nn;
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->cur = FT_MulFix( width->org, scale );
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->fit = width->cur;
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* an extra-light axis corresponds to a standard width that is */
597aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* smaller than 5/8 pixels                                     */
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->extra_light =
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* scale the blue zones */
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < axis->blue_count; nn++ )
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = &axis->blues[nn];
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        dist;
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.fit   = blue->ref.cur;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.fit = blue->shoot.cur;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a blue zone is only active if it is less than 3/4 pixels tall */
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist <= 48 && dist >= -48 )
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  delta1, delta2;
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta1 = blue->shoot.org - blue->ref.org;
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = delta1;
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = FT_MulFix( delta2, scale );
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta2 < 32 )
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 0;
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta2 < 64 )
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = FT_PIX_ROUND( delta2 );
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->shoot.fit = blue->ref.fit + delta2;
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
642aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( ">> activating blue zone %d:"
643aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      "  ref.cur=%.2g ref.fit=%.2g"
644aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      "  shoot.cur=%.2g shoot.fit=%.2g\n",
645aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
646aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->flags |= AF_LATIN_BLUE_ACTIVE;
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_scale( AF_LatinMetrics  metrics,
657aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                           AF_Scaler        scaler )
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.render_mode = scaler->render_mode;
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.face        = scaler->face;
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****           L A T I N   G L Y P H   A N A L Y S I S             *****/
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  SORT_SEGMENTS
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
679aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                    AF_Dimension   dim )
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory        = hints->memory;
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error         = AF_Err_Ok;
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment       = NULL;
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SegmentRec seg0;
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour       = hints->contours;
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour_limit = contour + hints->num_contours;
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  major_dir, segment_dir;
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ZERO( &seg0 );
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.score = 32000;
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.flags = AF_EDGE_NORMAL;
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    major_dir   = (AF_Direction)FT_ABS( axis->major_dir );
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment_dir = major_dir;
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_segments = 0;
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* set up (u,v) in each point */
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fx;
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fy;
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fy;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fx;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do each contour separately */
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point   =  contour[0];
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  start   =  point;
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  last    =  point->prev;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point == last )  /* skip singletons -- just in case */
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* already on an edge ?, backtrack to find its start */
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ABS( point->in_dir ) == major_dir )
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->prev;
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( point->in_dir == start->in_dir )
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->prev;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else  /* otherwise, find first segment start, if any */
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( FT_ABS( point->out_dir ) != major_dir )
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == start )
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto NextContour;
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = point;
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for  (;;)
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first;
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    min_u, min_v, max_u, max_v;
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* we're at the start of a new segment */
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           point->in_dir != point->out_dir );
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = point;
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min_u = max_u = point->u;
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min_v = max_v = point->v;
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->next;
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( point->out_dir == first->out_dir )
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->u < min_u )
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min_u = point->u;
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->u > max_u )
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            max_u = point->u;
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->v < min_v )
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min_v = point->v;
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->v > max_v )
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max_v = point->v;
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* record new segment */
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_axis_hints_new_segment( axis, memory, &segment );
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment[0]         = seg0;
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->dir       = first->out_dir;
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->first     = first;
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->last      = point;
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->pos       = (FT_Short)(( min_u + max_u ) >> 1);
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->min_coord = (FT_Short) min_v;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->max_coord = (FT_Short) max_v;
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->height    = (FT_Short)(max_v - min_v);
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a segment is round if it doesn't have successive */
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* on-curve points.                                 */
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  pt   = first;
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  last = point;
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Flags  f0   = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Flags  f1;
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment->flags &= ~AF_EDGE_ROUND;
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; pt != last; f0 = f1 )
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pt = pt->next;
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( !f0 && !f1 )
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( pt == last )
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segment->flags |= AF_EDGE_ROUND;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       /* this can happen in the case of a degenerate contour
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        * e.g. a 2-point vertical contour
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        */
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point == start )
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to the start of the next segment, if any */
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( FT_ABS(point->out_dir) != major_dir )
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == start )
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto NextContour;
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NextContour:
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    } /* contours */
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now slightly increase the height of segments when this makes */
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sense -- this is used to better detect and ignore serifs     */
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments     = axis->segments;
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments_end = segments + axis->num_segments;
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( segment = segments; segment < segments_end; segment++ )
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first   = segment->first;
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  last    = segment->last;
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  p;
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    first_v = first->v;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    last_v  = last->v;
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first == last )
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_v < last_v )
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < first_v )
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( first_v - p->v ) >> 1 ) );
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > last_v )
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - last_v ) >> 1 ) );
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > first_v )
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - first_v ) >> 1 ) );
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < last_v )
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( last_v - p->v ) >> 1 ) );
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   /* place all segments with a negative direction to the start
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    * of the array, used to speed up segment linking later...
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    */
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments = axis->segments;
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     count    = axis->num_segments;
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     ii, jj;
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (ii = 0; ii < count; ii++)
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( segments[ii].dir > 0 )
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for (jj = ii+1; jj < count; jj++)
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( segments[jj].dir < 0 )
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              AF_SegmentRec  tmp;
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              tmp          = segments[ii];
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segments[ii] = segments[jj];
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segments[jj] = tmp;
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( jj == count )
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->mid_segments = ii;
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_link_segments( AF_GlyphHints  hints,
936aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                 AF_Dimension   dim )
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_mid   = segments + axis->mid_segments;
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        len_threshold, len_score;
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg1, seg2;
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( len_threshold == 0 )
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      len_threshold = 1;
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_mid; seg1++ )
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now compare each segment to the others */
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the fake segments are introduced to hint the metrics -- */
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we must never link them to anything                     */
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segments; seg2 < segment_limit; seg2++ )
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  pos1 = seg1->pos;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  pos2 = seg2->pos;
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist = pos2 - pos1;
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 0 )
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  min = seg1->min_coord;
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  max = seg1->max_coord;
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  len, score;
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( min < seg2->min_coord )
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = seg2->min_coord;
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( max > seg2->max_coord )
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = seg2->max_coord;
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            len = max - min;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( len >= len_threshold )
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              score = dist + len_score / len;
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg1->score )
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->score = score;
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->link  = seg2;
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg2->score )
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->score = score;
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->link  = seg1;
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
10130a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#if 0
10140a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    }
10150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now, compute the `serif' segments */
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      seg2 = seg1->link;
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg2 )
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg2->link != seg1 )
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->link  = 0;
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->serif = seg2->link;
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_edges( AF_GlyphHints  hints,
1036aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                 AF_Dimension   dim )
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis   = &hints->axis[dim];
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error  = AF_Err_Ok;
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory = hints->memory;
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  up_dir;
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        edge_distance_threshold;
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        segment_length_threshold;
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges = 0;
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         : hints->y_scale;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          : AF_DIR_RIGHT;
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We want to ignore very small (mostly serif) segments, we do that
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  by ignoring those that whose length is less than a given fraction
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  of the standard width. If there is no standard width, we ignore
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  those that are less than a given size in pixels
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  also, unlink serif segments that are linked to segments farther
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  than 50% of the standard width
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( laxis->width_count > 0 )
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment_length_threshold = (laxis->standard_width * 10 ) >> 4;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      segment_length_threshold = 0;
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We will begin by generating a sorted table of edges for the       */
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* current direction.  To do so, we simply scan each segment and try */
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* to find an edge in our table that corresponds to its position.    */
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* If no edge is found, we create and insert a new edge in the       */
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sorted table.  Otherwise, we simply add the segment to the edge's */
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* list which will be processed in the second step to compute the    */
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* edge's properties.                                                */
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Note that the edges table is sorted along the segment/edge        */
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* position.                                                         */
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         scale );
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( edge_distance_threshold > 64 / 4 )
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge_distance_threshold = 64 / 4;
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge_distance_threshold = FT_DivFix( edge_distance_threshold,
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         scale );
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg = segments; seg < segment_limit; seg++ )
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  found = 0;
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int   ee;
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg->height < segment_length_threshold )
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A special case for serif edges: If they are smaller than */
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* 1.5 pixels we ignore them.                               */
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg->serif )
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  dist = seg->serif->pos - seg->pos;
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if (dist < 0)
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if (dist >= laxis->standard_width >> 1)
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* unlink this serif, it is too distant from its reference stem */
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg->serif = NULL;
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( 2*seg->height < 3 * segment_length_threshold )
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* look for an edge corresponding to the segment */
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ee = 0; ee < axis->num_edges; ee++ )
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge  edge = axis->edges + ee;
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   dist;
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = seg->pos - edge->fpos;
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 0 )
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < edge_distance_threshold && edge->dir == seg->dir )
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          found = edge;
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !found )
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge;
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* insert a new edge in the list and */
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* sort according to the position    */
1156aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
1157aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                        memory, &edge );
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* add the segment to the new edge's list */
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ZERO( edge );
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->first    = seg;
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->last     = seg;
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->fpos     = seg->pos;
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir      = seg->dir;
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next = seg;
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if an edge was found, simply add the segment to the edge's */
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* list                                                       */
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next         = found->first;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last->edge_next = seg;
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last            = seg;
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Good, we will now compute each edge's properties according to     */
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* segments found on its position.  Basically, these are:            */
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - edge's main direction                                          */
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - stem edge, serif edge or both (which defaults to stem then)    */
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - rounded edge, straight or both (which defaults to straight)    */
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - link for edge                                                  */
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, set the `edge' field in each segment -- this is */
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* required in order to compute edge links                       */
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * Note that removing this loop and setting the `edge' field of each
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * segment directly in the code above slows down execution speed for
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * some reasons on platforms like the Sun.
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edges      = axis->edges;
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge_limit = edges + axis->num_edges;
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge;
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg )
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg->edge = edge;
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg       = seg->edge_next;
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( seg != edge->first );
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now, compute each edge properties */
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_round    = 0;  /* does it contain round segments?    */
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_straight = 0;  /* does it contain straight segments? */
1225aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  ups         = 0;  /* number of upwards segments         */
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  downs       = 0;  /* number of downwards segments       */
1228aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Bool  is_serif;
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for roundness of segment */
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->flags & AF_EDGE_ROUND )
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_round++;
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_straight++;
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1244aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for segment direction */
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->dir == up_dir )
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ups   += seg->max_coord-seg->min_coord;
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            downs += seg->max_coord-seg->min_coord;
1250aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for links -- if seg->serif is set, then seg->link must */
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* be ignored                                                   */
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          is_serif = (FT_Bool)( seg->serif               &&
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge         &&
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge != edge );
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge     edge2;
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Segment  seg2;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge2 = edge->link;
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg2  = seg->link;
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg2  = seg->serif;
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = edge->serif;
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edge2 )
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  edge_delta;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  seg_delta;
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge_delta = edge->fpos - edge2->fpos;
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edge_delta < 0 )
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge_delta = -edge_delta;
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg_delta = seg->pos - seg2->pos;
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < 0 )
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg_delta = -seg_delta;
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < edge_delta )
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge2 = seg2->edge;
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = seg2->edge;
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->serif   = edge2;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2->flags |= AF_EDGE_SERIF;
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->link  = edge2;
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg = seg->edge_next;
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( seg != edge->first );
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the round/straight flags */
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags = AF_EDGE_NORMAL;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_round > 0 && is_round >= is_straight )
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->flags |= AF_EDGE_ROUND;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the edge's main direction */
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir = AF_DIR_NONE;
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ups > downs )
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)up_dir;
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups < downs )
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)-up_dir;
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups == downs )
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = 0;  /* both up and down! */
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* gets rid of serifs if link is set                */
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* XXX: This gets rid of many unpleasant artefacts! */
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*      Example: the `c' in cour.pfa at size 13     */
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif && edge->link )
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->serif = 0;
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_detect_features( AF_GlyphHints  hints,
1342aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                   AF_Dimension   dim )
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = af_latin2_hints_compute_segments( hints, dim );
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_hints_link_segments( hints, dim );
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_compute_edges( hints, dim );
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
1360aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                      AF_LatinMetrics  metrics )
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
136241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    AF_AxisHints  axis       = &hints->axis[AF_DIMENSION_VERT];
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge       = axis->edges;
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edge + axis->num_edges;
136541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    AF_LatinAxis  latin      = &metrics->axis[AF_DIMENSION_VERT];
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale      = latin->scale;
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        best_dist0;  /* initial threshold */
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute the initial threshold as a fraction of the EM size */
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( best_dist0 > 64 / 2 )
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      best_dist0 = 64 / 2;
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute which blue zones are active, i.e. have their scaled */
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* size < 3/4 pixels                                           */
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* for each horizontal edge search the blue zone which is closest */
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; edge < edge_limit; edge++ )
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    bb;
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  best_blue = NULL;
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos    best_dist = best_dist0;
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = latin->blues + bb;
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool       is_top_blue, is_major_dir;
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* skip inactive blue zones (i.e., those that are too small) */
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, check for right edges -- if it is a bottom */
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* zone, check for left edges                                      */
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                                 */
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* of course, that's for TrueType                                  */
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, the edge must be against the major    */
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction; if it is a bottom zone, it must be in the major */
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction                                                  */
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_top_blue ^ is_major_dir )
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos     dist;
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Width   compare;
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if it's a rounded edge, compare it to the overshoot position */
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if it's a flat edge, compare it to the reference position    */
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND )
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            compare = &blue->shoot;
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            compare = &blue->ref;
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = edge->fpos - compare->org;
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if (dist < 0)
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = -dist;
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = FT_MulFix( dist, scale );
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < best_dist )
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_dist = dist;
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_blue = compare;
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now, compare it to the overshoot position if the edge is     */
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* rounded, and if the edge is over the reference position of a */
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* top zone, or under the reference position of a bottom zone   */
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_top_blue ^ is_under_ref )
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              blue = latin->blues + bb;
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = edge->fpos - blue->shoot.org;
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 0 )
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = -dist;
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = FT_MulFix( dist, scale );
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < best_dist )
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_dist = dist;
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_blue = & blue->shoot;
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( best_blue )
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->blue_edge = best_blue;
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_init( AF_GlyphHints    hints,
1466aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        AF_LatinMetrics  metrics )
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Render_Mode  mode;
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32       scaler_flags, other_flags;
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Face         face = metrics->root.scaler.face;
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  correct x_scale and y_scale if needed, since they may have
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  been modified `af_latin2_metrics_scale_dim' above
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute flags depending on render mode, etc. */
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mode = metrics->root.scaler.render_mode;
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1487aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaler_flags = hints->scaler_flags;
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    other_flags  = 0;
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of vertical stems for the monochrome and
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  horizontal LCD rendering targets only.
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of horizontal stems for the monochrome and
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  vertical LCD rendering targets only.
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_VERT_SNAP;
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We adjust stems to full pixels only if we don't use the `light' mode.
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode != FT_RENDER_MODE_LIGHT )
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO )
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_MONO;
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  In `light' hinting mode we disable horizontal hinting completely.
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We also do it if the face is italic.
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LIGHT                    ||
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = scaler_flags;
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->other_flags  = other_flags;
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1538049d6fea481044fcc000e7782e5bc7046fc70844The 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        *****/
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* snap a given width in scaled coordinates to one of the */
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* current standard widths                                */
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_snap_width( AF_Width  widths,
1548aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        FT_Int    count,
1549aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        FT_Pos    width )
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     n;
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  best      = 64 + 32 + 2;
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  reference = width;
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  scaled;
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < count; n++ )
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  w;
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  dist;
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      w = widths[n].cur;
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = width - w;
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < 0 )
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = -dist;
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < best )
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best      = dist;
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        reference = w;
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaled = FT_PIX_ROUND( reference );
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( width >= reference )
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width < scaled + 48 )
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width > scaled - 48 )
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return width;
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compute the snapped width of a given stem */
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_compute_stem_width( AF_GlyphHints  hints,
1595aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                AF_Dimension   dim,
1596aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                FT_Pos         width,
1597aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                AF_Edge_Flags  base_flags,
1598aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                AF_Edge_Flags  stem_flags )
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis     axis     = & metrics->axis[dim];
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos           dist     = width;
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           sign     = 0;
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED(base_flags);
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          axis->extra_light                      )
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return width;
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dist < 0 )
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -width;
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sign = 1;
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( (  vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* smooth hinting process: very lightly quantize the stem width */
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* leave the widths of serifs alone */
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Done_Width;
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( ( base_flags & AF_EDGE_ROUND ) )
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 80 )
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( dist < 56 )
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = 56;
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( axis->width_count > 0 )
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* compare to standard width */
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( axis->width_count > 0 )
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = dist - axis->widths[0].cur;
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 40 )
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = axis->widths[0].cur;
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 48 )
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = 48;
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Done_Width;
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 3 * 64 )
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta  = dist & 63;
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist  &= -64;
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 10 )
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 32 )
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 10;
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 54 )
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 54;
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 32 ) & ~63;
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* strong hinting process: snap the stem width to integer pixels */
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  org_dist = dist;
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( vertical )
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* in the case of vertical hinting, always round */
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the stem heights to integer pixels            */
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist >= 64 )
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 16 ) & ~63;
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_HINTS_DO_MONO( hints ) )
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* monochrome horizontal hinting: snap widths to integer pixels */
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* with a different threshold                                   */
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 64 )
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = 64;
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        else
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for horizontal anti-aliased hinting, we adopt a more subtle */
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* approach: we strengthen small stems, round stems whose size */
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 48 )
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 64 ) >> 1;
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( dist < 128 )
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* We only round to an integer width if the corresponding */
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* distortion is less than 1/4 pixel.  Otherwise this     */
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* makes everything worse since the diagonals, which are  */
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* not hinted, appear a lot bolder or thinner than the    */
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* vertical stems.                                        */
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  delta;
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 22 ) & ~63;
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = dist - org_dist;
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( delta < 0 )
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta = -delta;
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if (delta >= 16)
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = org_dist;
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 48 )
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = ( dist + 64 ) >> 1;
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* round otherwise to prevent color fringes in LCD mode */
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Done_Width:
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( sign )
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -dist;
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dist;
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* align one stem edge relative to the previous stem edge */
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_align_linked_edge( AF_GlyphHints  hints,
1763aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Dimension   dim,
1764aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Edge        base_edge,
1765aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                               AF_Edge        stem_edge )
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  dist = stem_edge->opos - base_edge->opos;
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  fitted_width = af_latin2_compute_stem_width(
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hints, dim, dist,
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)base_edge->flags,
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)stem_edge->flags );
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stem_edge->pos = base_edge->pos + fitted_width;
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1777aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
1778aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                "dist was %.2f, now %.2f\n",
1779aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
1780aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_align_serif_edge( AF_GlyphHints  hints,
1786aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                              AF_Edge        base,
1787aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                              AF_Edge        serif )
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( hints );
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    serif->pos = base->pos + (serif->opos - base->opos);
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                    E D G E   H I N T I N G                      ****/
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hint_edges( AF_GlyphHints  hints,
1808aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        AF_Dimension   dim )
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis       = &hints->axis[dim];
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges      = axis->edges;
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edges + axis->num_edges;
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge;
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       anchor     = 0;
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        has_serifs = 0;
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        anchor_drift = 0;
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1820aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "==== hinting %s edges =====\n",
1821aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we begin by aligning all stems relative to the blue zone */
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if needed -- that's only for horizontal edges            */
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Width  blue;
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge1, edge2;
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue  = edge->blue_edge;
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1 = NULL;
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2 = edge->link;
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( blue )
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge;
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( edge2 && edge2->blue_edge )
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue  = edge2->blue_edge;
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge2;
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2 = edge;
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !edge1 )
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1855aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
1856aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    "was (%.2f)\n",
1857aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
1858aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge1->pos / 64.0 ));
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->pos    = blue->fit;
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->flags |= AF_EDGE_DONE;
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2 && !edge2->blue_edge )
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->flags |= AF_EDGE_DONE;
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !anchor )
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor = edge;
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor_drift = (anchor->pos - anchor->opos);
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if (edge2)
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1;
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now we will align all stem edges, trying to maintain the */
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relative order of stems in the glyph                     */
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( edge = edges; edge < edge_limit; edge++ )
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge2;
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge->flags & AF_EDGE_DONE )
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip all non-stem edges */
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge2 = edge->link;
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !edge2 )
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        has_serifs++;
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now align the stem */
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* this should not happen, but it's better to be safe */
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge2->blue_edge )
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1903aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_align_linked_edge( hints, dim, edge2, edge );
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !anchor )
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  org_len, org_center, cur_len;
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  cur_pos1, error1, error2, u_off, d_off;
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len = edge2->opos - edge->opos;
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin2_compute_stem_width(
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    hints, dim, org_len,
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge->flags,
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge2->flags );
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len <= 64 )
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = d_off = 32;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = 38;
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          d_off = 26;
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len < 96 )
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_center = edge->opos + ( org_len >> 1 );
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos1   = FT_PIX_ROUND( org_center );
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error1 = org_center - ( cur_pos1 - u_off );
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < 0 )
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error1 = -error1;
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error2 = org_center - ( cur_pos1 + d_off );
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error2 < 0 )
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error2 = -error2;
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < error2 )
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 -= u_off;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 += d_off;
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos  = cur_pos1 - cur_len / 2;
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->pos = edge->pos + cur_len;
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1954aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
1955aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    " snapped to (%.2f) (%.2f)\n",
1956aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge-edges, edge->opos / 64.0,
1957aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge2-edges, edge2->opos / 64.0,
1958aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge->pos / 64.0, edge2->pos / 64.0 ));
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        anchor = edge;
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_align_linked_edge( hints, dim, edge, edge2 );
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        anchor_drift = ( (anchor->pos - anchor->opos) +
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         (edge2->pos - edge2->opos)) >> 1;
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1970aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   org_pos, org_len, org_center, cur_center, cur_len;
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   org_left, org_right;
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_pos    = edge->opos + anchor_drift;
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len    = edge2->opos - edge->opos;
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_center = org_pos + ( org_len >> 1 );
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin2_compute_stem_width(
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   hints, dim, org_len,
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge->flags,
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge2->flags );
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_left  = org_pos + ((org_len - cur_len) >> 1);
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_right = org_pos + ((org_len + cur_len) >> 1);
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1990aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
1991aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    org_left / 64.0, org_right / 64.0 ));
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_center = org_center;
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2->flags & AF_EDGE_DONE )
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1996aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "\n" ));
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge2->pos - cur_len;
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         /* we want to compare several displacement, and choose
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          * the one that increases fitness while minimizing
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          * distortion as well
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          */
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos   displacements[6], scores[6], org, fit, delta;
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  count = 0;
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* note: don't even try to fit tiny stems */
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( cur_len < 32 )
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2011aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "tiny stem\n" ));
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto AlignStem;
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if the span is within a single pixel, don't touch it */
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2018aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "single pixel stem\n" ));
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto AlignStem;
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if (cur_len <= 96)
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* we want to avoid the absolute worst case which is
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * when the left and right edges of the span each represent
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * about 50% of the gray. we'd better want to change this
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * to 25/75%, since this is much more pleasant to the eye with
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * very acceptable distortion
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            */
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  frac_left  = (org_left) & 63;
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  frac_right = (org_right) & 63;
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( frac_left  >= 22 && frac_left  <= 42 &&
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 frac_right >= 22 && frac_right <= 42 )
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              org = frac_left;
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              fit = (org <= 32) ? 16 : 48;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta = FT_ABS(fit - org);
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              displacements[count] = fit - org;
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scores[count++]      = delta;
2041aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner              FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta ));
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              org = frac_right;
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              fit = (org <= 32) ? 16 : 48;
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta = FT_ABS(fit - org);
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              displacements[count] = fit - org;
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scores[count++]     = delta;
2048aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner              FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta ));
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* snapping the left edge to the grid */
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org   = org_left;
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fit   = FT_PIX_ROUND(org);
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = FT_ABS(fit - org);
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          displacements[count] = fit - org;
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scores[count++]      = delta;
2058aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta ));
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* snapping the right edge to the grid */
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org   = org_right;
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fit   = FT_PIX_ROUND(org);
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = FT_ABS(fit - org);
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          displacements[count] = fit - org;
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scores[count++]      = delta;
2066aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta ));
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now find the best displacement */
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  best_score = scores[0];
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  best_disp  = displacements[0];
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt nn;
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for (nn = 1; nn < count; nn++)
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if (scores[nn] < best_score)
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_score = scores[nn];
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_disp  = displacements[nn];
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_center = org_center + best_disp;
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2085aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "\n" ));
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AlignStem:
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->pos  = cur_center - (cur_len >> 1);
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->pos = edge->pos + cur_len;
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2092aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
2093aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    " snapped to (%.2f) and (%.2f),"
2094aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    " org_len=%.2f cur_len=%.2f\n",
2095aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge-edges, edge->opos / 64.0,
2096aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge2-edges, edge2->opos / 64.0,
2097aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    edge->pos / 64.0, edge2->pos / 64.0,
2098aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                    org_len / 64.0, cur_len / 64.0 ));
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags  |= AF_EDGE_DONE;
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2105aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
2106aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make sure that lowercase m's maintain their symmetry */
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* In general, lowercase m's have six vertical edges if they are sans */
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* serif, or twelve if they are with serifs.  This implementation is  */
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* based on that assumption, and seems to work very well with most    */
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* faces.  However, if for a certain face this assumption is not      */
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* true, the m is just rendered like before.  In addition, any stem   */
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* correction will only be applied to symmetrical glyphs (even if the */
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* glyph is not an m), so the potential for unwanted distortion is    */
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relatively low.                                                    */
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We don't handle horizontal edges since we can't easily assure that */
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the third (lowest) stem aligns with the base line; it might end up */
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* one pixel higher or lower.                                         */
2126295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
2128295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2129295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  n_edges = edge_limit - edges;
2130295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2131295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2132aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2134aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        AF_Edge  edge1, edge2, edge3;
2135aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        FT_Pos   dist1, dist2, span, delta;
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2138aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( n_edges == 6 )
2139aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2140aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge1 = edges;
2141aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge2 = edges + 2;
2142aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3 = edges + 4;
2143aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2144aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        else
2145aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2146aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge1 = edges + 1;
2147aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge2 = edges + 5;
2148aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3 = edges + 9;
2149aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2151aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        dist1 = edge2->opos - edge1->opos;
2152aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        dist2 = edge3->opos - edge2->opos;
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2154aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        span = dist1 - dist2;
2155aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( span < 0 )
2156aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          span = -span;
2157aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
2158aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( span < 8 )
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2160aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
2161aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3->pos -= delta;
2162aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( edge3->link )
2163aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            edge3->link->pos -= delta;
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2165aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          /* move the serifs along with the stem */
2166aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( n_edges == 12 )
2167aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          {
2168aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            ( edges + 8 )->pos -= delta;
2169aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            ( edges + 11 )->pos -= delta;
2170aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          }
2171aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
2172aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3->flags |= AF_EDGE_DONE;
2173aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( edge3->link )
2174aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            edge3->link->flags |= AF_EDGE_DONE;
2175aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2179295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( has_serifs || !anchor )
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  now hint the remaining edges (serifs and single) in order
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  to complete our processing
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = 1000;
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif )
2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = edge->serif->opos - edge->opos;
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < 64 + 16 )
2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin2_align_serif_edge( hints, edge->serif, edge );
2206aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
2207aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      " aligned to (%.2f)\n",
2208aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->opos / 64.0,
2209aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge->serif - edges, edge->serif->opos / 64.0,
2210aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge->pos / 64.0 ));
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( !anchor )
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2214aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
2215aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      " snapped to (%.2f)\n",
2216aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor    = edge;
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Edge  before, after;
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( before = edge - 1; before >= edges; before-- )
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->flags & AF_EDGE_DONE )
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( after = edge + 1; after < edge_limit; after++ )
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( after->flags & AF_EDGE_DONE )
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( before >= edges && before < edge   &&
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               after < edge_limit && after > edge )
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
22360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( after->opos == before->opos )
22370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos;
22380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            else
22390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos +
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_MulDiv( edge->opos - before->opos,
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->pos - before->pos,
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->opos - before->opos );
2243aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
2244aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        " from %d (opos=%.2f)\n",
2245aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        edge-edges, edge->opos / 64.0, edge->pos / 64.0,
2246aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        before - edges, before->opos / 64.0 ));
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2250aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            edge->pos = anchor->pos +
2251aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2253aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
2254aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        " snapped to (%.2f)\n",
2255aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge + 1 < edge_limit        &&
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge[1].flags & AF_EDGE_DONE &&
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge->pos > edge[1].pos      )
2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[1].pos;
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_apply( AF_GlyphHints    hints,
2275aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                         FT_Outline*      outline,
2276aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                         AF_LatinMetrics  metrics )
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int       dim;
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2282aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    error = af_glyph_hints_reload( hints, outline );
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* analyze glyph outline */
2287aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         AF_HINTS_DO_HORIZONTAL( hints ) )
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_HORIZONTAL( hints ) )
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_VERTICAL( hints ) )
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_hints_compute_blue_edges( hints, metrics );
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* grid-fit the outline */
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2311aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ &&
2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_WarperRec  warper;
2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Fixed      scale;
2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        delta;
2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_warper_compute( &warper, hints, dim, &scale, &delta );
2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_scale_dim( hints, dim, scale, delta );
2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_hint_edges( hints, (AF_Dimension)dim );
2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_save( hints, outline );
2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****              L A T I N   S C R I P T   C L A S S              *****/
2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const AF_Script_UniRangeRec  af_latin2_uniranges[] =
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2353aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_UNIRANGE_REC( 32UL,  127UL ),    /* TODO: Add new Unicode ranges here! */
2354295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC( 160UL, 255UL ),
2355295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC( 0UL,   0UL )
2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
235941371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class,
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SCRIPT_LATIN2,
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_uniranges,
2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
236341371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    sizeof ( AF_LatinMetricsRec ),
2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_InitMetricsFunc) af_latin2_metrics_init,
2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale,
2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_DoneMetricsFunc) NULL,
2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_InitHintsFunc)   af_latin2_hints_init,
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_ApplyHintsFunc)  af_latin2_hints_apply
2371295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  )
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
2375