1 /***************************************************************************/
5 /* Auto-fitter warping algorithm (body). */
7 /* Copyright 2006, 2007 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
24 static const AF_WarpScore
25 af_warper_weights
[64] =
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,
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,
34 static const AF_WarpScore
35 af_warper_weights
[64] =
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,
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,
47 af_warper_compute_line_best( AF_Warper warper
,
52 AF_WarpScore base_distort
,
54 FT_UInt num_segments
)
56 FT_Int idx_min
, idx_max
, idx0
;
58 AF_WarpScore scores
[65];
61 for ( nn
= 0; nn
< 65; nn
++ )
64 idx0
= xx1
- warper
->t1
;
66 /* compute minimum and maximum indices */
68 FT_Pos xx1min
= warper
->x1min
;
69 FT_Pos xx1max
= warper
->x1max
;
73 if ( xx1min
+ w
< warper
->x2min
)
74 xx1min
= warper
->x2min
- w
;
76 xx1max
= warper
->x1max
;
77 if ( xx1max
+ w
> warper
->x2max
)
78 xx1max
= warper
->x2max
- w
;
80 idx_min
= xx1min
- warper
->t1
;
81 idx_max
= xx1max
- warper
->t1
;
83 if ( idx_min
< 0 || idx_min
> idx_max
|| idx_max
> 64 )
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
));
95 for ( nn
= 0; nn
< num_segments
; nn
++ )
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
);
103 for ( idx
= idx_min
; idx
<= idx_max
; idx
++, y
++ )
104 scores
[idx
] += af_warper_weights
[y
& 63] * len
;
107 /* find best score */
112 for ( idx
= idx_min
; idx
<= idx_max
; idx
++ )
114 AF_WarpScore score
= scores
[idx
];
115 AF_WarpScore distort
= base_distort
+ ( idx
- idx0
);
118 if ( score
> warper
->best_score
||
119 ( score
== warper
->best_score
&&
120 distort
< warper
->best_distort
) )
122 warper
->best_score
= score
;
123 warper
->best_distort
= distort
;
124 warper
->best_scale
= scale
;
125 warper
->best_delta
= delta
+ ( idx
- idx0
);
133 af_warper_compute( AF_Warper warper
,
145 FT_UInt nn
, num_points
, num_segments
;
149 AF_WarpScore base_distort
;
153 /* get original scaling transformation */
154 if ( dim
== AF_DIMENSION_VERT
)
156 org_scale
= hints
->y_scale
;
157 org_delta
= hints
->y_delta
;
161 org_scale
= hints
->x_scale
;
162 org_delta
= hints
->x_delta
;
165 warper
->best_scale
= org_scale
;
166 warper
->best_delta
= org_delta
;
167 warper
->best_score
= INT_MIN
;
168 warper
->best_distort
= 0;
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
;
176 *a_scale
= org_scale
;
177 *a_delta
= org_delta
;
179 /* get X1 and X2, minimum and maximum in original coordinates */
180 if ( num_segments
< 1 )
184 X1
= X2
= points
[0].fx
;
185 for ( nn
= 1; nn
< num_points
; nn
++ )
187 FT_Int X
= points
[nn
].fx
;
196 X1
= X2
= segments
[0].pos
;
197 for ( nn
= 1; nn
< num_segments
; nn
++ )
199 FT_Int X
= segments
[nn
].pos
;
212 warper
->x1
= FT_MulFix( X1
, org_scale
) + org_delta
;
213 warper
->x2
= FT_MulFix( X2
, org_scale
) + org_delta
;
215 warper
->t1
= AF_WARPER_FLOOR( warper
->x1
);
216 warper
->t2
= AF_WARPER_CEIL( warper
->x2
);
218 warper
->x1min
= warper
->x1
& ~31;
219 warper
->x1max
= warper
->x1min
+ 32;
220 warper
->x2min
= warper
->x2
& ~31;
221 warper
->x2max
= warper
->x2min
+ 32;
223 if ( warper
->x1max
> warper
->x2
)
224 warper
->x1max
= warper
->x2
;
226 if ( warper
->x2min
< warper
->x1
)
227 warper
->x2min
= warper
->x1
;
229 warper
->w0
= warper
->x2
- warper
->x1
;
231 if ( warper
->w0
<= 64 )
233 warper
->x1max
= warper
->x1
;
234 warper
->x2min
= warper
->x2
;
237 warper
->wmin
= warper
->x2min
- warper
->x1max
;
238 warper
->wmax
= warper
->x2max
- warper
->x1min
;
245 if ( warper
->w0
<= 128 )
248 if ( warper
->w0
<= 96 )
252 if ( warper
->wmin
< warper
->w0
- margin
)
253 warper
->wmin
= warper
->w0
- margin
;
255 if ( warper
->wmax
> warper
->w0
+ margin
)
256 warper
->wmax
= warper
->w0
+ margin
;
259 if ( warper
->wmin
< warper
->w0
* 3 / 4 )
260 warper
->wmin
= warper
->w0
* 3 / 4;
262 if ( warper
->wmax
> warper
->w0
* 5 / 4 )
263 warper
->wmax
= warper
->w0
* 5 / 4;
265 /* no scaling, just translation */
266 warper
->wmin
= warper
->wmax
= warper
->w0
;
269 for ( w
= warper
->wmin
; w
<= warper
->wmax
; w
++ )
278 if ( w
>= warper
->w0
)
280 xx1
-= w
- warper
->w0
;
281 if ( xx1
< warper
->x1min
)
283 xx2
+= warper
->x1min
- xx1
;
289 xx1
-= w
- warper
->w0
;
290 if ( xx1
> warper
->x1max
)
292 xx2
-= xx1
- warper
->x1max
;
297 if ( xx1
< warper
->x1
)
298 base_distort
= warper
->x1
- xx1
;
300 base_distort
= xx1
- warper
->x1
;
302 if ( xx2
< warper
->x2
)
303 base_distort
+= warper
->x2
- xx2
;
305 base_distort
+= xx2
- warper
->x2
;
309 new_scale
= org_scale
+ FT_DivFix( w
- warper
->w0
, X2
- X1
);
310 new_delta
= xx1
- FT_MulFix( X1
, new_scale
);
312 af_warper_compute_line_best( warper
, new_scale
, new_delta
, xx1
, xx2
,
314 segments
, num_segments
);
318 FT_Fixed best_scale
= warper
->best_scale
;
319 FT_Pos best_delta
= warper
->best_delta
;
322 hints
->xmin_delta
= FT_MulFix( X1
, best_scale
- org_scale
)
324 hints
->xmax_delta
= FT_MulFix( X2
, best_scale
- org_scale
)
327 *a_scale
= best_scale
;
328 *a_delta
= best_delta
;
332 #else /* !AF_USE_WARPER */
334 char af_warper_dummy
= 0; /* make compiler happy */
336 #endif /* !AF_USE_WARPER */