1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner/*  aflatin2.c                                                             */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    Auto-fitter hinting routines for latin script (body).                */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 2003-2013 by                                                 */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include FT_ADVANCES_H
20295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
21a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "afglobal.h"
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin.h"
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin2.h"
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h"
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27c3ee10bfa1f76a18500b487de9c85757375b48f3David '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
31c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
32c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*************************************************************************/
33c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*                                                                       */
34c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
35c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
36c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /* messages during execution.                                            */
37c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  /*                                                                       */
38c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#undef  FT_COMPONENT
39c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define FT_COMPONENT  trace_aflatin2
40c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
41c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
44c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                    AF_Dimension   dim );
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_link_segments( AF_GlyphHints  hints,
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 AF_Dimension   dim );
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****            L A T I N   G L O B A L   M E T R I C S            *****/
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
60a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                 FT_Face          face )
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scan the array of segments in each direction */
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_GlyphHintsRec  hints[1];
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_init( hints, face->memory );
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->axis[AF_DIMENSION_VERT].width_count = 0;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Error             error;
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt              glyph_index;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      int                  dim;
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinMetricsRec   dummy[1];
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Scaler            scaler = &dummy->root.scaler;
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      glyph_index = FT_Get_Char_Index( face,
80a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                       metrics->root.clazz->standard_char );
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph_index == 0 )
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error || face->glyph->outline.n_points <= 0 )
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ZERO( dummy );
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dummy->units_per_em = metrics->units_per_em;
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->x_scale     = scaler->y_scale = 0x10000L;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler->x_delta     = scaler->y_delta = 0;
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_latin2_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_latin2_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 )
137e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang              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
171c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
172c3ee10bfa1f76a18500b487de9c85757375b48f3David '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
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init_blues( AF_LatinMetrics  metrics,
185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                FT_Face          face )
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_flats;
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        num_rounds;
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        bb;
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinBlue  blue;
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_GlyphSlot  glyph = face->glyph;
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
198c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* we compute the blues simply by loading each character from the     */
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
200c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
202a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_TRACE5(( "blue zones computation\n"
203a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                "======================\n\n" ));
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  p     = af_latin2_blue_chars[bb];
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_ref;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos*      blue_shoot;
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_TRACE5(( "blue zone %d:\n", bb ));
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_flats  = 0;
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      num_rounds = 0;
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; p < limit && *p; p++ )
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt     glyph_index;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int      best_point, best_y, best_first, best_last;
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Vector*  points;
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool     round;
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* load the character in the face -- skip unknown or empty ones */
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( glyph_index == 0 )
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error || glyph->outline.n_points <= 0 )
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now compute min or max point indices and coordinates */
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = glyph->outline.points;
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_point  = -1;
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_y      = 0;  /* make compiler happy */
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_first  = 0;  /* ditto */
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best_last   = 0;  /* ditto */
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  nn;
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  first = 0;
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  last  = -1;
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  old_best_point = best_point;
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  pp;
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            last = glyph->outline.contours[nn];
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* Avoid single-point contours since they are never rasterized. */
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* In some fonts, they correspond to mark attachment points     */
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* which are way outside of the glyph's real outline.           */
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( last == first )
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                continue;
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( AF_LATIN_IS_TOP_BLUE( bb ) )
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              for ( pp = first; pp <= last; pp++ )
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( best_point < 0 || points[pp].y > best_y )
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                {
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_point = pp;
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_y     = points[pp].y;
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                }
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              for ( pp = first; pp <= last; pp++ )
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( best_point < 0 || points[pp].y < best_y )
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                {
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_point = pp;
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  best_y     = points[pp].y;
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                }
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( best_point != old_best_point )
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              best_first = first;
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              best_last  = last;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE5(( "  %c  %d", *p, best_y ));
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* now check whether the point belongs to a straight or round   */
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* segment; we first need to find in which contour the extremum */
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* lies, then inspect its previous and next points              */
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_Pos  best_x = points[best_point].x;
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Int  start, end, prev, next;
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist;
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now look for the previous and next points that are not on the */
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* same Y coordinate.  Threshold the `closeness'...              */
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          start = end = best_point;
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
305a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            prev = start - 1;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( prev < best_first )
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              prev = best_last;
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
309a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            dist = FT_ABS( points[prev].y - best_y );
310a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* accept a small distance or a small angle (both values are */
311a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( dist > 5 )
313a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
314a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                break;
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start = prev;
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( start != best_point );
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
322a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            next = end + 1;
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( next > best_last )
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next = best_first;
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
326a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            dist = FT_ABS( points[next].y - best_y );
327a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( dist > 5 )
328a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
329a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                break;
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end = next;
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( end != best_point );
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now, set the `round' flag depending on the segment's kind */
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          round = FT_BOOL(
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
340a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( round )
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rounds[num_rounds++] = best_y;
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          flats[num_flats++]   = best_y;
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 && num_rounds == 0 )
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we couldn't find a single glyph to compute this blue zone,
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         *  we will simply ignore it then
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         */
355a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE5(( "  empty\n" ));
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we have computed the contents of the `rounds' and `flats' tables, */
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now determine the reference and overshoot position of the blue -- */
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we simply take the median value after a simple sort               */
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_rounds, rounds );
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_sort_pos( num_flats,  flats );
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue       = & axis->blues[axis->blue_count];
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_ref   = & blue->ref.org;
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      blue_shoot = & blue->shoot.org;
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->blue_count++;
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_flats == 0 )
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( num_rounds == 0 )
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   =
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = flats[num_flats / 2];
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_ref   = flats[num_flats / 2];
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *blue_shoot = rounds[num_rounds / 2];
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* there are sometimes problems: if the overshoot position of top     */
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones is under its reference position, or the opposite for bottom  */
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* zones.  We must thus check everything there and correct the errors */
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *blue_shoot != *blue_ref )
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   ref      = *blue_ref;
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   shoot    = *blue_shoot;
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool  over_ref = FT_BOOL( shoot > ref );
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
398a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          *blue_ref   =
400a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          *blue_shoot = ( shoot + ref ) / 2;
401a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
402a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE5(( "  [overshoot smaller than reference,"
403a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      " taking mean value]\n" ));
404a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
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      /*
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * The following flags 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
419a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_TRACE5(( "    -> reference = %ld\n"
420a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                  "       overshoot = %ld\n",
421a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                  *blue_ref, *blue_shoot ));
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return;
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_LOCAL_DEF( void )
429295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  af_latin2_metrics_check_digits( AF_LatinMetrics  metrics,
430295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                  FT_Face          face )
431295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
432295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   i;
433295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Bool   started = 0, same_width = 1;
434295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Fixed  advance, old_advance = 0;
435295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
436295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
437295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* check whether all ASCII digits have the same advance width; */
438295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* digit `0' is 0x30 in all supported charmaps                 */
439295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    for ( i = 0x30; i <= 0x39; i++ )
440295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_UInt  glyph_index;
442295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
443295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
444295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      glyph_index = FT_Get_Char_Index( face, i );
445295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( glyph_index == 0 )
446295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
447295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
448295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( FT_Get_Advance( face, glyph_index,
449295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_SCALE         |
450295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_NO_HINTING       |
451295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_LOAD_IGNORE_TRANSFORM,
452295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           &advance ) )
453295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        continue;
454295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
455295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( started )
456295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
457295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( advance != old_advance )
458295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
459295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          same_width = 0;
460295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          break;
461295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
462295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
463295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
464295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
465295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        old_advance = advance;
466295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        started     = 1;
467295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
468295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
469295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
470295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    metrics->root.digits_have_same_width = same_width;
471295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
472295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
473295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_init( AF_LatinMetrics  metrics,
476c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                          FT_Face          face )
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
478a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error    error  = FT_Err_Ok;
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CharMap  oldmap = face->charmap;
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     ee;
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Encoding  latin_encodings[] =
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_UNICODE,
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_APPLE_ROMAN,
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_STANDARD,
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_ADOBE_LATIN_1,
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ENCODING_NONE  /* end of list */
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->units_per_em = face->units_per_EM;
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do we have a latin charmap in there? */
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Select_Charmap( face, latin_encodings[ee] );
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !error )
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
504a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      af_latin2_metrics_init_widths( metrics, face );
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_metrics_init_blues( metrics, face );
506295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      af_latin2_metrics_check_digits( metrics, face );
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Set_Charmap( face, oldmap );
510a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_scale_dim( AF_LatinMetrics  metrics,
516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                               AF_Scaler        scaler,
517c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                               AF_Dimension     dim )
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        delta;
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  axis;
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt       nn;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->x_scale;
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->x_delta;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scale = scaler->y_scale;
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = scaler->y_delta;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis = &metrics->axis[dim];
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( axis->org_scale == scale && axis->org_delta == delta )
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_scale = scale;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->org_delta = delta;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * correct Y scale to optimize the alignment of the top of small
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * letters to the pixel grid
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinAxis  vaxis = &metrics->axis[AF_DIMENSION_VERT];
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_LatinBlue  blue = NULL;
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < vaxis->blue_count; nn++ )
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue = &vaxis->blues[nn];
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( blue )
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
565a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_Pos   scaled;
566a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_Pos   threshold;
567a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_Pos   fitted;
568a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_UInt  limit;
569a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_UInt  ppem;
570a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
571a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
572a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
573a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
574a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        limit     = metrics->root.globals->increase_x_height;
575a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        threshold = 40;
576a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
577a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* if the `increase-x-height' property is active, */
578a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* we round up much more often                    */
579a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( limit                                 &&
580a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang             ppem <= limit                         &&
581a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang             ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
582a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          threshold = 52;
583a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
584a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        fitted = ( scaled + threshold ) & ~63;
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1
587aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( scaled != fitted )
588aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scale = FT_MulDiv( scale, fitted, scaled );
590c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( "== scaled x-top = %.2g"
591c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      "  fitted = %.2g, scaling = %.4g\n",
592c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      scaled / 64.0, fitted / 64.0,
593c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      ( fitted * 1.0 ) / scaled ));
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->scale = scale;
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->delta = delta;
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_scale = scale;
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.x_delta = delta;
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_scale = scale;
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.y_delta = delta;
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scale the standard widths */
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < axis->width_count; nn++ )
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  width = axis->widths + nn;
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->cur = FT_MulFix( width->org, scale );
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      width->fit = width->cur;
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* an extra-light axis corresponds to a standard width that is */
624c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    /* smaller than 5/8 pixels                                     */
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->extra_light =
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT )
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* scale the blue zones */
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( nn = 0; nn < axis->blue_count; nn++ )
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = &axis->blues[nn];
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        dist;
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->ref.fit   = blue->ref.cur;
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->shoot.fit = blue->shoot.cur;
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a blue zone is only active if it is less than 3/4 pixels tall */
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist <= 48 && dist >= -48 )
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  delta1, delta2;
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta1 = blue->shoot.org - blue->ref.org;
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = delta1;
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta2 = FT_MulFix( delta2, scale );
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta2 < 32 )
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 0;
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta2 < 64 )
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = FT_PIX_ROUND( delta2 );
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta1 < 0 )
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta2 = -delta2;
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->shoot.fit = blue->ref.fit + delta2;
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
669c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( ">> activating blue zone %d:"
670c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      "  ref.cur=%.2g ref.fit=%.2g"
671c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      "  shoot.cur=%.2g shoot.fit=%.2g\n",
672c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
673c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue->flags |= AF_LATIN_BLUE_ACTIVE;
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_metrics_scale( AF_LatinMetrics  metrics,
684c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                           AF_Scaler        scaler )
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.render_mode = scaler->render_mode;
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->root.scaler.face        = scaler->face;
688a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    metrics->root.scaler.flags       = scaler->flags;
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****           L A T I N   G L Y P H   A N A L Y S I S             *****/
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  SORT_SEGMENTS
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
707c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                    AF_Dimension   dim )
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory        = hints->memory;
711a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error      error         = FT_Err_Ok;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment       = NULL;
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SegmentRec seg0;
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour       = hints->contours;
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Point*     contour_limit = contour + hints->num_contours;
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  major_dir, segment_dir;
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ZERO( &seg0 );
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.score = 32000;
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seg0.flags = AF_EDGE_NORMAL;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    major_dir   = (AF_Direction)FT_ABS( axis->major_dir );
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment_dir = major_dir;
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_segments = 0;
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* set up (u,v) in each point */
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fx;
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fy;
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point = hints->points;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  limit = point + hints->num_points;
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; point < limit; point++ )
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->u = point->fy;
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point->v = point->fx;
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* do each contour separately */
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; contour < contour_limit; contour++ )
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  point   =  contour[0];
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  start   =  point;
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Point  last    =  point->prev;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( point == last )  /* skip singletons -- just in case */
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* already on an edge ?, backtrack to find its start */
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ABS( point->in_dir ) == major_dir )
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->prev;
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( point->in_dir == start->in_dir )
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->prev;
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else  /* otherwise, find first segment start, if any */
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( FT_ABS( point->out_dir ) != major_dir )
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == start )
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto NextContour;
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = point;
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for  (;;)
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first;
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    min_u, min_v, max_u, max_v;
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* we're at the start of a new segment */
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           point->in_dir != point->out_dir );
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = point;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min_u = max_u = point->u;
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min_v = max_v = point->v;
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point = point->next;
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( point->out_dir == first->out_dir )
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->u < min_u )
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            min_u = point->u;
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point->u > max_u )
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            max_u = point->u;
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->v < min_v )
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          min_v = point->v;
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point->v > max_v )
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max_v = point->v;
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* record new segment */
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = af_axis_hints_new_segment( axis, memory, &segment );
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment[0]         = seg0;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->dir       = first->out_dir;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->first     = first;
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->last      = point;
827a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        segment->pos       = (FT_Short)( ( min_u + max_u ) >> 1 );
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->min_coord = (FT_Short) min_v;
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->max_coord = (FT_Short) max_v;
830a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        segment->height    = (FT_Short)( max_v - min_v );
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a segment is round if it doesn't have successive */
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* on-curve points.                                 */
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  pt   = first;
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Point  last = point;
837a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          AF_Flags  f0   = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Flags  f1;
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          segment->flags &= ~AF_EDGE_ROUND;
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; pt != last; f0 = f1 )
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pt = pt->next;
846a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( !f0 && !f1 )
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( pt == last )
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segment->flags |= AF_EDGE_ROUND;
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       /* this can happen in the case of a degenerate contour
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        * e.g. a 2-point vertical contour
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        */
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( point == start )
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to the start of the next segment, if any */
863a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        while ( FT_ABS( point->out_dir ) != major_dir )
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          point = point->next;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( point == start )
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto NextContour;
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NextContour:
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ;
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    } /* contours */
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now slightly increase the height of segments when this makes */
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sense -- this is used to better detect and ignore serifs     */
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments     = axis->segments;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments_end = segments + axis->num_segments;
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( segment = segments; segment < segments_end; segment++ )
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  first   = segment->first;
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  last    = segment->last;
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Point  p;
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    first_v = first->v;
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos    last_v  = last->v;
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first == last )
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_v < last_v )
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < first_v )
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( first_v - p->v ) >> 1 ) );
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > last_v )
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - last_v ) >> 1 ) );
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = first->prev;
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v > first_v )
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( p->v - first_v ) >> 1 ) );
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p = last->next;
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( p->v < last_v )
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            segment->height = (FT_Short)( segment->height +
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          ( ( last_v - p->v ) >> 1 ) );
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   /* place all segments with a negative direction to the start
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    * of the array, used to speed up segment linking later...
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    */
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Segment  segments = axis->segments;
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     count    = axis->num_segments;
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt     ii, jj;
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
931a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      for ( ii = 0; ii < count; ii++ )
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( segments[ii].dir > 0 )
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
935a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          for ( jj = ii + 1; jj < count; jj++ )
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( segments[jj].dir < 0 )
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              AF_SegmentRec  tmp;
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
941a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              tmp          = segments[ii];
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segments[ii] = segments[jj];
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              segments[jj] = tmp;
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( jj == count )
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      axis->mid_segments = ii;
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_link_segments( AF_GlyphHints  hints,
965c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                 AF_Dimension   dim )
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis          = &hints->axis[dim];
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_mid   = segments + axis->mid_segments;
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        len_threshold, len_score;
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg1, seg2;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( len_threshold == 0 )
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      len_threshold = 1;
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_SORT_SEGMENTS
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_mid; seg1++ )
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now compare each segment to the others */
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the fake segments are introduced to hint the metrics -- */
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we must never link them to anything                     */
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( seg2 = segments; seg2 < segment_limit; seg2++ )
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  pos1 = seg1->pos;
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  pos2 = seg2->pos;
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos  dist = pos2 - pos1;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 0 )
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  min = seg1->min_coord;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  max = seg1->max_coord;
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  len, score;
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( min < seg2->min_coord )
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              min = seg2->min_coord;
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( max > seg2->max_coord )
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              max = seg2->max_coord;
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            len = max - min;
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( len >= len_threshold )
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              score = dist + len_score / len;
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg1->score )
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->score = score;
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg1->link  = seg2;
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( score < seg2->score )
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->score = score;
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg2->link  = seg1;
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
10420a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#if 0
10430a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    }
10440a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now, compute the `serif' segments */
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      seg2 = seg1->link;
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg2 )
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg2->link != seg1 )
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->link  = 0;
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg1->serif = seg2->link;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_edges( AF_GlyphHints  hints,
1065c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                 AF_Dimension   dim )
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis   = &hints->axis[dim];
1068a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error      error  = FT_Err_Ok;
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory = hints->memory;
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segments      = axis->segments;
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    segment_limit = segments + axis->num_segments;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Segment    seg;
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Direction  up_dir;
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        edge_distance_threshold;
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        segment_length_threshold;
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axis->num_edges = 0;
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         : hints->y_scale;
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          : AF_DIR_RIGHT;
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We want to ignore very small (mostly serif) segments, we do that
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  by ignoring those that whose length is less than a given fraction
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  of the standard width. If there is no standard width, we ignore
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  those that are less than a given size in pixels
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  also, unlink serif segments that are linked to segments farther
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  than 50% of the standard width
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_HORZ )
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( laxis->width_count > 0 )
1102a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        segment_length_threshold = ( laxis->standard_width * 10 ) >> 4;
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      segment_length_threshold = 0;
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We will begin by generating a sorted table of edges for the       */
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* current direction.  To do so, we simply scan each segment and try */
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* to find an edge in our table that corresponds to its position.    */
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* If no edge is found, we create and insert a new edge in the       */
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sorted table.  Otherwise, we simply add the segment to the edge's */
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* list which will be processed in the second step to compute the    */
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* edge's properties.                                                */
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Note that the edges table is sorted along the segment/edge        */
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* position.                                                         */
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         scale );
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( edge_distance_threshold > 64 / 4 )
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge_distance_threshold = 64 / 4;
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    edge_distance_threshold = FT_DivFix( edge_distance_threshold,
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         scale );
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( seg = segments; seg < segment_limit; seg++ )
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  found = 0;
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int   ee;
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg->height < segment_length_threshold )
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A special case for serif edges: If they are smaller than */
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* 1.5 pixels we ignore them.                               */
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( seg->serif )
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  dist = seg->serif->pos - seg->pos;
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1149a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( dist < 0 )
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1152a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( dist >= laxis->standard_width >> 1 )
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* unlink this serif, it is too distant from its reference stem */
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg->serif = NULL;
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( 2*seg->height < 3 * segment_length_threshold )
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* look for an edge corresponding to the segment */
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ee = 0; ee < axis->num_edges; ee++ )
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge  edge = axis->edges + ee;
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   dist;
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = seg->pos - edge->fpos;
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 0 )
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = -dist;
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < edge_distance_threshold && edge->dir == seg->dir )
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          found = edge;
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !found )
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge;
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* insert a new edge in the list and */
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* sort according to the position    */
1186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
1187c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                        memory, &edge );
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( error )
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* add the segment to the new edge's list */
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ZERO( edge );
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->first    = seg;
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->last     = seg;
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->fpos     = seg->pos;
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir      = seg->dir;
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next = seg;
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if an edge was found, simply add the segment to the edge's */
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* list                                                       */
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg->edge_next         = found->first;
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last->edge_next = seg;
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        found->last            = seg;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Good, we will now compute each edge's properties according to     */
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* segments found on its position.  Basically, these are:            */
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - edge's main direction                                          */
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - stem edge, serif edge or both (which defaults to stem then)    */
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - rounded edge, straight or both (which defaults to straight)    */
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*  - link for edge                                                  */
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                   */
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*********************************************************************/
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, set the `edge' field in each segment -- this is */
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* required in order to compute edge links                       */
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * Note that removing this loop and setting the `edge' field of each
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * segment directly in the code above slows down execution speed for
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * some reasons on platforms like the Sun.
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edges      = axis->edges;
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge_limit = edges + axis->num_edges;
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge;
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( seg )
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg->edge = edge;
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg       = seg->edge_next;
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( seg != edge->first );
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now, compute each edge properties */
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_round    = 0;  /* does it contain round segments?    */
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int  is_straight = 0;  /* does it contain straight segments? */
1255c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#if 0
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  ups         = 0;  /* number of upwards segments         */
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  downs       = 0;  /* number of downwards segments       */
1258c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#endif
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        seg = edge->first;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Bool  is_serif;
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for roundness of segment */
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->flags & AF_EDGE_ROUND )
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_round++;
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            is_straight++;
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1274c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#if 0
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for segment direction */
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( seg->dir == up_dir )
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ups   += seg->max_coord-seg->min_coord;
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            downs += seg->max_coord-seg->min_coord;
1280c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#endif
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check for links -- if seg->serif is set, then seg->link must */
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* be ignored                                                   */
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          is_serif = (FT_Bool)( seg->serif               &&
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge         &&
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                seg->serif->edge != edge );
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Edge     edge2;
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            AF_Segment  seg2;
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            edge2 = edge->link;
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            seg2  = seg->link;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg2  = seg->serif;
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = edge->serif;
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( edge2 )
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  edge_delta;
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Pos  seg_delta;
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge_delta = edge->fpos - edge2->fpos;
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( edge_delta < 0 )
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge_delta = -edge_delta;
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              seg_delta = seg->pos - seg2->pos;
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < 0 )
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                seg_delta = -seg_delta;
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( seg_delta < edge_delta )
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                edge2 = seg2->edge;
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2 = seg2->edge;
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_serif )
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->serif   = edge2;
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge2->flags |= AF_EDGE_SERIF;
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              edge->link  = edge2;
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          seg = seg->edge_next;
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        } while ( seg != edge->first );
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the round/straight flags */
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags = AF_EDGE_NORMAL;
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_round > 0 && is_round >= is_straight )
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->flags |= AF_EDGE_ROUND;
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* set the edge's main direction */
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->dir = AF_DIR_NONE;
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ups > downs )
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)up_dir;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups < downs )
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = (FT_Char)-up_dir;
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( ups == downs )
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->dir = 0;  /* both up and down! */
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* gets rid of serifs if link is set                */
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* XXX: This gets rid of many unpleasant artefacts! */
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*      Example: the `c' in cour.pfa at size 13     */
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif && edge->link )
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->serif = 0;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_detect_features( AF_GlyphHints  hints,
1372c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                   AF_Dimension   dim )
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = af_latin2_hints_compute_segments( hints, dim );
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_hints_link_segments( hints, dim );
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_compute_edges( hints, dim );
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
1390c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                      AF_LatinMetrics  metrics )
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1392e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    AF_AxisHints  axis       = &hints->axis[AF_DIMENSION_VERT];
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge       = axis->edges;
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edge + axis->num_edges;
1395e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    AF_LatinAxis  latin      = &metrics->axis[AF_DIMENSION_VERT];
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed      scale      = latin->scale;
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        best_dist0;  /* initial threshold */
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute the initial threshold as a fraction of the EM size */
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( best_dist0 > 64 / 2 )
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      best_dist0 = 64 / 2;
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute which blue zones are active, i.e. have their scaled */
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* size < 3/4 pixels                                           */
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* for each horizontal edge search the blue zone which is closest */
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; edge < edge_limit; edge++ )
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    bb;
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Width  best_blue = NULL;
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos    best_dist = best_dist0;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_LatinBlue  blue = latin->blues + bb;
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Bool       is_top_blue, is_major_dir;
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* skip inactive blue zones (i.e., those that are too small) */
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, check for right edges -- if it is a bottom */
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* zone, check for left edges                                      */
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                                 */
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* of course, that's for TrueType                                  */
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* if it is a top zone, the edge must be against the major    */
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction; if it is a bottom zone, it must be in the major */
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* direction                                                  */
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( is_top_blue ^ is_major_dir )
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos     dist;
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Width   compare;
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if it's a rounded edge, compare it to the overshoot position */
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if it's a flat edge, compare it to the reference position    */
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND )
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            compare = &blue->shoot;
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            compare = &blue->ref;
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = edge->fpos - compare->org;
1450a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( dist < 0 )
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = -dist;
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = FT_MulFix( dist, scale );
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < best_dist )
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_dist = dist;
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            best_blue = compare;
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now, compare it to the overshoot position if the edge is     */
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* rounded, and if the edge is over the reference position of a */
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* top zone, or under the reference position of a bottom zone   */
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( is_top_blue ^ is_under_ref )
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              blue = latin->blues + bb;
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = edge->fpos - blue->shoot.org;
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 0 )
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = -dist;
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = FT_MulFix( dist, scale );
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < best_dist )
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_dist = dist;
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_blue = & blue->shoot;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( best_blue )
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->blue_edge = best_blue;
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_init( AF_GlyphHints    hints,
1496c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        AF_LatinMetrics  metrics )
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Render_Mode  mode;
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32       scaler_flags, other_flags;
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Face         face = metrics->root.scaler.face;
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  correct x_scale and y_scale if needed, since they may have
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  been modified `af_latin2_metrics_scale_dim' above
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute flags depending on render mode, etc. */
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mode = metrics->root.scaler.render_mode;
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1517c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaler_flags = hints->scaler_flags;
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    other_flags  = 0;
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of vertical stems for the monochrome and
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  horizontal LCD rendering targets only.
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We snap the width of horizontal stems for the monochrome and
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  vertical LCD rendering targets only.
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_VERT_SNAP;
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We adjust stems to full pixels only if we don't use the `light' mode.
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode != FT_RENDER_MODE_LIGHT )
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_MONO )
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      other_flags |= AF_LATIN_HINTS_MONO;
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  In `light' hinting mode we disable horizontal hinting completely.
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  We also do it if the face is italic.
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
1554a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( mode == FT_RENDER_MODE_LIGHT                      ||
1555a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->scaler_flags = scaler_flags;
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    hints->other_flags  = other_flags;
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****        L A T I N   G L Y P H   G R I D - F I T T I N G        *****/
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* snap a given width in scaled coordinates to one of the */
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* current standard widths                                */
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_snap_width( AF_Width  widths,
1578c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        FT_Int    count,
1579c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        FT_Pos    width )
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     n;
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  best      = 64 + 32 + 2;
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  reference = width;
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  scaled;
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < count; n++ )
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  w;
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  dist;
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      w = widths[n].cur;
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = width - w;
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < 0 )
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = -dist;
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dist < best )
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        best      = dist;
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        reference = w;
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    scaled = FT_PIX_ROUND( reference );
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( width >= reference )
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width < scaled + 48 )
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( width > scaled - 48 )
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        width = reference;
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return width;
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compute the snapped width of a given stem */
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Pos
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_compute_stem_width( AF_GlyphHints  hints,
1625c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                AF_Dimension   dim,
1626c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                FT_Pos         width,
1627c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                AF_Edge_Flags  base_flags,
1628c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                                AF_Edge_Flags  stem_flags )
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_LatinAxis     axis     = & metrics->axis[dim];
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos           dist     = width;
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           sign     = 0;
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1636a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UNUSED( base_flags );
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          axis->extra_light                      )
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return width;
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dist < 0 )
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -width;
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sign = 1;
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( (  vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* smooth hinting process: very lightly quantize the stem width */
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* leave the widths of serifs alone */
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Done_Width;
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( ( base_flags & AF_EDGE_ROUND ) )
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 80 )
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( dist < 56 )
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        dist = 56;
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( axis->width_count > 0 )
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* compare to standard width */
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( axis->width_count > 0 )
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = dist - axis->widths[0].cur;
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 40 )
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = axis->widths[0].cur;
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( dist < 48 )
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = 48;
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Done_Width;
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist < 3 * 64 )
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta  = dist & 63;
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist  &= -64;
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 10 )
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 32 )
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 10;
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( delta < 54 )
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += 54;
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist += delta;
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 32 ) & ~63;
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* strong hinting process: snap the stem width to integer pixels */
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Pos  org_dist = dist;
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( vertical )
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* in the case of vertical hinting, always round */
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* the stem heights to integer pixels            */
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( dist >= 64 )
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = ( dist + 16 ) & ~63;
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dist = 64;
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( AF_LATIN_HINTS_DO_MONO( hints ) )
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* monochrome horizontal hinting: snap widths to integer pixels */
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* with a different threshold                                   */
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 64 )
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = 64;
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for horizontal anti-aliased hinting, we adopt a more subtle */
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* approach: we strengthen small stems, round stems whose size */
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( dist < 48 )
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 64 ) >> 1;
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else if ( dist < 128 )
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* We only round to an integer width if the corresponding */
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* distortion is less than 1/4 pixel.  Otherwise this     */
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* makes everything worse since the diagonals, which are  */
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* not hinted, appear a lot bolder or thinner than the    */
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* vertical stems.                                        */
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Int  delta;
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 22 ) & ~63;
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = dist - org_dist;
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( delta < 0 )
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta = -delta;
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1767a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( delta >= 16 )
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              dist = org_dist;
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( dist < 48 )
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                dist = ( dist + 64 ) >> 1;
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* round otherwise to prevent color fringes in LCD mode */
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            dist = ( dist + 32 ) & ~63;
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Done_Width:
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( sign )
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dist = -dist;
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return dist;
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* align one stem edge relative to the previous stem edge */
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_align_linked_edge( AF_GlyphHints  hints,
1793c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                               AF_Dimension   dim,
1794c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                               AF_Edge        base_edge,
1795c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                               AF_Edge        stem_edge )
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  dist = stem_edge->opos - base_edge->opos;
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos  fitted_width = af_latin2_compute_stem_width(
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             hints, dim, dist,
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)base_edge->flags,
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (AF_Edge_Flags)stem_edge->flags );
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    stem_edge->pos = base_edge->pos + fitted_width;
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1807c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
1808c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                "dist was %.2f, now %.2f\n",
1809c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
1810c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_align_serif_edge( AF_GlyphHints  hints,
1816c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                              AF_Edge        base,
1817c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                              AF_Edge        serif )
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( hints );
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1821a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    serif->pos = base->pos + ( serif->opos - base->opos );
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                    E D G E   H I N T I N G                      ****/
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /****                                                                 ****/
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hint_edges( AF_GlyphHints  hints,
1838c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        AF_Dimension   dim )
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_AxisHints  axis       = &hints->axis[dim];
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edges      = axis->edges;
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge_limit = edges + axis->num_edges;
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       edge;
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_Edge       anchor     = 0;
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int        has_serifs = 0;
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Pos        anchor_drift = 0;
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1850c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_TRACE5(( "==== hinting %s edges =====\n",
1851c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we begin by aligning all stems relative to the blue zone */
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if needed -- that's only for horizontal edges            */
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Width  blue;
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_Edge   edge1, edge2;
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blue  = edge->blue_edge;
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1 = NULL;
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2 = edge->link;
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( blue )
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge;
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( edge2 && edge2->blue_edge )
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blue  = edge2->blue_edge;
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge1 = edge2;
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2 = edge;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !edge1 )
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1885c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
1886c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    "was (%.2f)\n",
1887c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
1888c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge1->pos / 64.0 ));
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->pos    = blue->fit;
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge1->flags |= AF_EDGE_DONE;
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2 && !edge2->blue_edge )
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->flags |= AF_EDGE_DONE;
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !anchor )
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor = edge;
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1903a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          anchor_drift = ( anchor->pos - anchor->opos );
1904a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( edge2 )
1905a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            anchor_drift = ( anchor_drift +
1906a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             ( edge2->pos - edge2->opos ) ) >> 1;
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now we will align all stem edges, trying to maintain the */
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relative order of stems in the glyph                     */
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( edge = edges; edge < edge_limit; edge++ )
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AF_Edge  edge2;
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge->flags & AF_EDGE_DONE )
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* skip all non-stem edges */
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      edge2 = edge->link;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !edge2 )
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        has_serifs++;
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* now align the stem */
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* this should not happen, but it's better to be safe */
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( edge2->blue_edge )
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1934c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_align_linked_edge( hints, dim, edge2, edge );
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !anchor )
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  org_len, org_center, cur_len;
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  cur_pos1, error1, error2, u_off, d_off;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len = edge2->opos - edge->opos;
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin2_compute_stem_width(
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    hints, dim, org_len,
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge->flags,
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    (AF_Edge_Flags)edge2->flags );
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len <= 64 )
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = d_off = 32;
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          u_off = 38;
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          d_off = 26;
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cur_len < 96 )
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org_center = edge->opos + ( org_len >> 1 );
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cur_pos1   = FT_PIX_ROUND( org_center );
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error1 = org_center - ( cur_pos1 - u_off );
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < 0 )
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error1 = -error1;
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          error2 = org_center - ( cur_pos1 + d_off );
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error2 < 0 )
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error2 = -error2;
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( error1 < error2 )
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 -= u_off;
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_pos1 += d_off;
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos  = cur_pos1 - cur_len / 2;
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge2->pos = edge->pos + cur_len;
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1985c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
1986c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    " snapped to (%.2f) (%.2f)\n",
1987c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge-edges, edge->opos / 64.0,
1988c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge2-edges, edge2->opos / 64.0,
1989c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge->pos / 64.0, edge2->pos / 64.0 ));
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        anchor = edge;
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_align_linked_edge( hints, dim, edge, edge2 );
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1998a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        anchor_drift = ( ( anchor->pos - anchor->opos ) +
1999a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         ( edge2->pos - edge2->opos ) ) >> 1;
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2001c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   org_pos, org_len, org_center, cur_center, cur_len;
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos   org_left, org_right;
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_pos    = edge->opos + anchor_drift;
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_len    = edge2->opos - edge->opos;
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        org_center = org_pos + ( org_len >> 1 );
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_len = af_latin2_compute_stem_width(
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   hints, dim, org_len,
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge->flags,
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   (AF_Edge_Flags)edge2->flags );
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2018a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        org_left  = org_pos + ( ( org_len - cur_len ) >> 1 );
2019a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2021c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
2022c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    org_left / 64.0, org_right / 64.0 ));
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cur_center = org_center;
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge2->flags & AF_EDGE_DONE )
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2027c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( "\n" ));
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge2->pos - cur_len;
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         /* we want to compare several displacement, and choose
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          * the one that increases fitness while minimizing
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          * distortion as well
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          */
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Pos   displacements[6], scores[6], org, fit, delta;
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  count = 0;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* note: don't even try to fit tiny stems */
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( cur_len < 32 )
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2042c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_TRACE5(( "tiny stem\n" ));
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto AlignStem;
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if the span is within a single pixel, don't touch it */
2047a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) )
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2049c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_TRACE5(( "single pixel stem\n" ));
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto AlignStem;
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2053a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( cur_len <= 96 )
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* we want to avoid the absolute worst case which is
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * when the left and right edges of the span each represent
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * about 50% of the gray. we'd better want to change this
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * to 25/75%, since this is much more pleasant to the eye with
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            * very acceptable distortion
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            */
2061a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_Pos  frac_left  = org_left  & 63;
2062a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_Pos  frac_right = org_right & 63;
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( frac_left  >= 22 && frac_left  <= 42 &&
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 frac_right >= 22 && frac_right <= 42 )
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              org = frac_left;
2068a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              fit = ( org <= 32 ) ? 16 : 48;
2069a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              delta = FT_ABS( fit - org );
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              displacements[count] = fit - org;
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scores[count++]      = delta;
2072a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              org = frac_right;
2075a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              fit = ( org <= 32 ) ? 16 : 48;
2076a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              delta = FT_ABS( fit - org );
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              displacements[count] = fit - org;
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              scores[count++]     = delta;
2079a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* snapping the left edge to the grid */
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org   = org_left;
2085a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          fit   = FT_PIX_ROUND( org );
2086a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          delta = FT_ABS( fit - org );
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          displacements[count] = fit - org;
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scores[count++]      = delta;
2089a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* snapping the right edge to the grid */
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          org   = org_right;
2093a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          fit   = FT_PIX_ROUND( org );
2094a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          delta = FT_ABS( fit - org );
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          displacements[count] = fit - org;
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          scores[count++]      = delta;
2097a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* now find the best displacement */
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  best_score = scores[0];
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Pos  best_disp  = displacements[0];
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt nn;
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2105a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            for ( nn = 1; nn < count; nn++ )
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
2107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              if ( scores[nn] < best_score )
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_score = scores[nn];
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                best_disp  = displacements[nn];
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cur_center = org_center + best_disp;
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2116c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( "\n" ));
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      AlignStem:
2120a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        edge->pos  = cur_center - ( cur_len >> 1 );
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->pos = edge->pos + cur_len;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2123c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
2124c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    " snapped to (%.2f) and (%.2f),"
2125c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    " org_len=%.2f cur_len=%.2f\n",
2126c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge-edges, edge->opos / 64.0,
2127c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge2-edges, edge2->opos / 64.0,
2128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    edge->pos / 64.0, edge2->pos / 64.0,
2129c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    org_len / 64.0, cur_len / 64.0 ));
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags  |= AF_EDGE_DONE;
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge2->flags |= AF_EDGE_DONE;
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2136c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
2137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make sure that lowercase m's maintain their symmetry */
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* In general, lowercase m's have six vertical edges if they are sans */
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* serif, or twelve if they are with serifs.  This implementation is  */
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* based on that assumption, and seems to work very well with most    */
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* faces.  However, if for a certain face this assumption is not      */
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* true, the m is just rendered like before.  In addition, any stem   */
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* correction will only be applied to symmetrical glyphs (even if the */
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* glyph is not an m), so the potential for unwanted distortion is    */
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* relatively low.                                                    */
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* We don't handle horizontal edges since we can't easily assure that */
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the third (lowest) stem aligns with the base line; it might end up */
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* one pixel higher or lower.                                         */
2157295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
2159295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2160295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int  n_edges = edge_limit - edges;
2161295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2162295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2163aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2165aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        AF_Edge  edge1, edge2, edge3;
2166aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        FT_Pos   dist1, dist2, span, delta;
2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2169aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( n_edges == 6 )
2170aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2171aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge1 = edges;
2172aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge2 = edges + 2;
2173aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3 = edges + 4;
2174aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2175aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        else
2176aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2177aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge1 = edges + 1;
2178aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge2 = edges + 5;
2179aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3 = edges + 9;
2180aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2182aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        dist1 = edge2->opos - edge1->opos;
2183aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        dist2 = edge3->opos - edge2->opos;
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2185aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        span = dist1 - dist2;
2186aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( span < 0 )
2187aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          span = -span;
2188aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
2189aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( span < 8 )
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2191aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
2192aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3->pos -= delta;
2193aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( edge3->link )
2194aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            edge3->link->pos -= delta;
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2196aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          /* move the serifs along with the stem */
2197aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( n_edges == 12 )
2198aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          {
2199aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            ( edges + 8 )->pos -= delta;
2200aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            ( edges + 11 )->pos -= delta;
2201aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          }
2202aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
2203aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          edge3->flags |= AF_EDGE_DONE;
2204aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich          if ( edge3->link )
2205aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            edge3->link->flags |= AF_EDGE_DONE;
2206aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        }
2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2210295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( has_serifs || !anchor )
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  now hint the remaining edges (serifs and single) in order
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       *  to complete our processing
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( edge = edges; edge < edge_limit; edge++ )
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos  delta;
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->flags & AF_EDGE_DONE )
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = 1000;
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge->serif )
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta = edge->serif->opos - edge->opos;
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( delta < 0 )
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta = -delta;
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( delta < 64 + 16 )
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          af_latin2_align_serif_edge( hints, edge->serif, edge );
2237c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
2238c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      " aligned to (%.2f)\n",
2239c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      edge-edges, edge->opos / 64.0,
2240c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      edge->serif - edges, edge->serif->opos / 64.0,
2241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      edge->pos / 64.0 ));
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( !anchor )
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
2246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      " snapped to (%.2f)\n",
2247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = FT_PIX_ROUND( edge->opos );
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          anchor    = edge;
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          AF_Edge  before, after;
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( before = edge - 1; before >= edges; before-- )
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( before->flags & AF_EDGE_DONE )
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( after = edge + 1; after < edge_limit; after++ )
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( after->flags & AF_EDGE_DONE )
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( before >= edges && before < edge   &&
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               after < edge_limit && after > edge )
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
22670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( after->opos == before->opos )
22680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos;
22690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            else
22700a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              edge->pos = before->pos +
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_MulDiv( edge->opos - before->opos,
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->pos - before->pos,
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     after->opos - before->opos );
2274c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
2275c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        " from %d (opos=%.2f)\n",
2276c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        edge-edges, edge->opos / 64.0, edge->pos / 64.0,
2277c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        before - edges, before->opos / 64.0 ));
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2281c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            edge->pos = anchor->pos +
2282c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2284c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner            FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
2285c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        " snapped to (%.2f)\n",
2286c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                        edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        edge->flags |= AF_EDGE_DONE;
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge > edges && edge->pos < edge[-1].pos )
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[-1].pos;
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( edge + 1 < edge_limit        &&
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge[1].flags & AF_EDGE_DONE &&
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             edge->pos > edge[1].pos      )
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          edge->pos = edge[1].pos;
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
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  af_latin2_hints_apply( AF_GlyphHints    hints,
2306c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                         FT_Outline*      outline,
2307c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                         AF_LatinMetrics  metrics )
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int       dim;
2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2313aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    error = af_glyph_hints_reload( hints, outline );
2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* analyze glyph outline */
2318c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         AF_HINTS_DO_HORIZONTAL( hints ) )
2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_HORIZONTAL( hints ) )
2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( AF_HINTS_DO_VERTICAL( hints ) )
2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      af_latin2_hints_compute_blue_edges( hints, metrics );
2337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* grid-fit the outline */
2340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER
2343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ &&
2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        AF_WarperRec  warper;
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Fixed      scale;
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Pos        delta;
2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_warper_compute( &warper, hints, dim, &scale, &delta );
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_scale_dim( hints, dim, scale, delta );
2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_latin2_hint_edges( hints, (AF_Dimension)dim );
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
2363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_glyph_hints_save( hints, outline );
2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****              L A T I N   S C R I P T   C L A S S              *****/
2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const AF_Script_UniRangeRec  af_latin2_uniranges[] =
2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2384c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    AF_UNIRANGE_REC( 32UL,  127UL ),    /* TODO: Add new Unicode ranges here! */
2385295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC( 160UL, 255UL ),
2386295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    AF_UNIRANGE_REC( 0UL,   0UL )
2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
2388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2390e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class,
2391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    AF_SCRIPT_LATIN2,
2392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    af_latin2_uniranges,
2393a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'o',
2394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2395e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    sizeof ( AF_LatinMetricsRec ),
2396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_InitMetricsFunc) af_latin2_metrics_init,
2398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale,
2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_DoneMetricsFunc) NULL,
2400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_InitHintsFunc)   af_latin2_hints_init,
2402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (AF_Script_ApplyHintsFunc)  af_latin2_hints_apply
2403295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  )
2404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
2407