source: trunk/poppler/freetype-2.2.1/src/autofit/afwarp.c @ 150

Last change on this file since 150 was 150, checked in by Eugene Romanenko, 15 years ago

update freetype to 2.2.1

File size: 8.7 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  afwarp.c                                                               */
4/*                                                                         */
5/*    Auto-fitter warping algorithm (body).                                */
6/*                                                                         */
7/*  Copyright 2006 by                                                      */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19#include "afwarp.h"
20
21#ifdef AF_USE_WARPER
22
23#if 1
24  static const AF_WarpScore
25  af_warper_weights[64] =
26  {
27    35, 20, 20, 20, 15, 12, 10,  5,  2,  1,  0,  0,  0,  0,  0,  0,
28     0,  0,  0,  0,  0,  0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
29
30   -30,-30,-20,-20,-10,-10, -8, -5, -2, -1,  0,  0,  0,  0,  0,  0,
31     0,  0,  0,  0,  0,  0,  0,  1,  2,  5, 10, 12, 15, 20, 20, 20,
32  };
33#else
34  static const AF_WarpScore
35  af_warper_weights[64] =
36  {
37    30, 20, 10,  5,  4,  4,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,
38     0,  0,  0,  0,  0,  0,  0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
39
40   -20,-15,-15,-10,-10, -5, -5, -2, -2, -1,  0,  0,  0,  0,  0,  0,
41     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  4,  5, 10, 20,
42  };
43#endif
44
45
46  static void
47  af_warper_compute_line_best( AF_Warper     warper,
48                               FT_Fixed      scale,
49                               FT_Pos        delta,
50                               FT_Pos        xx1,
51                               FT_Pos        xx2,
52                               AF_WarpScore  base_distort,
53                               AF_Segment    segments,
54                               FT_UInt       num_segments )
55  {
56    FT_Int        idx_min, idx_max, idx0;
57    FT_UInt       nn;
58    AF_WarpScore  scores[64];
59
60
61    for ( nn = 0; nn < 64; nn++ )
62      scores[nn] = 0;
63
64    idx0 = xx1 - warper->t1;
65
66    /* compute minimum and maximum indices */
67    {
68      FT_Pos  xx1min = warper->x1min;
69      FT_Pos  xx1max = warper->x1max;
70      FT_Pos  w      = xx2 - xx1;
71
72
73      if ( xx1min + w < warper->x2min )
74        xx1min = warper->x2min - ( xx2 - xx1 );
75
76      xx1max = warper->x1max;
77      if ( xx1max + w > warper->x2max )
78        xx1max = warper->x2max - ( xx2 - xx1 );
79
80      idx_min = xx1min - warper->t1;
81      idx_max = xx1max - warper->t1;
82
83      if ( idx_min > idx_max )
84      {
85        AF_LOG(( "invalid indices:\n"
86                 "  min=%d max=%d, xx1=%ld xx2=%ld,\n"
87                 "  x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
88                 idx_min, idx_max, xx1, xx2,
89                 warper->x1min, warper->x1max,
90                 warper->x2min, warper->x2max ));
91        return;
92      }
93    }
94
95    for ( nn = 0; nn < num_segments; nn++ )
96    {
97      FT_Pos  len = segments[nn].max_coord - segments[nn].min_coord;
98      FT_Pos  y0  = FT_MulFix( segments[nn].pos, scale ) + delta;
99      FT_Pos  y   = y0 + ( idx_min - idx0 );
100
101      FT_Int  idx;
102
103
104      for ( idx = idx_min; idx <= idx_max; idx++, y++ )
105        scores[idx] += af_warper_weights[y & 63] * len;
106    }
107
108    /* find best score */
109    {
110      FT_Int  idx;
111
112
113      for ( idx = idx_min; idx <= idx_max; idx++ )
114      {
115        AF_WarpScore  score = scores[idx];
116        AF_WarpScore  distort = base_distort + ( idx - idx0 );
117
118
119        if ( score > warper->best_score           ||
120             ( score == warper->best_score    &&
121               distort < warper->best_distort )   )
122        {
123          warper->best_score   = score;
124          warper->best_distort = distort;
125          warper->best_scale   = scale;
126          warper->best_delta   = delta + ( idx - idx0 );
127        }
128      }
129    }
130  }
131
132
133  FT_LOCAL_DEF( void )
134  af_warper_compute( AF_Warper      warper,
135                     AF_GlyphHints  hints,
136                     AF_Dimension   dim,
137                     FT_Fixed      *a_scale,
138                     FT_Pos        *a_delta )
139  {
140    AF_AxisHints  axis;
141    AF_Point      points;
142
143    FT_Fixed      org_scale;
144    FT_Pos        org_delta;
145
146    FT_UInt       nn, num_points, num_segments;
147    FT_Int        X1, X2;
148    FT_Int        w;
149
150    AF_WarpScore  base_distort;
151    AF_Segment    segments;
152
153
154    /* get original scaling transformation */
155    if ( dim == AF_DIMENSION_VERT )
156    {
157      org_scale = hints->y_scale;
158      org_delta = hints->y_delta;
159    }
160    else
161    {
162      org_scale = hints->x_scale;
163      org_delta = hints->x_delta;
164    }
165
166    warper->best_scale   = org_scale;
167    warper->best_delta   = org_delta;
168    warper->best_score   = 0;
169    warper->best_distort = 0;
170
171    axis         = &hints->axis[dim];
172    segments     = axis->segments;
173    num_segments = axis->num_segments;
174    points       = hints->points;
175    num_points   = hints->num_points;
176
177    *a_scale = org_scale;
178    *a_delta = org_delta;
179
180    /* get X1 and X2, minimum and maximum in original coordinates */
181    if ( axis->num_segments < 1 )
182      return;
183
184#if 1
185    X1 = X2 = points[0].fx;
186    for ( nn = 1; nn < num_points; nn++ )
187    {
188      FT_Int  X = points[nn].fx;
189
190
191      if ( X < X1 )
192        X1 = X;
193      if ( X > X2 )
194        X2 = X;
195    }
196#else
197    X1 = X2 = segments[0].pos;
198    for ( nn = 1; nn < num_segments; nn++ )
199    {
200      FT_Int  X = segments[nn].pos;
201
202
203      if ( X < X1 )
204        X1 = X;
205      if ( X > X2 )
206        X2 = X;
207    }
208#endif
209
210    if ( X1 >= X2 )
211      return;
212
213    warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
214    warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
215
216    warper->t1 = AF_WARPER_FLOOR( warper->x1 );
217    warper->t2 = AF_WARPER_CEIL( warper->x2 );
218
219    warper->x1min = warper->x1 & ~31;
220    warper->x1max = warper->x1min + 32;
221    warper->x2min = warper->x2 & ~31;
222    warper->x2max = warper->x2min + 32;
223
224    if ( warper->x1max > warper->x2 )
225      warper->x1max = warper->x2;
226
227    if ( warper->x2min < warper->x1 )
228      warper->x2min = warper->x1;
229
230    warper->w0 = warper->x2 - warper->x1;
231
232    if ( warper->w0 <= 64 )
233    {
234      warper->x1max = warper->x1;
235      warper->x2min = warper->x2;
236    }
237
238    warper->wmin = warper->x2min - warper->x1max;
239    warper->wmax = warper->x2max - warper->x1min;
240
241    if ( warper->wmin < warper->w0 - 32 )
242      warper->wmin = warper->w0 - 32;
243
244    if ( warper->wmax > warper->w0 + 32 )
245      warper->wmax = warper->w0 + 32;
246
247    if ( warper->wmin < warper->w0 * 3 / 4 )
248      warper->wmin = warper->w0 * 3 / 4;
249
250    if ( warper->wmax > warper->w0 * 5 / 4 )
251      warper->wmax = warper->w0 * 5 / 4;
252
253    /* warper->wmin = warper->wmax = warper->w0; */
254
255    for ( w = warper->wmin; w <= warper->wmax; w++ )
256    {
257      FT_Fixed  new_scale;
258      FT_Pos    new_delta;
259      FT_Pos    xx1, xx2;
260
261
262      xx1 = warper->x1;
263      xx2 = warper->x2;
264      if ( w >= warper->w0 )
265      {
266        xx1 -= w - warper->w0;
267        if ( xx1 < warper->x1min )
268        {
269          xx2 += warper->x1min - xx1;
270          xx1  = warper->x1min;
271        }
272      }
273      else
274      {
275        xx1 -= w - warper->w0;
276        if ( xx1 > warper->x1max )
277        {
278          xx2 -= xx1 - warper->x1max;
279          xx1  = warper->x1max;
280        }
281      }
282
283      if ( xx1 < warper->x1 )
284        base_distort = warper->x1 - xx1;
285      else
286        base_distort = xx1 - warper->x1;
287
288      if ( xx2 < warper->x2 )
289        base_distort += warper->x2 - xx2;
290      else
291        base_distort += xx2 - warper->x2;
292
293      base_distort *= 10;
294
295      new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
296      new_delta = xx1 - FT_MulFix( X1, new_scale );
297
298      af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
299                                   base_distort,
300                                   segments, num_segments );
301    }
302
303    *a_scale = warper->best_scale;
304    *a_delta = warper->best_delta;
305  }
306
307#else /* !AF_USE_WARPER */
308
309char  af_warper_dummy = 0;  /* make compiler happy */
310
311#endif /* !AF_USE_WARPER */
312
313/* END */
Note: See TracBrowser for help on using the repository browser.