afwarp.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  afwarp.c                                                               */
00004 /*                                                                         */
00005 /*    Auto-fitter warping algorithm (body).                                */
00006 /*                                                                         */
00007 /*  Copyright 2006, 2007 by                                                */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include "afwarp.h"
00020 
00021 #ifdef AF_USE_WARPER
00022 
00023 #if 1
00024   static const AF_WarpScore
00025   af_warper_weights[64] =
00026   {
00027     35, 32, 30, 25, 20, 15, 12, 10,  5,  1,  0,  0,  0,  0,  0,  0,
00028      0,  0,  0,  0,  0,  0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
00029 
00030    -30,-30,-20,-20,-10,-10, -8, -5, -2, -1,  0,  0,  0,  0,  0,  0,
00031      0,  0,  0,  0,  0,  0,  0,  1,  5, 10, 12, 15, 20, 25, 30, 32,
00032   };
00033 #else
00034   static const AF_WarpScore
00035   af_warper_weights[64] =
00036   {
00037     30, 20, 10,  5,  4,  4,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,
00038      0,  0,  0,  0,  0,  0,  0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
00039 
00040    -20,-15,-15,-10,-10, -5, -5, -2, -2, -1,  0,  0,  0,  0,  0,  0,
00041      0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  4,  5, 10, 20,
00042   };
00043 #endif
00044 
00045 
00046   static void
00047   af_warper_compute_line_best( AF_Warper     warper,
00048                                FT_Fixed      scale,
00049                                FT_Pos        delta,
00050                                FT_Pos        xx1,
00051                                FT_Pos        xx2,
00052                                AF_WarpScore  base_distort,
00053                                AF_Segment    segments,
00054                                FT_UInt       num_segments )
00055   {
00056     FT_Int        idx_min, idx_max, idx0;
00057     FT_UInt       nn;
00058     AF_WarpScore  scores[65];
00059 
00060 
00061     for ( nn = 0; nn < 65; nn++ )
00062       scores[nn] = 0;
00063 
00064     idx0 = xx1 - warper->t1;
00065 
00066     /* compute minimum and maximum indices */
00067     {
00068       FT_Pos  xx1min = warper->x1min;
00069       FT_Pos  xx1max = warper->x1max;
00070       FT_Pos  w      = xx2 - xx1;
00071 
00072 
00073       if ( xx1min + w < warper->x2min )
00074         xx1min = warper->x2min - w;
00075 
00076       xx1max = warper->x1max;
00077       if ( xx1max + w > warper->x2max )
00078         xx1max = warper->x2max - w;
00079 
00080       idx_min = xx1min - warper->t1;
00081       idx_max = xx1max - warper->t1;
00082 
00083       if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
00084       {
00085         AF_LOG(( "invalid indices:\n"
00086                  "  min=%d max=%d, xx1=%ld xx2=%ld,\n"
00087                  "  x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
00088                  idx_min, idx_max, xx1, xx2,
00089                  warper->x1min, warper->x1max,
00090                  warper->x2min, warper->x2max ));
00091         return;
00092       }
00093     }
00094 
00095     for ( nn = 0; nn < num_segments; nn++ )
00096     {
00097       FT_Pos  len = segments[nn].max_coord - segments[nn].min_coord;
00098       FT_Pos  y0  = FT_MulFix( segments[nn].pos, scale ) + delta;
00099       FT_Pos  y   = y0 + ( idx_min - idx0 );
00100       FT_Int  idx;
00101 
00102 
00103       for ( idx = idx_min; idx <= idx_max; idx++, y++ )
00104         scores[idx] += af_warper_weights[y & 63] * len;
00105     }
00106 
00107     /* find best score */
00108     {
00109       FT_Int  idx;
00110 
00111 
00112       for ( idx = idx_min; idx <= idx_max; idx++ )
00113       {
00114         AF_WarpScore  score = scores[idx];
00115         AF_WarpScore  distort = base_distort + ( idx - idx0 );
00116 
00117 
00118         if ( score > warper->best_score           ||
00119              ( score == warper->best_score    &&
00120                distort < warper->best_distort )   )
00121         {
00122           warper->best_score   = score;
00123           warper->best_distort = distort;
00124           warper->best_scale   = scale;
00125           warper->best_delta   = delta + ( idx - idx0 );
00126         }
00127       }
00128     }
00129   }
00130 
00131 
00132   FT_LOCAL_DEF( void )
00133   af_warper_compute( AF_Warper      warper,
00134                      AF_GlyphHints  hints,
00135                      AF_Dimension   dim,
00136                      FT_Fixed      *a_scale,
00137                      FT_Pos        *a_delta )
00138   {
00139     AF_AxisHints  axis;
00140     AF_Point      points;
00141 
00142     FT_Fixed      org_scale;
00143     FT_Pos        org_delta;
00144 
00145     FT_UInt       nn, num_points, num_segments;
00146     FT_Int        X1, X2;
00147     FT_Int        w;
00148 
00149     AF_WarpScore  base_distort;
00150     AF_Segment    segments;
00151 
00152 
00153     /* get original scaling transformation */
00154     if ( dim == AF_DIMENSION_VERT )
00155     {
00156       org_scale = hints->y_scale;
00157       org_delta = hints->y_delta;
00158     }
00159     else
00160     {
00161       org_scale = hints->x_scale;
00162       org_delta = hints->x_delta;
00163     }
00164 
00165     warper->best_scale   = org_scale;
00166     warper->best_delta   = org_delta;
00167     warper->best_score   = INT_MIN;
00168     warper->best_distort = 0;
00169 
00170     axis         = &hints->axis[dim];
00171     segments     = axis->segments;
00172     num_segments = axis->num_segments;
00173     points       = hints->points;
00174     num_points   = hints->num_points;
00175 
00176     *a_scale = org_scale;
00177     *a_delta = org_delta;
00178 
00179     /* get X1 and X2, minimum and maximum in original coordinates */
00180     if ( num_segments < 1 )
00181       return;
00182 
00183 #if 1
00184     X1 = X2 = points[0].fx;
00185     for ( nn = 1; nn < num_points; nn++ )
00186     {
00187       FT_Int  X = points[nn].fx;
00188 
00189 
00190       if ( X < X1 )
00191         X1 = X;
00192       if ( X > X2 )
00193         X2 = X;
00194     }
00195 #else
00196     X1 = X2 = segments[0].pos;
00197     for ( nn = 1; nn < num_segments; nn++ )
00198     {
00199       FT_Int  X = segments[nn].pos;
00200 
00201 
00202       if ( X < X1 )
00203         X1 = X;
00204       if ( X > X2 )
00205         X2 = X;
00206     }
00207 #endif
00208 
00209     if ( X1 >= X2 )
00210       return;
00211 
00212     warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
00213     warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
00214 
00215     warper->t1 = AF_WARPER_FLOOR( warper->x1 );
00216     warper->t2 = AF_WARPER_CEIL( warper->x2 );
00217 
00218     warper->x1min = warper->x1 & ~31;
00219     warper->x1max = warper->x1min + 32;
00220     warper->x2min = warper->x2 & ~31;
00221     warper->x2max = warper->x2min + 32;
00222 
00223     if ( warper->x1max > warper->x2 )
00224       warper->x1max = warper->x2;
00225 
00226     if ( warper->x2min < warper->x1 )
00227       warper->x2min = warper->x1;
00228 
00229     warper->w0 = warper->x2 - warper->x1;
00230 
00231     if ( warper->w0 <= 64 )
00232     {
00233       warper->x1max = warper->x1;
00234       warper->x2min = warper->x2;
00235     }
00236 
00237     warper->wmin = warper->x2min - warper->x1max;
00238     warper->wmax = warper->x2max - warper->x1min;
00239 
00240 #if 1
00241     {
00242       int  margin = 16;
00243 
00244 
00245       if ( warper->w0 <= 128 )
00246       {
00247          margin = 8;
00248          if ( warper->w0 <= 96 )
00249            margin = 4;
00250       }
00251 
00252       if ( warper->wmin < warper->w0 - margin )
00253         warper->wmin = warper->w0 - margin;
00254 
00255       if ( warper->wmax > warper->w0 + margin )
00256         warper->wmax = warper->w0 + margin;
00257     }
00258 
00259     if ( warper->wmin < warper->w0 * 3 / 4 )
00260       warper->wmin = warper->w0 * 3 / 4;
00261 
00262     if ( warper->wmax > warper->w0 * 5 / 4 )
00263       warper->wmax = warper->w0 * 5 / 4;
00264 #else
00265     /* no scaling, just translation */
00266     warper->wmin = warper->wmax = warper->w0;
00267 #endif
00268 
00269     for ( w = warper->wmin; w <= warper->wmax; w++ )
00270     {
00271       FT_Fixed  new_scale;
00272       FT_Pos    new_delta;
00273       FT_Pos    xx1, xx2;
00274 
00275 
00276       xx1 = warper->x1;
00277       xx2 = warper->x2;
00278       if ( w >= warper->w0 )
00279       {
00280         xx1 -= w - warper->w0;
00281         if ( xx1 < warper->x1min )
00282         {
00283           xx2 += warper->x1min - xx1;
00284           xx1  = warper->x1min;
00285         }
00286       }
00287       else
00288       {
00289         xx1 -= w - warper->w0;
00290         if ( xx1 > warper->x1max )
00291         {
00292           xx2 -= xx1 - warper->x1max;
00293           xx1  = warper->x1max;
00294         }
00295       }
00296 
00297       if ( xx1 < warper->x1 )
00298         base_distort = warper->x1 - xx1;
00299       else
00300         base_distort = xx1 - warper->x1;
00301 
00302       if ( xx2 < warper->x2 )
00303         base_distort += warper->x2 - xx2;
00304       else
00305         base_distort += xx2 - warper->x2;
00306 
00307       base_distort *= 10;
00308 
00309       new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
00310       new_delta = xx1 - FT_MulFix( X1, new_scale );
00311 
00312       af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
00313                                    base_distort,
00314                                    segments, num_segments );
00315     }
00316 
00317     {
00318       FT_Fixed  best_scale = warper->best_scale;
00319       FT_Pos    best_delta = warper->best_delta;
00320      
00321 
00322       hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
00323                           + best_delta;
00324       hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
00325                           + best_delta;
00326 
00327       *a_scale = best_scale;
00328       *a_delta = best_delta;
00329     }
00330   }
00331 
00332 #else /* !AF_USE_WARPER */
00333 
00334 char  af_warper_dummy = 0;  /* make compiler happy */
00335 
00336 #endif /* !AF_USE_WARPER */
00337 
00338 /* END */

Generated on Tue Jul 5 14:13:42 2011 for ROOT_528-00b_version by  doxygen 1.5.1