~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/autofit/afwarp.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  afwarp.c                                                               */
 
4
/*                                                                         */
 
5
/*    Auto-fitter warping algorithm (body).                                */
 
6
/*                                                                         */
 
7
/*  Copyright 2006, 2007 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, 32, 30, 25, 20, 15, 12, 10,  5,  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,  5, 10, 12, 15, 20, 25, 30, 32,
 
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[65];
 
59
 
 
60
 
 
61
    for ( nn = 0; nn < 65; 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 - w;
 
75
 
 
76
      xx1max = warper->x1max;
 
77
      if ( xx1max + w > warper->x2max )
 
78
        xx1max = warper->x2max - w;
 
79
 
 
80
      idx_min = xx1min - warper->t1;
 
81
      idx_max = xx1max - warper->t1;
 
82
 
 
83
      if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
 
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
      FT_Int  idx;
 
101
 
 
102
 
 
103
      for ( idx = idx_min; idx <= idx_max; idx++, y++ )
 
104
        scores[idx] += af_warper_weights[y & 63] * len;
 
105
    }
 
106
 
 
107
    /* find best score */
 
108
    {
 
109
      FT_Int  idx;
 
110
 
 
111
 
 
112
      for ( idx = idx_min; idx <= idx_max; idx++ )
 
113
      {
 
114
        AF_WarpScore  score = scores[idx];
 
115
        AF_WarpScore  distort = base_distort + ( idx - idx0 );
 
116
 
 
117
 
 
118
        if ( score > warper->best_score           ||
 
119
             ( score == warper->best_score    &&
 
120
               distort < warper->best_distort )   )
 
121
        {
 
122
          warper->best_score   = score;
 
123
          warper->best_distort = distort;
 
124
          warper->best_scale   = scale;
 
125
          warper->best_delta   = delta + ( idx - idx0 );
 
126
        }
 
127
      }
 
128
    }
 
129
  }
 
130
 
 
131
 
 
132
  FT_LOCAL_DEF( void )
 
133
  af_warper_compute( AF_Warper      warper,
 
134
                     AF_GlyphHints  hints,
 
135
                     AF_Dimension   dim,
 
136
                     FT_Fixed      *a_scale,
 
137
                     FT_Pos        *a_delta )
 
