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