1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  aflatin.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 <ft2build.h>
20295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include FT_ADVANCES_H
21aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#include FT_INTERNAL_DEBUG_H
22295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin.h"
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h"
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afwarp.h"
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
33aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                       */
34aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
35aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
36aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* messages during execution.                                            */
37aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*                                                                       */
38aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#undef  FT_COMPONENT
39aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#define FT_COMPONENT  trace_aflatin
40aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
41aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
42aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /*************************************************************************/
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****            L A T I N   G L O B A L   M E T R I C S            *****/
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
50aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
51aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Find segments and links, compute all stem widths, and initialize */
52aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* standard width and height for the glyph with given charcode.     */
53aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_metrics_init_widths( AF_LatinMetrics  metrics,
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_Face          face,
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_ULong         charcode )
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scan the array of segments in each direction */
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_GlyphHintsRec  hints[1];
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_init( hints, face->memory );
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->axis[AF_DIMENSION_VERT].width_count = 0;
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Error             error;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt              glyph_index;
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      int                  dim;
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinMetricsRec   dummy[1];
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Scaler            scaler = &dummy->root.scaler;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      glyph_index = FT_Get_Char_Index( face, charcode );
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph_index == 0 )
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error || face->glyph->outline.n_points <= 0 )
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ZERO( dummy );
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dummy->units_per_em = metrics->units_per_em;
87aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
88aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      scaler->x_scale = 0x10000L;
89aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      scaler->y_scale = 0x10000L;
90aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      scaler->x_delta = 0;
91aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      scaler->y_delta = 0;
92aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->face        = face;
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->render_mode = FT_RENDER_MODE_NORMAL;
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->flags       = 0;
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
99aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      error = af_glyph_hints_reload( hints, &face->glyph->outline );
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinAxis  axis    = &metrics->axis[dim];
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_AxisHints  axhints = &hints->axis[dim];
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Segment    seg, limit, link;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt       num_widths = 0;
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_latin_hints_compute_segments( hints,
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                 (AF_Dimension)dim );
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin_hints_link_segments( hints,
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      (AF_Dimension)dim );
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg   = axhints->segments;
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        limit = seg + axhints->num_segments;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; seg < limit; seg++ )
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          link = seg->link;
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* we only consider stem segments there! */
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( link && link->link == seg && link > seg )
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  dist;
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = seg->pos - link->pos;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 0 )
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = -dist;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( num_widths < AF_LATIN_MAX_WIDTHS )
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              axis->widths[ num_widths++ ].org = dist;
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_sort_widths( num_widths, axis->widths );
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->width_count = num_widths;
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinAxis  axis = &metrics->axis[dim];
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        stdw;
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        stdw = ( axis->width_count > 0 )
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 ? axis->widths[0].org
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 : AF_LATIN_CONSTANT( metrics, 50 );
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* let's try 20% of the smallest width */
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->edge_distance_threshold = stdw / 5;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->standard_width          = stdw;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        axis->extra_light             = 0;
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_done( hints );
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LATIN_MAX_TEST_CHARACTERS  12
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
171295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static const char af_latin_blue_chars[AF_LATIN_MAX_BLUES]
172295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                       [AF_LATIN_MAX_TEST_CHARACTERS + 1] =
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "THEZOCQS",
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "HEZLOCUS",
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "fijkdbh",
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "xzroesc",
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "xzroesc",
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "pqgjy"
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
183aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Find all blue zones.  Flat segments give the reference points, */
184aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* round segments the overshoot positions.                        */
185aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_metrics_init_blues( AF_LatinMetrics  metrics,
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_Face          face )
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_flats;
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_rounds;
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        bb;
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinBlue  blue;
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_GlyphSlot  glyph = face->glyph;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we compute the blues simply by loading each character from the    */
202aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                */
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "blue zones computation\n" ));
206aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "------------------------------------------------\n" ));
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  p     = af_latin_blue_chars[bb];
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_ref;
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_shoot;
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
216aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      FT_TRACE5(( "blue %3d: ", bb ));
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_flats  = 0;
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_rounds = 0;
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; p < limit && *p; p++ )
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt     glyph_index;
224295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        FT_Pos      best_y; /* same as points.y */
225295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        FT_Int      best_point, best_first, best_last;
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  points;
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool     round = 0;
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
230aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "'%c'", *p ));
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* load the character in the face -- skip unknown or empty ones */
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( glyph_index == 0 )
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error || glyph->outline.n_points <= 0 )
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now compute min or max point indices and coordinates */
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = glyph->outline.points;
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_point  = -1;
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_y      = 0;  /* make compiler happy */
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_first  = 0;  /* ditto */
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_last   = 0;  /* ditto */
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  nn;
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  first = 0;
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  last  = -1;
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          for ( nn = 0;
255aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                nn < glyph->outline.n_contours;
256aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                first = last + 1, nn++ )
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  old_best_point = best_point;
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  pp;
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            last = glyph->outline.contours[nn];
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* Avoid single-point contours since they are never rasterized. */
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* In some fonts, they correspond to mark attachment points     */
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* which are way outside of the glyph's real outline.           */
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( last <= first )
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                continue;
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( AF_LATIN_IS_TOP_BLUE( bb ) )
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              for ( pp = first; pp <= last; pp++ )
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( best_point < 0 || points[pp].y > best_y )
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                {
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_point = pp;
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_y     = points[pp].y;
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                }
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              for ( pp = first; pp <= last; pp++ )
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( best_point < 0 || points[pp].y < best_y )
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                {
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_point = pp;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_y     = points[pp].y;
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                }
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( best_point != old_best_point )
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              best_first = first;
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              best_last  = last;
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
295aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "%5d", best_y ));
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now check whether the point belongs to a straight or round   */
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* segment; we first need to find in which contour the extremum */
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* lies, then inspect its previous and next points              */
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( best_point >= 0 )
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  prev, next;
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist;
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now look for the previous and next points that are not on the */
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* same Y coordinate.  Threshold the `closeness'...              */
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          prev = best_point;
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          next = prev;
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( prev > best_first )
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              prev--;
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              prev = best_last;
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = points[prev].y - best_y;
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < -5 || dist > 5 )
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( prev != best_point );
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( next < best_last )
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next++;
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next = best_first;
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = points[next].y - best_y;
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < -5 || dist > 5 )
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( next != best_point );
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
338aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* now set the `round' flag depending on the segment's kind */
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          round = FT_BOOL(
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
343aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( round )
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rounds[num_rounds++] = best_y;
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          flats[num_flats++]   = best_y;
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
352aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      FT_TRACE5(( "\n" ));
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 && num_rounds == 0 )
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we couldn't find a single glyph to compute this blue zone,
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we will simply ignore it then
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         */
360aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "empty\n" ));
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we have computed the contents of the `rounds' and `flats' tables, */
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now determine the reference and overshoot position of the blue -- */
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we simply take the median value after a simple sort               */
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_rounds, rounds );
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_flats,  flats );
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue       = & axis->blues[axis->blue_count];
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_ref   = & blue->ref.org;
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_shoot = & blue->shoot.org;
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->blue_count++;
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 )
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( num_rounds == 0 )
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = flats[num_flats / 2];
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   = flats[num_flats / 2];
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* there are sometimes problems: if the overshoot position of top     */
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones is under its reference position, or the opposite for bottom  */
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones.  We must thus check everything there and correct the errors */
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *blue_shoot != *blue_ref )
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   ref      = *blue_ref;
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   shoot    = *blue_shoot;
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool  over_ref = FT_BOOL( shoot > ref );
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
403aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          *blue_ref   =
404aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          *blue_shoot = ( shoot + ref ) / 2;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue->flags = 0;
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( AF_LATIN_IS_TOP_BLUE( bb ) )
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags |= AF_LATIN_BLUE_TOP;
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
412295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner       * The following flag is used later to adjust the y and x scales
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * in order to optimize the pixel grid alignment of the top of small
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * letters.
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( bb == AF_LATIN_BLUE_SMALL_TOP )
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
419aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
422aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "\n" ));
423aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return;
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Check whether all ASCII digits have the same advance width. */
429aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
430295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_LOCAL_DEF( void )
431295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  af_latin_metrics_check_digits( AF_LatinMetrics  metrics,
432295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 FT_Face          face )
433295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
434295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   i;
435295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Bool   started = 0, same_width = 1;
436295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Fixed  advance, old_advance = 0;
437295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
438295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
439295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* digit `0' is 0x30 in all supported charmaps                 */
440295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    for ( i = 0x30; i <= 0x39; i++ )
441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
442295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_UInt  glyph_index;
443295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
444295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
445295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      glyph_index = FT_Get_Char_Index( face, i );
446295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( glyph_index == 0 )
447295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
448295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
449295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( FT_Get_Advance( face, glyph_index,
450295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_SCALE         |
451295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_HINTING       |
452295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_IGNORE_TRANSFORM,
453295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           &advance ) )
454295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
455295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
456295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( started )
457295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
458295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( advance != old_advance )
459295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
460295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          same_width = 0;
461295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          break;
462295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
463295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
464295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
465295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
466295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        old_advance = advance;
467295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        started     = 1;
468295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
469295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
470295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
471295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    metrics->root.digits_have_same_width = same_width;
472295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
473295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
474295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
475aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Initialize global metrics. */
476aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_metrics_init( AF_LatinMetrics  metrics,
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Face          face )
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error = AF_Err_Ok;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CharMap  oldmap = face->charmap;
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     ee;
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Encoding  latin_encodings[] =
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_UNICODE,
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_APPLE_ROMAN,
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_STANDARD,
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_LATIN_1,
491aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_NONE  /* end of list */
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->units_per_em = face->units_per_EM;
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do we have a latin charmap in there? */
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Select_Charmap( face, latin_encodings[ee] );
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !error )
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* For now, compute the standard width and height from the `o'. */
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin_metrics_init_widths( metrics, face, 'o' );
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin_metrics_init_blues( metrics, face );
511295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      af_latin_metrics_check_digits( metrics, face );
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Set_Charmap( face, oldmap );
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return AF_Err_Ok;
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
519aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Adjust scaling value, then scale and shift widths   */
520aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* and blue zones (if applicable) for given dimension. */
521aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_metrics_scale_dim( AF_LatinMetrics  metrics,
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              AF_Scaler        scaler,
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              AF_Dimension     dim )
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        delta;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt       nn;
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->x_scale;
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->x_delta;
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->y_scale;
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->y_delta;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis = &metrics->axis[dim];
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( axis->org_scale == scale && axis->org_delta == delta )
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_scale = scale;
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_delta = delta;
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * correct X and Y scale to optimize the alignment of the top of small
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * letters to the pixel grid
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinAxis  Axis = &metrics->axis[AF_DIMENSION_VERT];
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinBlue  blue = NULL;
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < Axis->blue_count; nn++ )
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue = &Axis->blues[nn];
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( blue )
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  fitted = ( scaled + 40 ) & ~63;
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( scaled != fitted )
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dim == AF_DIMENSION_HORZ )
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( fitted < scaled )
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scale -= scale / 50;  /* scale *= 0.98 */
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dim == AF_DIMENSION_VERT )
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            scale = FT_MulDiv( scale, fitted, scaled );
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->scale = scale;
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->delta = delta;
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_scale = scale;
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_delta = delta;
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_scale = scale;
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_delta = delta;
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
606aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* scale the widths */
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < axis->width_count; nn++ )
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  width = axis->widths + nn;
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->cur = FT_MulFix( width->org, scale );
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->fit = width->cur;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* an extra-light axis corresponds to a standard width that is */
617aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* smaller than 5/8 pixels                                     */
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->extra_light =
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* scale the blue zones */
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < axis->blue_count; nn++ )
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = &axis->blues[nn];
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        dist;
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.fit   = blue->ref.cur;
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.fit = blue->shoot.cur;
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a blue zone is only active if it is less than 3/4 pixels tall */
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist <= 48 && dist >= -48 )
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
640aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
641aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_Pos  delta1;
642aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
643aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_Pos  delta2;
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
646aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* use discrete values for blue zone widths */
647aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
648aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
649aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
650aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* generic, original code */
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta1 = blue->shoot.org - blue->ref.org;
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = delta1;
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = FT_MulFix( delta2, scale );
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta2 < 32 )
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 0;
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta2 < 64 )
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = FT_PIX_ROUND( delta2 );
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->shoot.fit = blue->ref.fit + delta2;
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
671aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#else
672aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
673aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* simplified version due to abs(dist) <= 48 */
674aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          delta2 = dist;
675aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          if ( dist < 0 )
676aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            delta2 = -delta2;
677aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
678aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          if ( delta2 < 32 )
679aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            delta2 = 0;
680aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          else if ( delta < 48 )
681aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            delta2 = 32;
682aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          else
683aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            delta2 = 64;
684aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
685aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          if ( dist < 0 )
686aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            delta2 = -delta2;
687aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
688aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
689aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          blue->shoot.fit = blue->ref.fit - delta2;
690aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
691aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
692aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->flags |= AF_LATIN_BLUE_ACTIVE;
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
700aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Scale global values in both directions. */
701aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_metrics_scale( AF_LatinMetrics  metrics,
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          AF_Scaler        scaler )
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.render_mode = scaler->render_mode;
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.face        = scaler->face;
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****           L A T I N   G L Y P H   A N A L Y S I S             *****/
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
722aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
723aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Walk over all contours and compute its segments. */
724aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_compute_segments( AF_GlyphHints  hints,
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   AF_Dimension   dim )
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory        = hints->memory;
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error         = AF_Err_Ok;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment       = NULL;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SegmentRec seg0;
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour       = hints->contours;
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour_limit = contour + hints->num_contours;
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  major_dir, segment_dir;
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ZERO( &seg0 );
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.score = 32000;
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.flags = AF_EDGE_NORMAL;
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    major_dir   = (AF_Direction)FT_ABS( axis->major_dir );
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment_dir = major_dir;
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_segments = 0;
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* set up (u,v) in each point */
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fx;
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fy;
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fy;
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fx;
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do each contour separately */
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point   =  contour[0];
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  last    =  point->prev;
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      int       on_edge =  0;
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos    min_pos =  32000;  /* minimum segment pos != min_coord */
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos    max_pos = -32000;  /* maximum segment pos != max_coord */
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Bool   passed;
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point == last )  /* skip singletons -- just in case */
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ABS( last->out_dir )  == major_dir &&
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           FT_ABS( point->out_dir ) == major_dir )
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* we are already on an edge, try to locate its start */
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = point;
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (;;)
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->prev;
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( FT_ABS( point->out_dir ) != major_dir )
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point = point->next;
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == last )
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last   = point;
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      passed = 0;
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (;;)
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  u, v;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( on_edge )
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u = point->u;
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( u < min_pos )
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min_pos = u;
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( u > max_pos )
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            max_pos = u;
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->out_dir != segment_dir || point == last )
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* we are just leaving an edge; record a new segment! */
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->last = point;
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* a segment is round if either its first or last point */
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* is a control point                                   */
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ( segment->first->flags | point->flags ) &
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   AF_FLAG_CONTROL                        )
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segment->flags |= AF_EDGE_ROUND;
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* compute segment size */
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min_pos = max_pos = point->v;
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            v = segment->first->v;
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( v < min_pos )
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min_pos = v;
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( v > max_pos )
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max_pos = v;
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->min_coord = (FT_Short)min_pos;
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->max_coord = (FT_Short)max_pos;
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height    = (FT_Short)( segment->max_coord -
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             segment->min_coord );
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            on_edge = 0;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment = NULL;
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* fallthrough */
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now exit if we are at the start/end point */
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point == last )
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( passed )
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          passed = 1;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !on_edge && FT_ABS( point->out_dir ) == major_dir )
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* this is the start of a new segment! */
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment_dir = (AF_Direction)point->out_dir;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* clear all segment fields */
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error = af_axis_hints_new_segment( axis, memory, &segment );
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error )
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Exit;
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment[0]        = seg0;
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment->dir      = (FT_Char)segment_dir;
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min_pos = max_pos = point->u;
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment->first    = point;
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment->last     = point;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          on_edge           = 1;
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->next;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    } /* contours */
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now slightly increase the height of segments when this makes */
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sense -- this is used to better detect and ignore serifs     */
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments     = axis->segments;
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments_end = segments + axis->num_segments;
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( segment = segments; segment < segments_end; segment++ )
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first   = segment->first;
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  last    = segment->last;
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    first_v = first->v;
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    last_v  = last->v;
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first == last )
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_v < last_v )
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  p;
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < first_v )
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( first_v - p->v ) >> 1 ) );
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > last_v )
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - last_v ) >> 1 ) );
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  p;
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > first_v )
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - first_v ) >> 1 ) );
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < last_v )
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( last_v - p->v ) >> 1 ) );
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
943aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Link segments to form stems and serifs. */
944aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_link_segments( AF_GlyphHints  hints,
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                AF_Dimension   dim )
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        len_threshold, len_score;
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg1, seg2;
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( len_threshold == 0 )
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      len_threshold = 1;
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
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
970aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* search for stems having opposite directions, */
971aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* with seg1 to the `left' of seg2              */
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segments; seg2 < segment_limit; seg2++ )
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
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
978aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
979aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        {
980aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* compute distance between the two segments */
981aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_Pos  dist = pos2 - pos1;
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  min = seg1->min_coord;
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  max = seg1->max_coord;
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  len, score;
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( min < seg2->min_coord )
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = seg2->min_coord;
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( max > seg2->max_coord )
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = seg2->max_coord;
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
993aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* compute maximum coordinate difference of the two segments */
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            len = max - min;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( len >= len_threshold )
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
997aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            /* small coordinate differences cause a higher score, and     */
998aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            /* segments with a greater distance cause a higher score also */
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              score = dist + len_score / len;
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1001aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            /* and we search for the smallest score */
1002aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            /* of the sum of the two values         */
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg1->score )
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->score = score;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->link  = seg2;
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg2->score )
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->score = score;
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->link  = seg1;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1019aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* now compute the `serif' segments, cf. explanations in `afhints.h' */
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      seg2 = seg1->link;
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg2 )
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg2->link != seg1 )
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->link  = 0;
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->serif = seg2->link;
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
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1036aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Link segments to edges, using feature analysis for selection. */
1037aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_compute_edges( AF_GlyphHints  hints,
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                AF_Dimension   dim )
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis   = &hints->axis[dim];
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error  = AF_Err_Ok;
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory = hints->memory;
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1051aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  up_dir;
1053aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        edge_distance_threshold;
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        segment_length_threshold;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges = 0;
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         : hints->y_scale;
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1064aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          : AF_DIR_RIGHT;
1067aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1070aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner     *  We ignore all segments that are less than 1 pixel in length
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  to avoid many problems with serif fonts.  We compute the
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  corresponding threshold in font units.
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment_length_threshold = 0;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1081aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* We begin by generating a sorted table of edges for the current    */
1082aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* direction.  To do so, we simply scan each segment and try to find */
1083aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* an edge in our table that corresponds to its position.            */
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* If no edge is found, we create and insert a new edge in the       */
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sorted table.  Otherwise, we simply add the segment to the edge's */
1087aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* list which gets processed in the second step to compute the       */
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* edge's properties.                                                */
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1090aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* Note that the table of edges is sorted along the segment/edge     */
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* position.                                                         */
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1095aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* assure that edge distance threshold is at most 0.25px */
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    {
1106aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      AF_Edge  found = NULL;
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           2 * seg->height < 3 * segment_length_threshold )
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* look for an edge corresponding to the segment */
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ee = 0; ee < axis->num_edges; ee++ )
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge  edge = axis->edges + ee;
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   dist;
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = seg->pos - edge->fpos;
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 0 )
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < edge_distance_threshold && edge->dir == seg->dir )
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          found = edge;
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !found )
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge  edge;
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* insert a new edge in the list and */
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* sort according to the position    */
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_axis_hints_new_edge( axis, seg->pos,
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        (AF_Direction)seg->dir,
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        memory, &edge );
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* add the segment to the new edge's list */
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ZERO( edge );
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->first    = seg;
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->last     = seg;
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir      = seg->dir;
1156aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        edge->fpos     = seg->pos;
1157aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        edge->opos     = FT_MulFix( seg->pos, scale );
1158aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        edge->pos      = edge->opos;
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next = seg;
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if an edge was found, simply add the segment to the edge's */
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* list                                                       */
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next         = found->first;
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last->edge_next = seg;
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last            = seg;
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Good, we will now compute each edge's properties according to     */
1175aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* the segments found on its position.  Basically, these are         */
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1177aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /*  - the edge's main direction                                      */
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - stem edge, serif edge or both (which defaults to stem then)    */
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - rounded edge, straight or both (which defaults to straight)    */
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - link for edge                                                  */
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, set the `edge' field in each segment -- this is */
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* required in order to compute edge links                       */
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * Note that removing this loop and setting the `edge' field of each
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * segment directly in the code above slows down execution speed for
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * some reasons on platforms like the Sun.
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edges      = axis->edges;
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge_limit = edges + axis->num_edges;
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge;
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg )
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg->edge = edge;
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg       = seg->edge_next;
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( seg != edge->first );
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1210aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* now compute each edge properties */
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_round    = 0;  /* does it contain round segments?    */
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_straight = 0;  /* does it contain straight segments? */
1215aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  ups         = 0;  /* number of upwards segments         */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  downs       = 0;  /* number of downwards segments       */
1218aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Bool  is_serif;
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for roundness of segment */
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->flags & AF_EDGE_ROUND )
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_round++;
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_straight++;
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1234aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for segment direction */
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->dir == up_dir )
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ups   += seg->max_coord-seg->min_coord;
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            downs += seg->max_coord-seg->min_coord;
1240aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for links -- if seg->serif is set, then seg->link must */
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* be ignored                                                   */
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          is_serif = (FT_Bool)( seg->serif               &&
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge         &&
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge != edge );
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge     edge2;
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Segment  seg2;
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge2 = edge->link;
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg2  = seg->link;
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg2  = seg->serif;
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = edge->serif;
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edge2 )
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  edge_delta;
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  seg_delta;
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge_delta = edge->fpos - edge2->fpos;
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edge_delta < 0 )
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge_delta = -edge_delta;
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg_delta = seg->pos - seg2->pos;
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < 0 )
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg_delta = -seg_delta;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < edge_delta )
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge2 = seg2->edge;
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = seg2->edge;
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->serif   = edge2;
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2->flags |= AF_EDGE_SERIF;
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->link  = edge2;
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg = seg->edge_next;
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( seg != edge->first );
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the round/straight flags */
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags = AF_EDGE_NORMAL;
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_round > 0 && is_round >= is_straight )
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->flags |= AF_EDGE_ROUND;
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the edge's main direction */
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir = AF_DIR_NONE;
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ups > downs )
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)up_dir;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups < downs )
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)-up_dir;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups == downs )
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = 0;  /* both up and down! */
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1316aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* get rid of serifs if link is set                 */
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* XXX: This gets rid of many unpleasant artefacts! */
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*      Example: the `c' in cour.pfa at size 13     */
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif && edge->link )
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->serif = 0;
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1330aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Detect segments and edges for given dimension. */
1331aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_detect_features( AF_GlyphHints  hints,
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  AF_Dimension   dim )
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = af_latin_hints_compute_segments( hints, dim );
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin_hints_link_segments( hints, dim );
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin_hints_compute_edges( hints, dim );
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1346aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1351aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Compute all edges which lie within blue zones. */
1352aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_compute_blue_edges( AF_GlyphHints    hints,
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     AF_LatinMetrics  metrics )
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis       = &hints->axis[ AF_DIMENSION_VERT ];
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge       = axis->edges;
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edge + axis->num_edges;
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  latin      = &metrics->axis[ AF_DIMENSION_VERT ];
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale      = latin->scale;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute which blue zones are active, i.e. have their scaled */
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* size < 3/4 pixels                                           */
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* for each horizontal edge search the blue zone which is closest */
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; edge < edge_limit; edge++ )
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    bb;
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  best_blue = NULL;
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos    best_dist;  /* initial threshold */
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute the initial threshold as a fraction of the EM size */
1376aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* (the value 40 is heuristic)                                */
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      best_dist = FT_MulFix( metrics->units_per_em / 40, scale );
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1379aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      /* assure a minimum distance of 0.5px */
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( best_dist > 64 / 2 )
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_dist = 64 / 2;
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = latin->blues + bb;
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool       is_top_blue, is_major_dir;
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1389aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* skip inactive blue zones (i.e., those that are too large) */
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, check for right edges -- if it is a bottom */
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* zone, check for left edges                                      */
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                                 */
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* of course, that's for TrueType                                  */
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, the edge must be against the major    */
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction; if it is a bottom zone, it must be in the major */
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction                                                  */
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_top_blue ^ is_major_dir )
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist;
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* first of all, compare it to the reference position */
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = edge->fpos - blue->ref.org;
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 0 )
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = -dist;
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = FT_MulFix( dist, scale );
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < best_dist )
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_dist = dist;
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_blue = & blue->ref;
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1420aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* now compare it to the overshoot position and check whether */
1421aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* the edge is rounded, and whether the edge is over the      */
1422aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* reference position of a top zone, or under the reference   */
1423aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* position of a bottom zone                                  */
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_top_blue ^ is_under_ref )
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = edge->fpos - blue->shoot.org;
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 0 )
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = -dist;
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = FT_MulFix( dist, scale );
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < best_dist )
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_dist = dist;
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_blue = & blue->shoot;
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( best_blue )
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->blue_edge = best_blue;
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1452aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Initalize hinting engine. */
1453aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_init( AF_GlyphHints    hints,
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       AF_LatinMetrics  metrics )
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Render_Mode  mode;
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32       scaler_flags, other_flags;
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Face         face = metrics->root.scaler.face;
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  correct x_scale and y_scale if needed, since they may have
1467aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner     *  been modified by `af_latin_metrics_scale_dim' above
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute flags depending on render mode, etc. */
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mode = metrics->root.scaler.render_mode;
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1477aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaler_flags = hints->scaler_flags;
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    other_flags  = 0;
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of vertical stems for the monochrome and
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  horizontal LCD rendering targets only.
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of horizontal stems for the monochrome and
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  vertical LCD rendering targets only.
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_VERT_SNAP;
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We adjust stems to full pixels only if we don't use the `light' mode.
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode != FT_RENDER_MODE_LIGHT )
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO )
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_MONO;
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  In `light' hinting mode we disable horizontal hinting completely.
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We also do it if the face is italic.
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LIGHT                    ||
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = scaler_flags;
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->other_flags  = other_flags;
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1521aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    return AF_Err_Ok;
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1528049d6fea481044fcc000e7782e5bc7046fc70844The 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        *****/
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1533aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Snap a given width in scaled coordinates to one of the */
1534aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* current standard widths.                               */
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_snap_width( AF_Width  widths,
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Int    count,
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_Pos    width )
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     n;
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  best      = 64 + 32 + 2;
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  reference = width;
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  scaled;
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < count; n++ )
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  w;
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  dist;
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      w = widths[n].cur;
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = width - w;
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < 0 )
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = -dist;
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < best )
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best      = dist;
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        reference = w;
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaled = FT_PIX_ROUND( reference );
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( width >= reference )
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width < scaled + 48 )
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width > scaled - 48 )
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return width;
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1581aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Compute the snapped width of a given stem, ignoring very thin ones. */
1582aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* There is a lot of voodoo in this function; changing the hard-coded  */
1583aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* parameters influence the whole hinting process.                     */
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_compute_stem_width( AF_GlyphHints  hints,
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               AF_Dimension   dim,
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_Pos         width,
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               AF_Edge_Flags  base_flags,
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               AF_Edge_Flags  stem_flags )
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis     axis     = & metrics->axis[dim];
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos           dist     = width;
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           sign     = 0;
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          axis->extra_light                      )
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return width;
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dist < 0 )
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -width;
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sign = 1;
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( (  vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* smooth hinting process: very lightly quantize the stem width */
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* leave the widths of serifs alone */
1615aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      if ( ( stem_flags & AF_EDGE_SERIF ) &&
1616aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner           vertical                       &&
1617aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner           ( dist < 3 * 64 )              )
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Done_Width;
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1620aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      else if ( base_flags & AF_EDGE_ROUND )
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 80 )
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( dist < 56 )
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = 56;
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( axis->width_count > 0 )
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* compare to standard width */
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = dist - axis->widths[0].cur;
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 40 )
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = axis->widths[0].cur;
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 48 )
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = 48;
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Done_Width;
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 3 * 64 )
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta  = dist & 63;
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist  &= -64;
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 10 )
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 32 )
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 10;
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 54 )
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 54;
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 32 ) & ~63;
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* strong hinting process: snap the stem width to integer pixels */
1672aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  org_dist = dist;
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( vertical )
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* in the case of vertical hinting, always round */
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the stem heights to integer pixels            */
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist >= 64 )
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 16 ) & ~63;
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_HINTS_DO_MONO( hints ) )
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* monochrome horizontal hinting: snap widths to integer pixels */
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* with a different threshold                                   */
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 64 )
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = 64;
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for horizontal anti-aliased hinting, we adopt a more subtle */
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* approach: we strengthen small stems, round stems whose size */
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 48 )
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 64 ) >> 1;
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( dist < 128 )
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* We only round to an integer width if the corresponding */
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* distortion is less than 1/4 pixel.  Otherwise this     */
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* makes everything worse since the diagonals, which are  */
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* not hinted, appear a lot bolder or thinner than the    */
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* vertical stems.                                        */
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1717295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            FT_Pos  delta;
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 22 ) & ~63;
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = dist - org_dist;
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( delta < 0 )
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta = -delta;
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if (delta >= 16)
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = org_dist;
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 48 )
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = ( dist + 64 ) >> 1;
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* round otherwise to prevent color fringes in LCD mode */
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Done_Width:
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( sign )
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -dist;
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dist;
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1747aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Align one stem edge relative to the previous stem edge. */
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_align_linked_edge( AF_GlyphHints  hints,
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              AF_Dimension   dim,
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              AF_Edge        base_edge,
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              AF_Edge        stem_edge )
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  dist = stem_edge->opos - base_edge->opos;
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  fitted_width = af_latin_compute_stem_width(
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hints, dim, dist,
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)base_edge->flags,
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)stem_edge->flags );
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stem_edge->pos = base_edge->pos + fitted_width;
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1765aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "  LINK: edge %d (opos=%.2f) linked to (%.2f),"
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             "dist was %.2f, now %.2f\n",
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1772aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Shift the coordinates of the `serif' edge by the same amount */
1773aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* as the corresponding `base' edge has been moved already.     */
1774aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_align_serif_edge( AF_GlyphHints  hints,
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             AF_Edge        base,
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             AF_Edge        serif )
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( hints );
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    serif->pos = base->pos + (serif->opos - base->opos);
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                    E D G E   H I N T I N G                      ****/
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
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
1797aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* The main grid-fitting routine. */
1798aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hint_edges( AF_GlyphHints  hints,
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       AF_Dimension   dim )
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis       = &hints->axis[dim];
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges      = axis->edges;
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edges + axis->num_edges;
1806295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_PtrDist    n_edges;
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge;
1808aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    AF_Edge       anchor     = NULL;
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        has_serifs = 0;
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1812aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal"
1813aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                                             : "vertical"));
1814aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we begin by aligning all stems relative to the blue zone */
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if needed -- that's only for horizontal edges            */
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Width  blue;
1823aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        AF_Edge   edge1, edge2; /* these edges form the stem to check */
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue  = edge->blue_edge;
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1 = NULL;
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2 = edge->link;
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( blue )
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge;
1835aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1836aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* flip edges if the other stem is aligned to a blue zone */
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( edge2 && edge2->blue_edge )
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue  = edge2->blue_edge;
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge2;
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2 = edge;
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !edge1 )
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1847aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "  BLUE: edge %d (opos=%.2f) snapped to (%.2f),"
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 "was (%.2f)\n",
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 edge1->pos / 64.0 ));
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->pos    = blue->fit;
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->flags |= AF_EDGE_DONE;
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2 && !edge2->blue_edge )
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin_align_linked_edge( hints, dim, edge1, edge2 );
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->flags |= AF_EDGE_DONE;
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !anchor )
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor = edge;
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1866aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    /* now we align all other stem edges, trying to maintain the */
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relative order of stems in the glyph                     */
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( edge = edges; edge < edge_limit; edge++ )
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge2;
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge->flags & AF_EDGE_DONE )
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip all non-stem edges */
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge2 = edge->link;
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !edge2 )
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        has_serifs++;
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now align the stem */
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* this should not happen, but it's better to be safe */
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge2->blue_edge )
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1889aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "  ASSERTION FAILED for edge %d\n", edge2-edges ));
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin_align_linked_edge( hints, dim, edge2, edge );
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !anchor )
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1898aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* if we reach this if clause, no stem has been aligned yet */
1899aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  org_len, org_center, cur_len;
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  cur_pos1, error1, error2, u_off, d_off;
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len = edge2->opos - edge->opos;
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin_compute_stem_width(
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    hints, dim, org_len,
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge->flags,
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge2->flags );
1909aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1910aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* some voodoo to specially round edges for small stem widths; */
1911aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* the idea is to align the center of a stem, then shifting    */
1912aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        /* the stem edges to suitable positions                        */
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len <= 64 )
1914aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        {
1915aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* width <= 1px */
1916aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          u_off = 32;
1917aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          d_off = 32;
1918aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        }
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1921aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          /* 1px < width < 1.5px */
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = 38;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          d_off = 26;
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len < 96 )
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_center = edge->opos + ( org_len >> 1 );
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos1   = FT_PIX_ROUND( org_center );
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error1 = org_center - ( cur_pos1 - u_off );
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < 0 )
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error1 = -error1;
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error2 = org_center - ( cur_pos1 + d_off );
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error2 < 0 )
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error2 = -error2;
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < error2 )
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 -= u_off;
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 += d_off;
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos  = cur_pos1 - cur_len / 2;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->pos = edge->pos + cur_len;
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1950aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        FT_TRACE5(( "  ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 "snapped to (%.2f) (%.2f)\n",
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 edge-edges, edge->opos / 64.0,
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 edge2-edges, edge2->opos / 64.0,
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 edge->pos / 64.0, edge2->pos / 64.0 ));
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        anchor = edge;
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin_align_linked_edge( hints, dim, edge, edge2 );
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  org_pos, org_len, org_center, cur_len;
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  cur_pos1, cur_pos2, delta1, delta2;
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_pos    = anchor->pos + ( edge->opos - anchor->opos );
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len    = edge2->opos - edge->opos;
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_center = org_pos + ( org_len >> 1 );
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin_compute_stem_width(
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   hints, dim, org_len,
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge->flags,
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge2->flags );
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2->flags & AF_EDGE_DONE )
1977aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        {
1978aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "  ADJUST: edge %d (pos=%.2f) moved to %.2f\n",
1979aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge - edges, edge->pos / 64.0,
1980aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      ( edge2->pos - cur_len ) / 64.0 ));
1981aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge2->pos - cur_len;
1983aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        }
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( cur_len < 96 )
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  u_off, d_off;
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos1 = FT_PIX_ROUND( org_center );
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if (cur_len <= 64 )
1993aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          {
1994aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            u_off = 32;
1995aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            d_off = 32;
1996aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          }
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            u_off = 38;
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            d_off = 26;
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta1 = org_center - ( cur_pos1 - u_off );
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta1 = -delta1;
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = org_center - ( cur_pos1 + d_off );
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta2 < 0 )
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < delta2 )
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 -= u_off;
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 += d_off;
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos  = cur_pos1 - cur_len / 2;
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->pos = cur_pos1 + cur_len / 2;
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2019aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   "snapped to (%.2f) and (%.2f)\n",
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge-edges, edge->opos / 64.0,
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge2-edges, edge2->opos / 64.0,
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge->pos / 64.0, edge2->pos / 64.0 ));
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_pos    = anchor->pos + ( edge->opos - anchor->opos );
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_len    = edge2->opos - edge->opos;
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_center = org_pos + ( org_len >> 1 );
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_len    = af_latin_compute_stem_width(
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         hints, dim, org_len,
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         (AF_Edge_Flags)edge->flags,
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         (AF_Edge_Flags)edge2->flags );
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos1   = FT_PIX_ROUND( org_pos );
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta1     = cur_pos1 + ( cur_len >> 1 ) - org_center;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta1 = -delta1;
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos2   = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2     = cur_pos2 + ( cur_len >> 1 ) - org_center;
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta2 < 0 )
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos  = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->pos = edge->pos + cur_len;
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2049aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   "snapped to (%.2f) and (%.2f)\n",
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge-edges, edge->opos / 64.0,
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge2-edges, edge2->opos / 64.0,
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge->pos / 64.0, edge2->pos / 64.0 ));
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags  |= AF_EDGE_DONE;
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2061aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "  BOUND: %d (pos=%.2f) to (%.2f)\n",
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make sure that lowercase m's maintain their symmetry */
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* In general, lowercase m's have six vertical edges if they are sans */
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* serif, or twelve if they are with serifs.  This implementation is  */
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* based on that assumption, and seems to work very well with most    */
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* faces.  However, if for a certain face this assumption is not      */
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* true, the m is just rendered like before.  In addition, any stem   */
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* correction will only be applied to symmetrical glyphs (even if the */
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* glyph is not an m), so the potential for unwanted distortion is    */
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relatively low.                                                    */
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We don't handle horizontal edges since we can't easily assure that */
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the third (lowest) stem aligns with the base line; it might end up */
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* one pixel higher or lower.                                         */
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    n_edges = edge_limit - edges;
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge1, edge2, edge3;
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos   dist1, dist2, span, delta;
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( n_edges == 6 )
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1 = edges;
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2 = edges + 2;
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge3 = edges + 4;
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1 = edges + 1;
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2 = edges + 5;
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge3 = edges + 9;
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist1 = edge2->opos - edge1->opos;
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist2 = edge3->opos - edge2->opos;
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span = dist1 - dist2;
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( span < 0 )
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span = -span;
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( span < 8 )
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge3->pos -= delta;
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge3->link )
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge3->link->pos -= delta;
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* move the serifs along with the stem */
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n_edges == 12 )
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ( edges + 8 )->pos -= delta;
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ( edges + 11 )->pos -= delta;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge3->flags |= AF_EDGE_DONE;
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge3->link )
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge3->link->flags |= AF_EDGE_DONE;
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( has_serifs || !anchor )
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  now hint the remaining edges (serifs and single) in order
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  to complete our processing
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = 1000;
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif )
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = edge->serif->opos - edge->opos;
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < 64 + 16 )
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin_align_serif_edge( hints, edge->serif, edge );
2156aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "  SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   "aligned to (%.2f)\n",
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge-edges, edge->opos / 64.0,
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge->serif - edges, edge->serif->opos / 64.0,
2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   edge->pos / 64.0 ));
2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( !anchor )
2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor    = edge;
2166aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner          FT_TRACE5(( "  SERIF_ANCHOR: edge %d (opos=%.2f)"
2167aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      " snapped to (%.2f)\n",
2168aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Edge  before, after;
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( before = edge - 1; before >= edges; before-- )
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->flags & AF_EDGE_DONE )
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( after = edge + 1; after < edge_limit; after++ )
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( after->flags & AF_EDGE_DONE )
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( before >= edges && before < edge   &&
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               after < edge_limit && after > edge )
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
21860a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( after->opos == before->opos )
21870a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos;
21880a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            else
21890a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos +
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_MulDiv( edge->opos - before->opos,
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->pos - before->pos,
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->opos - before->opos );
2193aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
2194aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "  SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     "from %d (opos=%.2f)\n",
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     edge-edges, edge->opos / 64.0,
2197aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        edge->pos / 64.0,
2198aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        before - edges, before->opos / 64.0 ));
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge->pos = anchor->pos +
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
2204aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
2205aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner            FT_TRACE5(( "  SERIF_LINK2: edge %d (opos=%.2f)"
2206aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                        " snapped to (%.2f)\n",
2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge + 1 < edge_limit        &&
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge[1].flags & AF_EDGE_DONE &&
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge->pos > edge[1].pos      )
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[1].pos;
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2222aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
2223aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_TRACE5(( "\n" ));
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2227aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner  /* Apply the complete hinting algorithm to a latin glyph. */
2228aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin_hints_apply( AF_GlyphHints    hints,
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Outline*      outline,
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        AF_LatinMetrics  metrics )
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int       dim;
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2238aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    error = af_glyph_hints_reload( hints, outline );
2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* analyze glyph outline */
2243aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         AF_HINTS_DO_HORIZONTAL( hints ) )
2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_HORIZONTAL( hints ) )
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_VERTICAL( hints ) )
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin_hints_compute_blue_edges( hints, metrics );
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* grid-fit the outline */
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2267aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2268aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner      if ( dim == AF_DIMENSION_HORZ                                 &&
2269aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner           metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_WarperRec  warper;
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Fixed      scale;
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        delta;
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2276aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        af_warper_compute( &warper, hints, (AF_Dimension)dim,
2277aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                           &scale, &delta );
2278aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner        af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
2279aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner                                  scale, delta );
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin_hint_edges( hints, (AF_Dimension)dim );
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_save( hints, outline );
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****              L A T I N   S C R I P T   C L A S S              *****/
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* XXX: this should probably fine tuned to differentiate better between */
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*      scripts...                                                      */
2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const AF_Script_UniRangeRec  af_latin_uniranges[] =
2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2314295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0020UL,  0x007FUL ),  /* Basic Latin (no control chars) */
2315295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x00A0UL,  0x00FFUL ),  /* Latin-1 Supplement (no control chars) */
2316295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0100UL,  0x017FUL ),  /* Latin Extended-A */
2317295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0180UL,  0x024FUL ),  /* Latin Extended-B */
2318295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0250UL,  0x02AFUL ),  /* IPA Extensions */
2319295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x02B0UL,  0x02FFUL ),  /* Spacing Modifier Letters */
2320295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0300UL,  0x036FUL ),  /* Combining Diacritical Marks */
2321295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
2322295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0400UL,  0x04FFUL ),  /* Cyrillic */
2323295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x0500UL,  0x052FUL ),  /* Cyrillic Supplement */
2324295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x1D00UL,  0x1D7FUL ),  /* Phonetic Extensions */
2325295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x1D80UL,  0x1DBFUL ),  /* Phonetic Extensions Supplement */
2326295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x1DC0UL,  0x1DFFUL ),  /* Combining Diacritical Marks Supplement */
2327295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x1E00UL,  0x1EFFUL ),  /* Latin Extended Additional */
2328295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended */
2329295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x2000UL,  0x206FUL ),  /* General Punctuation */
2330295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x2070UL,  0x209FUL ),  /* Superscripts and Subscripts */
2331295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x20A0UL,  0x20CFUL ),  /* Currency Symbols */
2332295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x2150UL,  0x218FUL ),  /* Number Forms */
2333295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x2460UL,  0x24FFUL ),  /* Enclosed Alphanumerics */
2334295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x2C60UL,  0x2C7FUL ),  /* Latin Extended-C */
2335295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0x2DE0UL,  0x2DFFUL ),  /* Cyrillic Extended-A */
2336295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0xA640UL,  0xA69FUL ),  /* Cyrillic Extended-B */
2337295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0xA720UL,  0xA7FFUL ),  /* Latin Extended-D */
2338295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(  0xFB00UL,  0xFB06UL ),  /* Alphab. Present. Forms (Latin Ligs) */
2339295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ),  /* Mathematical Alphanumeric Symbols */
2340295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC(       0UL,       0UL )
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
2342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2344295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,
2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SCRIPT_LATIN,
2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin_uniranges,
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    sizeof( AF_LatinMetricsRec ),
2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_InitMetricsFunc) af_latin_metrics_init,
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_ScaleMetricsFunc)af_latin_metrics_scale,
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_DoneMetricsFunc) NULL,
2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_InitHintsFunc)   af_latin_hints_init,
2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_ApplyHintsFunc)  af_latin_hints_apply
2356295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  )
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
2360