138
  {
 
139
    AF_AxisHints  axis;
 
140
    AF_Point      points;
 
141
 
 
142
    FT_Fixed      org_scale;
 
143
    FT_Pos        org_delta;
 
144
 
 
145
    FT_UInt       nn, num_points, num_segments;
 
146
    FT_Int        X1, X2;
 
147
    FT_Int        w;
 
148
 
 
149
    AF_WarpScore  base_distort;
 
150
    AF_Segment    segments;
 
151
 
 
152
 
 
153
    /* get original scaling transformation */
 
154
    if ( dim == AF_DIMENSION_VERT )
 
155
    {
 
156
      org_scale = hints->y_scale;
 
157
      org_delta = hints->y_delta;
 
158
    }
 
159
    else
 
160
    {
 
161
      org_scale = hints->x_scale;
 
162
      org_delta = hints->x_delta;
 
163
    }
 
164
 
 
165
    warper->best_scale   = org_scale;
 
166
    warper->best_delta   = org_delta;
 
167
    warper->best_score   = INT_MIN;
 
168
    warper->best_distort = 0;
 
169
 
 
170
    axis         = &hints->axis[dim];
 
171
    segments     = axis->segments;
 
172
    num_segments = axis->num_segments;
 
173
    points       = hints->points;
 
174
    num_points   = hints->num_points;
 
175
 
 
176
    *a_scale = org_scale;
 
177
    *a_delta = org_delta;
 
178
 
 
179
    /* get X1 and X2, minimum and maximum in original coordinates */
 
180
    if ( num_segments < 1 )
 
181
      return;
 
182
 
 
183
#if 1
 
184
    X1 = X2 = points[0].fx;
 
185
    for ( nn = 1; nn < num_points; nn++ )
 
186
    {
 
187
      FT_Int  X = points[nn].fx;
 
188
 
 
189
 
 
190
      if ( X < X1 )
 
191
        X1 = X;
 
192
      if ( X > X2 )
 
193
        X2 = X;
 
194
    }
 
195
#else
 
196
    X1 = X2 = segments[0].pos;
 
197
    for ( nn = 1; nn < num_segments; nn++ )
 
198
    {
 
199
      FT_Int  X = segments[nn].pos;
 
200
 
 
201
 
 
202
      if ( X < X1 )
 
203
        X1 = X;
 
204
      if ( X > X2 )
 
205
        X2 = X;
 
206
    }
 
207
#endif
 
208
 
 
209
    if ( X1 >= X2 )
 
210
      return;
 
211
 
 
212
    warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
 
213
    warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
 
214
 
 
215
    warper->t1 = AF_WARPER_FLOOR( warper->x1 );
 
216
    warper->t2 = AF_WARPER_CEIL( warper->x2 );
 
217
 
 
218
    warper->x1min = warper->x1 & ~31;
 
219
    warper->x1max = warper->x1min + 32;
 
220
    warper->x2min = warper->x2 & ~31;
 
221
    warper->x2max = warper->x2min + 32;
 
222
 
 
223
    if ( warper->x1max > warper->x2 )
 
224
      warper->x1max = warper->x2;
 
225
 
 
226
    if ( warper->x2min < warper->x1 )
 
227
      warper->x2min = warper->x1;
 
228
 
 
229
    warper->w0 = warper->x2 - warper->x1;
 
230
 
 
231
    if ( warper->w0 <= 64 )
 
232
    {
 
233
      warper->x1max = warper->x1;
 
234
      warper->x2min = warper->x2;
 
235
    }
 
236
 
 
237
    warper->wmin = warper->x2min - warper->x1max;
 
238
    warper->wmax = warper->x2max - warper->x1min;
 
239
 
 
240
#if 1
 
241
    {
 
242
      int  margin = 16;
 
243
 
 
244
 
 
245
      if ( warper->w0 <= 128 )
 
246
      {
 
247
         margin = 8;
 
248
         if ( warper->w0 <= 96 )
 
249
           margin = 4;
 
250
      }
 
251
 
 
252
      if ( warper->wmin < warper->w0 - margin )
 
253
        warper->wmin = warper->w0 - margin;
 
254
 
 
255
      if ( warper->wmax > warper->w0 + margin )
 
256
        warper->wmax = warper->w0 + margin;
 
257
    }
 
258
 
 
259
    if ( warper->wmin < warper->w0 * 3 / 4 )
 
260
      warper->wmin = warper->w0 * 3 / 4;
 
261
 
 
262
    if ( warper->wmax > warper->w0 * 5 / 4 )
 
263
      warper->wmax = warper->w0 * 5 / 4;
 
264
#else
 
265
    /* no scaling, just translation */
 
266
    warper->wmin = warper->wmax = warper->w0;
 
267
#endif
 
268
 
 
269
    for ( w = warper->wmin; w <= warper->wmax; w++ )
 
270
    {
 
271
      FT_Fixed  new_scale;
 
272
      FT_Pos    new_delta;
 
273
      FT_Pos    xx1, xx2;
 
274
 
 
275
 
 
276
      xx1 = warper->x1;
 
277
      xx2 = warper->x2;
 
278
      if ( w >= warper->w0 )
 
279
      {
 
280
        xx1 -= w - warper->w0;
 
281
        if ( xx1 < warper->x1min )
 
282
        {
 
283
          xx2 += warper->x1min - xx1;
 
284
          xx1  = warper->x1min;
 
285
        }
 
286
      }
 
287
      else
 
288
      {
 
289
        xx1 -= w - warper->w0;
 
290
        if ( xx1 > warper->x1max )
 
291
        {
 
292
          xx2 -= xx1 - warper->x1max;
 
293
          xx1  = warper->x1max;
 
294
        }
 
295
      }
 
296
 
 
297
      if ( xx1 < warper->x1 )
 
298
        base_distort = warper->x1 - xx1;
 
299
      else
 
300
        base_distort = xx1 - warper->x1;
 
301
 
 
302
      if ( xx2 < warper->x2 )
 
303
        base_distort += warper->x2 - xx2;
 
304
      else
 
305
        base_distort += xx2 - warper->x2;
 
306
 
 
307
      base_distort *= 10;
 
308
 
 
309
      new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
 
310
      new_delta = xx1 - FT_MulFix( X1, new_scale );
 
311
 
 
312
      af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
 
313
                                   base_distort,
 
314
                                   segments, num_segments );
 
315
    }
 
316
 
 
317
    {
 
318
      FT_Fixed  best_scale = warper->best_scale;
 
319
      FT_Pos    best_delta = warper->best_delta;
 
320
     
 
321
 
 
322
      hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
 
323
                          + best_delta;
 
324
      hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
 
325
                          + best_delta;
 
326
 
 
327
      *a_scale = best_scale;
 
328
      *a_delta = best_delta;
 
329
    }
 
330
  }
 
331
 
 
332
#else /* !AF_USE_WARPER */
 
333
 
 
334
char  af_warper_dummy = 0;  /* make compiler happy */
 
335
 
 
336
#endif /* !AF_USE_WARPER */
 
337
 
 
338
/* END */