xref: /inferno-os/libfreetype/ahglobal.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ahglobal.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    Routines used to compute global metrics automatically (body).        */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2000-2001, 2002 Catharon Productions Inc.                    */
8*37da2899SCharles.Forsyth /*  Author: David Turner                                                   */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the Catharon Typography Project and shall only    */
11*37da2899SCharles.Forsyth /*  be used, modified, and distributed under the terms of the Catharon     */
12*37da2899SCharles.Forsyth /*  Open Source License that should come with this file under the name     */
13*37da2899SCharles.Forsyth /*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
14*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
15*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
16*37da2899SCharles.Forsyth /*                                                                         */
17*37da2899SCharles.Forsyth /*  Note that this license is compatible with the FreeType license.        */
18*37da2899SCharles.Forsyth /*                                                                         */
19*37da2899SCharles.Forsyth /***************************************************************************/
20*37da2899SCharles.Forsyth 
21*37da2899SCharles.Forsyth 
22*37da2899SCharles.Forsyth #include <ft2build.h>
23*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
24*37da2899SCharles.Forsyth #include "ahglobal.h"
25*37da2899SCharles.Forsyth #include "ahglyph.h"
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth #define MAX_TEST_CHARACTERS  12
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth   static
31*37da2899SCharles.Forsyth   const char*  blue_chars[AH_BLUE_MAX] =
32*37da2899SCharles.Forsyth   {
33*37da2899SCharles.Forsyth     "THEZOCQS",
34*37da2899SCharles.Forsyth     "HEZLOCUS",
35*37da2899SCharles.Forsyth     "xzroesc",
36*37da2899SCharles.Forsyth     "xzroesc",
37*37da2899SCharles.Forsyth     "pqgjy"
38*37da2899SCharles.Forsyth   };
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth   /* simple insertion sort */
42*37da2899SCharles.Forsyth   static void
sort_values(FT_Int count,FT_Pos * table)43*37da2899SCharles.Forsyth   sort_values( FT_Int   count,
44*37da2899SCharles.Forsyth                FT_Pos*  table )
45*37da2899SCharles.Forsyth   {
46*37da2899SCharles.Forsyth     FT_Int  i, j;
47*37da2899SCharles.Forsyth     FT_Pos  swap;
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth 
50*37da2899SCharles.Forsyth     for ( i = 1; i < count; i++ )
51*37da2899SCharles.Forsyth     {
52*37da2899SCharles.Forsyth       for ( j = i; j > 0; j-- )
53*37da2899SCharles.Forsyth       {
54*37da2899SCharles.Forsyth         if ( table[j] > table[j - 1] )
55*37da2899SCharles.Forsyth           break;
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth         swap         = table[j];
58*37da2899SCharles.Forsyth         table[j]     = table[j - 1];
59*37da2899SCharles.Forsyth         table[j - 1] = swap;
60*37da2899SCharles.Forsyth       }
61*37da2899SCharles.Forsyth     }
62*37da2899SCharles.Forsyth   }
63*37da2899SCharles.Forsyth 
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth   static FT_Error
ah_hinter_compute_blues(AH_Hinter hinter)66*37da2899SCharles.Forsyth   ah_hinter_compute_blues( AH_Hinter  hinter )
67*37da2899SCharles.Forsyth   {
68*37da2899SCharles.Forsyth     AH_Blue       blue;
69*37da2899SCharles.Forsyth     AH_Globals    globals = &hinter->globals->design;
70*37da2899SCharles.Forsyth     FT_Pos        flats [MAX_TEST_CHARACTERS];
71*37da2899SCharles.Forsyth     FT_Pos        rounds[MAX_TEST_CHARACTERS];
72*37da2899SCharles.Forsyth     FT_Int        num_flats;
73*37da2899SCharles.Forsyth     FT_Int        num_rounds;
74*37da2899SCharles.Forsyth 
75*37da2899SCharles.Forsyth     FT_Face       face;
76*37da2899SCharles.Forsyth     FT_GlyphSlot  glyph;
77*37da2899SCharles.Forsyth     FT_Error      error;
78*37da2899SCharles.Forsyth     FT_CharMap    charmap;
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth 
81*37da2899SCharles.Forsyth     face  = hinter->face;
82*37da2899SCharles.Forsyth     glyph = face->glyph;
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth     /* save current charmap */
85*37da2899SCharles.Forsyth     charmap = face->charmap;
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     /* do we have a Unicode charmap in there? */
88*37da2899SCharles.Forsyth     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
89*37da2899SCharles.Forsyth     if ( error )
90*37da2899SCharles.Forsyth       goto Exit;
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth     /* we compute the blues simply by loading each character from the */
93*37da2899SCharles.Forsyth     /* 'blue_chars[blues]' string, then compute its top-most and      */
94*37da2899SCharles.Forsyth     /* bottom-most points                                             */
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth     AH_LOG(( "blue zones computation\n" ));
97*37da2899SCharles.Forsyth     AH_LOG(( "------------------------------------------------\n" ));
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth     for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ )
100*37da2899SCharles.Forsyth     {
101*37da2899SCharles.Forsyth       const char*  p     = blue_chars[blue];
102*37da2899SCharles.Forsyth       const char*  limit = p + MAX_TEST_CHARACTERS;
103*37da2899SCharles.Forsyth       FT_Pos       *blue_ref, *blue_shoot;
104*37da2899SCharles.Forsyth 
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth       AH_LOG(( "blue %3d: ", blue ));
107*37da2899SCharles.Forsyth 
108*37da2899SCharles.Forsyth       num_flats  = 0;
109*37da2899SCharles.Forsyth       num_rounds = 0;
110*37da2899SCharles.Forsyth 
111*37da2899SCharles.Forsyth       for ( ; p < limit; p++ )
112*37da2899SCharles.Forsyth       {
113*37da2899SCharles.Forsyth         FT_UInt     glyph_index;
114*37da2899SCharles.Forsyth         FT_Vector*  extremum;
115*37da2899SCharles.Forsyth         FT_Vector*  points;
116*37da2899SCharles.Forsyth         FT_Vector*  point_limit;
117*37da2899SCharles.Forsyth         FT_Vector*  point;
118*37da2899SCharles.Forsyth         FT_Bool     round;
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth         /* exit if we reach the end of the string */
122*37da2899SCharles.Forsyth         if ( !*p )
123*37da2899SCharles.Forsyth           break;
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth         AH_LOG(( "`%c'", *p ));
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth         /* load the character in the face -- skip unknown or empty ones */
128*37da2899SCharles.Forsyth         glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
129*37da2899SCharles.Forsyth         if ( glyph_index == 0 )
130*37da2899SCharles.Forsyth           continue;
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth         error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
133*37da2899SCharles.Forsyth         if ( error || glyph->outline.n_points <= 0 )
134*37da2899SCharles.Forsyth           continue;
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth         /* now compute min or max point indices and coordinates */
137*37da2899SCharles.Forsyth         points      = glyph->outline.points;
138*37da2899SCharles.Forsyth         point_limit = points + glyph->outline.n_points;
139*37da2899SCharles.Forsyth         point       = points;
140*37da2899SCharles.Forsyth         extremum    = point;
141*37da2899SCharles.Forsyth         point++;
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth         if ( AH_IS_TOP_BLUE( blue ) )
144*37da2899SCharles.Forsyth         {
145*37da2899SCharles.Forsyth           for ( ; point < point_limit; point++ )
146*37da2899SCharles.Forsyth             if ( point->y > extremum->y )
147*37da2899SCharles.Forsyth               extremum = point;
148*37da2899SCharles.Forsyth         }
149*37da2899SCharles.Forsyth         else
150*37da2899SCharles.Forsyth         {
151*37da2899SCharles.Forsyth           for ( ; point < point_limit; point++ )
152*37da2899SCharles.Forsyth             if ( point->y < extremum->y )
153*37da2899SCharles.Forsyth               extremum = point;
154*37da2899SCharles.Forsyth         }
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth         AH_LOG(( "%5d", (int)extremum->y ));
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth         /* now, check whether the point belongs to a straight or round  */
159*37da2899SCharles.Forsyth         /* segment; we first need to find in which contour the extremum */
160*37da2899SCharles.Forsyth         /* lies, then see its previous and next points                  */
161*37da2899SCharles.Forsyth         {
162*37da2899SCharles.Forsyth           FT_Int  idx = (FT_Int)( extremum - points );
163*37da2899SCharles.Forsyth           FT_Int  n;
164*37da2899SCharles.Forsyth           FT_Int  first, last, prev, next, end;
165*37da2899SCharles.Forsyth           FT_Pos  dist;
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth           last  = -1;
169*37da2899SCharles.Forsyth           first = 0;
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth           for ( n = 0; n < glyph->outline.n_contours; n++ )
172*37da2899SCharles.Forsyth           {
173*37da2899SCharles.Forsyth             end = glyph->outline.contours[n];
174*37da2899SCharles.Forsyth             if ( end >= idx )
175*37da2899SCharles.Forsyth             {
176*37da2899SCharles.Forsyth               last = end;
177*37da2899SCharles.Forsyth               break;
178*37da2899SCharles.Forsyth             }
179*37da2899SCharles.Forsyth             first = end + 1;
180*37da2899SCharles.Forsyth           }
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth           /* XXX: should never happen! */
183*37da2899SCharles.Forsyth           if ( last < 0 )
184*37da2899SCharles.Forsyth             continue;
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth           /* now look for the previous and next points that are not on the */
187*37da2899SCharles.Forsyth           /* same Y coordinate.  Threshold the `closeness'...              */
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth           prev = idx;
190*37da2899SCharles.Forsyth           next = prev;
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth           do
193*37da2899SCharles.Forsyth           {
194*37da2899SCharles.Forsyth             if ( prev > first )
195*37da2899SCharles.Forsyth               prev--;
196*37da2899SCharles.Forsyth             else
197*37da2899SCharles.Forsyth               prev = last;
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth             dist = points[prev].y - extremum->y;
200*37da2899SCharles.Forsyth             if ( dist < -5 || dist > 5 )
201*37da2899SCharles.Forsyth               break;
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth           } while ( prev != idx );
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth           do
206*37da2899SCharles.Forsyth           {
207*37da2899SCharles.Forsyth             if ( next < last )
208*37da2899SCharles.Forsyth               next++;
209*37da2899SCharles.Forsyth             else
210*37da2899SCharles.Forsyth               next = first;
211*37da2899SCharles.Forsyth 
212*37da2899SCharles.Forsyth             dist = points[next].y - extremum->y;
213*37da2899SCharles.Forsyth             if ( dist < -5 || dist > 5 )
214*37da2899SCharles.Forsyth               break;
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth           } while ( next != idx );
217*37da2899SCharles.Forsyth 
218*37da2899SCharles.Forsyth           /* now, set the `round' flag depending on the segment's kind */
219*37da2899SCharles.Forsyth           round = FT_BOOL(
220*37da2899SCharles.Forsyth             FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
221*37da2899SCharles.Forsyth             FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
222*37da2899SCharles.Forsyth 
223*37da2899SCharles.Forsyth           AH_LOG(( "%c ", round ? 'r' : 'f' ));
224*37da2899SCharles.Forsyth         }
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth         if ( round )
227*37da2899SCharles.Forsyth           rounds[num_rounds++] = extremum->y;
228*37da2899SCharles.Forsyth         else
229*37da2899SCharles.Forsyth           flats[num_flats++] = extremum->y;
230*37da2899SCharles.Forsyth       }
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth       AH_LOG(( "\n" ));
233*37da2899SCharles.Forsyth 
234*37da2899SCharles.Forsyth       /* we have computed the contents of the `rounds' and `flats' tables, */
235*37da2899SCharles.Forsyth       /* now determine the reference and overshoot position of the blue;   */
236*37da2899SCharles.Forsyth       /* we simply take the median value after a simple short              */
237*37da2899SCharles.Forsyth       sort_values( num_rounds, rounds );
238*37da2899SCharles.Forsyth       sort_values( num_flats,  flats  );
239*37da2899SCharles.Forsyth 
240*37da2899SCharles.Forsyth       blue_ref   = globals->blue_refs + blue;
241*37da2899SCharles.Forsyth       blue_shoot = globals->blue_shoots + blue;
242*37da2899SCharles.Forsyth       if ( num_flats == 0 && num_rounds == 0 )
243*37da2899SCharles.Forsyth       {
244*37da2899SCharles.Forsyth         *blue_ref   = -10000;
245*37da2899SCharles.Forsyth         *blue_shoot = -10000;
246*37da2899SCharles.Forsyth       }
247*37da2899SCharles.Forsyth       else if ( num_flats == 0 )
248*37da2899SCharles.Forsyth       {
249*37da2899SCharles.Forsyth         *blue_ref   =
250*37da2899SCharles.Forsyth         *blue_shoot = rounds[num_rounds / 2];
251*37da2899SCharles.Forsyth       }
252*37da2899SCharles.Forsyth       else if ( num_rounds == 0 )
253*37da2899SCharles.Forsyth       {
254*37da2899SCharles.Forsyth         *blue_ref   =
255*37da2899SCharles.Forsyth         *blue_shoot = flats[num_flats / 2];
256*37da2899SCharles.Forsyth       }
257*37da2899SCharles.Forsyth       else
258*37da2899SCharles.Forsyth       {
259*37da2899SCharles.Forsyth         *blue_ref   = flats[num_flats / 2];
260*37da2899SCharles.Forsyth         *blue_shoot = rounds[num_rounds / 2];
261*37da2899SCharles.Forsyth       }
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth       /* there are sometimes problems: if the overshoot position of top     */
264*37da2899SCharles.Forsyth       /* zones is under its reference position, or the opposite for bottom  */
265*37da2899SCharles.Forsyth       /* zones.  We must thus check everything there and correct the errors */
266*37da2899SCharles.Forsyth       if ( *blue_shoot != *blue_ref )
267*37da2899SCharles.Forsyth       {
268*37da2899SCharles.Forsyth         FT_Pos   ref      = *blue_ref;
269*37da2899SCharles.Forsyth         FT_Pos   shoot    = *blue_shoot;
270*37da2899SCharles.Forsyth         FT_Bool  over_ref = FT_BOOL( shoot > ref );
271*37da2899SCharles.Forsyth 
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth         if ( AH_IS_TOP_BLUE( blue ) ^ over_ref )
274*37da2899SCharles.Forsyth           *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
275*37da2899SCharles.Forsyth       }
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth       AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
278*37da2899SCharles.Forsyth     }
279*37da2899SCharles.Forsyth 
280*37da2899SCharles.Forsyth     /* reset original face charmap */
281*37da2899SCharles.Forsyth     FT_Set_Charmap( face, charmap );
282*37da2899SCharles.Forsyth     error = 0;
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth   Exit:
285*37da2899SCharles.Forsyth     return error;
286*37da2899SCharles.Forsyth   }
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth 
289*37da2899SCharles.Forsyth   static FT_Error
ah_hinter_compute_widths(AH_Hinter hinter)290*37da2899SCharles.Forsyth   ah_hinter_compute_widths( AH_Hinter  hinter )
291*37da2899SCharles.Forsyth   {
292*37da2899SCharles.Forsyth     /* scan the array of segments in each direction */
293*37da2899SCharles.Forsyth     AH_Outline  outline = hinter->glyph;
294*37da2899SCharles.Forsyth     AH_Segment  segments;
295*37da2899SCharles.Forsyth     AH_Segment  limit;
296*37da2899SCharles.Forsyth     AH_Globals  globals = &hinter->globals->design;
297*37da2899SCharles.Forsyth     FT_Pos*     widths;
298*37da2899SCharles.Forsyth     FT_Int      dimension;
299*37da2899SCharles.Forsyth     FT_Int*     p_num_widths;
300*37da2899SCharles.Forsyth     FT_Error    error = 0;
301*37da2899SCharles.Forsyth     FT_Pos      edge_distance_threshold = 32000;
302*37da2899SCharles.Forsyth 
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth     globals->num_widths  = 0;
305*37da2899SCharles.Forsyth     globals->num_heights = 0;
306*37da2899SCharles.Forsyth 
307*37da2899SCharles.Forsyth     /* For now, compute the standard width and height from the `o'       */
308*37da2899SCharles.Forsyth     /* character.  I started computing the stem width of the `i' and the */
309*37da2899SCharles.Forsyth     /* stem height of the "-", but it wasn't too good.  Moreover, we now */
310*37da2899SCharles.Forsyth     /* have a single character that gives us standard width and height.  */
311*37da2899SCharles.Forsyth     {
312*37da2899SCharles.Forsyth       FT_UInt   glyph_index;
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth 
315*37da2899SCharles.Forsyth       glyph_index = FT_Get_Char_Index( hinter->face, 'o' );
316*37da2899SCharles.Forsyth       if ( glyph_index == 0 )
317*37da2899SCharles.Forsyth         return 0;
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth       error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE );
320*37da2899SCharles.Forsyth       if ( error )
321*37da2899SCharles.Forsyth         goto Exit;
322*37da2899SCharles.Forsyth 
323*37da2899SCharles.Forsyth       error = ah_outline_load( hinter->glyph, hinter->face );
324*37da2899SCharles.Forsyth       if ( error )
325*37da2899SCharles.Forsyth         goto Exit;
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth       ah_outline_compute_segments( hinter->glyph );
328*37da2899SCharles.Forsyth       ah_outline_link_segments( hinter->glyph );
329*37da2899SCharles.Forsyth     }
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth     segments     = outline->horz_segments;
332*37da2899SCharles.Forsyth     limit        = segments + outline->num_hsegments;
333*37da2899SCharles.Forsyth     widths       = globals->heights;
334*37da2899SCharles.Forsyth     p_num_widths = &globals->num_heights;
335*37da2899SCharles.Forsyth 
336*37da2899SCharles.Forsyth     for ( dimension = 1; dimension >= 0; dimension-- )
337*37da2899SCharles.Forsyth     {
338*37da2899SCharles.Forsyth       AH_Segment  seg = segments;
339*37da2899SCharles.Forsyth       AH_Segment  link;
340*37da2899SCharles.Forsyth       FT_Int      num_widths = 0;
341*37da2899SCharles.Forsyth 
342*37da2899SCharles.Forsyth 
343*37da2899SCharles.Forsyth       for ( ; seg < limit; seg++ )
344*37da2899SCharles.Forsyth       {
345*37da2899SCharles.Forsyth         link = seg->link;
346*37da2899SCharles.Forsyth         /* we only consider stem segments there! */
347*37da2899SCharles.Forsyth         if ( link && link->link == seg && link > seg )
348*37da2899SCharles.Forsyth         {
349*37da2899SCharles.Forsyth           FT_Pos  dist;
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth 
352*37da2899SCharles.Forsyth           dist = seg->pos - link->pos;
353*37da2899SCharles.Forsyth           if ( dist < 0 )
354*37da2899SCharles.Forsyth             dist = -dist;
355*37da2899SCharles.Forsyth 
356*37da2899SCharles.Forsyth           if ( num_widths < AH_MAX_WIDTHS )
357*37da2899SCharles.Forsyth             widths[num_widths++] = dist;
358*37da2899SCharles.Forsyth         }
359*37da2899SCharles.Forsyth       }
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth       sort_values( num_widths, widths );
362*37da2899SCharles.Forsyth       *p_num_widths = num_widths;
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth       /* we will now try to find the smallest width */
365*37da2899SCharles.Forsyth       if ( num_widths > 0 && widths[0] < edge_distance_threshold )
366*37da2899SCharles.Forsyth         edge_distance_threshold = widths[0];
367*37da2899SCharles.Forsyth 
368*37da2899SCharles.Forsyth       segments     = outline->vert_segments;
369*37da2899SCharles.Forsyth       limit        = segments + outline->num_vsegments;
370*37da2899SCharles.Forsyth       widths       = globals->widths;
371*37da2899SCharles.Forsyth       p_num_widths = &globals->num_widths;
372*37da2899SCharles.Forsyth     }
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth     /* Now, compute the edge distance threshold as a fraction of the */
375*37da2899SCharles.Forsyth     /* smallest width in the font. Set it in `hinter.glyph' too!     */
376*37da2899SCharles.Forsyth     if ( edge_distance_threshold == 32000 )
377*37da2899SCharles.Forsyth       edge_distance_threshold = 50;
378*37da2899SCharles.Forsyth 
379*37da2899SCharles.Forsyth     /* let's try 20% */
380*37da2899SCharles.Forsyth     hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5;
381*37da2899SCharles.Forsyth 
382*37da2899SCharles.Forsyth   Exit:
383*37da2899SCharles.Forsyth     return error;
384*37da2899SCharles.Forsyth   }
385*37da2899SCharles.Forsyth 
386*37da2899SCharles.Forsyth 
387*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
ah_hinter_compute_globals(AH_Hinter hinter)388*37da2899SCharles.Forsyth   ah_hinter_compute_globals( AH_Hinter  hinter )
389*37da2899SCharles.Forsyth   {
390*37da2899SCharles.Forsyth     return ah_hinter_compute_widths( hinter ) ||
391*37da2899SCharles.Forsyth            ah_hinter_compute_blues ( hinter );
392*37da2899SCharles.Forsyth   }
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth /* END */
396