ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

afhints.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  afhints.c                                                              */
00004 /*                                                                         */
00005 /*    Auto-fitter hinting routines (body).                                 */
00006 /*                                                                         */
00007 /*  Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 "afhints.h"
00020 #include "aferrors.h"
00021 #include FT_INTERNAL_CALC_H
00022 
00023 
00024   FT_LOCAL_DEF( FT_Error )
00025   af_axis_hints_new_segment( AF_AxisHints  axis,
00026                              FT_Memory     memory,
00027                              AF_Segment   *asegment )
00028   {
00029     FT_Error    error   = AF_Err_Ok;
00030     AF_Segment  segment = NULL;
00031 
00032 
00033     if ( axis->num_segments >= axis->max_segments )
00034     {
00035       FT_Int  old_max = axis->max_segments;
00036       FT_Int  new_max = old_max;
00037       FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );
00038 
00039 
00040       if ( old_max >= big_max )
00041       {
00042         error = AF_Err_Out_Of_Memory;
00043         goto Exit;
00044       }
00045 
00046       new_max += ( new_max >> 2 ) + 4;
00047       if ( new_max < old_max || new_max > big_max )
00048         new_max = big_max;
00049 
00050       if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
00051         goto Exit;
00052 
00053       axis->max_segments = new_max;
00054     }
00055 
00056     segment = axis->segments + axis->num_segments++;
00057 
00058   Exit:
00059     *asegment = segment;
00060     return error;
00061   }
00062 
00063 
00064   FT_LOCAL( FT_Error )
00065   af_axis_hints_new_edge( AF_AxisHints  axis,
00066                           FT_Int        fpos,
00067                           AF_Direction  dir,
00068                           FT_Memory     memory,
00069                           AF_Edge      *aedge )
00070   {
00071     FT_Error  error = AF_Err_Ok;
00072     AF_Edge   edge  = NULL;
00073     AF_Edge   edges;
00074 
00075 
00076     if ( axis->num_edges >= axis->max_edges )
00077     {
00078       FT_Int  old_max = axis->max_edges;
00079       FT_Int  new_max = old_max;
00080       FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
00081 
00082 
00083       if ( old_max >= big_max )
00084       {
00085         error = AF_Err_Out_Of_Memory;
00086         goto Exit;
00087       }
00088 
00089       new_max += ( new_max >> 2 ) + 4;
00090       if ( new_max < old_max || new_max > big_max )
00091         new_max = big_max;
00092 
00093       if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
00094         goto Exit;
00095 
00096       axis->max_edges = new_max;
00097     }
00098 
00099     edges = axis->edges;
00100     edge  = edges + axis->num_edges;
00101 
00102     while ( edge > edges )
00103     {
00104       if ( edge[-1].fpos < fpos )
00105         break;
00106 
00107       /* we want the edge with same position and minor direction */
00108       /* to appear before those in the major one in the list     */
00109       if ( edge[-1].fpos == fpos && dir == axis->major_dir )
00110         break;
00111 
00112       edge[0] = edge[-1];
00113       edge--;
00114     }
00115 
00116     axis->num_edges++;
00117 
00118     FT_ZERO( edge );
00119     edge->fpos = (FT_Short)fpos;
00120     edge->dir  = (FT_Char)dir;
00121 
00122   Exit:
00123     *aedge = edge;
00124     return error;
00125   }
00126 
00127 
00128 #ifdef AF_DEBUG
00129 
00130 #include FT_CONFIG_STANDARD_LIBRARY_H
00131 
00132   static const char*
00133   af_dir_str( AF_Direction  dir )
00134   {
00135     const char*  result;
00136 
00137 
00138     switch ( dir )
00139     {
00140     case AF_DIR_UP:
00141       result = "up";
00142       break;
00143     case AF_DIR_DOWN:
00144       result = "down";
00145       break;
00146     case AF_DIR_LEFT:
00147       result = "left";
00148       break;
00149     case AF_DIR_RIGHT:
00150       result = "right";
00151       break;
00152     default:
00153       result = "none";
00154     }
00155 
00156     return result;
00157   }
00158 
00159 
00160 #define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )
00161 
00162 
00163   void
00164   af_glyph_hints_dump_points( AF_GlyphHints  hints )
00165   {
00166     AF_Point  points = hints->points;
00167     AF_Point  limit  = points + hints->num_points;
00168     AF_Point  point;
00169 
00170 
00171     printf( "Table of points:\n" );
00172     printf(   "  [ index |  xorg |  yorg |  xscale |  yscale "
00173               "|  xfit  |  yfit  |  flags ]\n" );
00174 
00175     for ( point = points; point < limit; point++ )
00176     {
00177       printf( "  [ %5d | %5d | %5d | %-5.2f | %-5.2f "
00178               "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
00179               point - points,
00180               point->fx,
00181               point->fy,
00182               point->ox/64.0,
00183               point->oy/64.0,
00184               point->x/64.0,
00185               point->y/64.0,
00186               ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
00187               ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
00188               ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
00189               ( point->flags & AF_FLAG_EXTREMA_Y )          ? 'v' : ' ',
00190               ( point->flags & AF_FLAG_ROUND_X )            ? '(' : ' ',
00191               ( point->flags & AF_FLAG_ROUND_Y )            ? 'u' : ' ');
00192     }
00193     printf( "\n" );
00194   }
00195 
00196 
00197   static const char*
00198   af_edge_flags_to_string( AF_Edge_Flags  flags )
00199   {
00200     static char  temp[32];
00201     int          pos = 0;
00202 
00203 
00204     if ( flags & AF_EDGE_ROUND )
00205     {
00206       ft_memcpy( temp + pos, "round", 5 );
00207       pos += 5;
00208     }
00209     if ( flags & AF_EDGE_SERIF )
00210     {
00211       if ( pos > 0 )
00212         temp[pos++] = ' ';
00213       ft_memcpy( temp + pos, "serif", 5 );
00214       pos += 5;
00215     }
00216     if ( pos == 0 )
00217       return "normal";
00218 
00219     temp[pos] = 0;
00220 
00221     return temp;
00222   }
00223 
00224 
00225   /* A function to dump the array of linked segments. */
00226   void
00227   af_glyph_hints_dump_segments( AF_GlyphHints  hints )
00228   {
00229     FT_Int  dimension;
00230 
00231 
00232     for ( dimension = 1; dimension >= 0; dimension-- )
00233     {
00234       AF_AxisHints  axis     = &hints->axis[dimension];
00235       AF_Segment    segments = axis->segments;
00236       AF_Segment    limit    = segments + axis->num_segments;
00237       AF_Segment    seg;
00238 
00239 
00240       printf ( "Table of %s segments:\n",
00241                dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
00242       printf ( "  [ index |  pos  |  dir  | link | serif |"
00243                " height  | extra | flags    ]\n" );
00244 
00245       for ( seg = segments; seg < limit; seg++ )
00246       {
00247         printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
00248                  seg - segments,
00249                  dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
00250                                                 : (int)seg->first->oy / 64.0,
00251                  af_dir_str( (AF_Direction)seg->dir ),
00252                  AF_INDEX_NUM( seg->link, segments ),
00253                  AF_INDEX_NUM( seg->serif, segments ),
00254                  seg->height,
00255                  seg->height - ( seg->max_coord - seg->min_coord ),
00256                  af_edge_flags_to_string( seg->flags ) );
00257       }
00258       printf( "\n" );
00259     }
00260   }
00261 
00262 
00263   void
00264   af_glyph_hints_dump_edges( AF_GlyphHints  hints )
00265   {
00266     FT_Int  dimension;
00267 
00268 
00269     for ( dimension = 1; dimension >= 0; dimension-- )
00270     {
00271       AF_AxisHints  axis  = &hints->axis[dimension];
00272       AF_Edge       edges = axis->edges;
00273       AF_Edge       limit = edges + axis->num_edges;
00274       AF_Edge       edge;
00275 
00276 
00277       /*
00278        *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
00279        *        since they have constant a X coordinate.
00280        */
00281       printf ( "Table of %s edges:\n",
00282                dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
00283       printf ( "  [ index |  pos  |  dir  | link |"
00284                " serif | blue | opos  |  pos  | flags   ]\n" );
00285 
00286       for ( edge = edges; edge < limit; edge++ )
00287       {
00288         printf ( "  [ %5d | %5.2g | %5s | %4d |"
00289                  " %5d |   %c  | %5.2f | %5.2f | %s ]\n",
00290                  edge - edges,
00291                  (int)edge->opos / 64.0,
00292                  af_dir_str( (AF_Direction)edge->dir ),
00293                  AF_INDEX_NUM( edge->link, edges ),
00294                  AF_INDEX_NUM( edge->serif, edges ),
00295                  edge->blue_edge ? 'y' : 'n',
00296                  edge->opos / 64.0,
00297                  edge->pos / 64.0,
00298                  af_edge_flags_to_string( edge->flags ) );
00299       }
00300       printf( "\n" );
00301     }
00302   }
00303 
00304 #else /* !AF_DEBUG */
00305 
00306   /* these empty stubs are only used to link the `ftgrid' test program */
00307   /* when debugging is disabled                                        */
00308 
00309   void
00310   af_glyph_hints_dump_points( AF_GlyphHints  hints )
00311   {
00312     FT_UNUSED( hints );
00313   }
00314 
00315 
00316   void
00317   af_glyph_hints_dump_segments( AF_GlyphHints  hints )
00318   {
00319     FT_UNUSED( hints );
00320   }
00321 
00322 
00323   void
00324   af_glyph_hints_dump_edges( AF_GlyphHints  hints )
00325   {
00326     FT_UNUSED( hints );
00327   }
00328 
00329 #endif /* !AF_DEBUG */
00330 
00331 
00332   /* compute the direction value of a given vector */
00333   FT_LOCAL_DEF( AF_Direction )
00334   af_direction_compute( FT_Pos  dx,
00335                         FT_Pos  dy )
00336   {
00337     FT_Pos        ll, ss;  /* long and short arm lengths */
00338     AF_Direction  dir;     /* candidate direction        */
00339 
00340 
00341     if ( dy >= dx )
00342     {
00343       if ( dy >= -dx )
00344       {
00345         dir = AF_DIR_UP;
00346         ll  = dy;
00347         ss  = dx;
00348       }
00349       else
00350       {
00351         dir = AF_DIR_LEFT;
00352         ll  = -dx;
00353         ss  = dy;
00354       }
00355     }
00356     else /* dy < dx */
00357     {
00358       if ( dy >= -dx )
00359       {
00360         dir = AF_DIR_RIGHT;
00361         ll  = dx;
00362         ss  = dy;
00363       }
00364       else
00365       {
00366         dir = AF_DIR_DOWN;
00367         ll  = dy;
00368         ss  = dx;
00369       }
00370     }
00371 
00372     ss *= 14;
00373     if ( FT_ABS( ll ) <= FT_ABS( ss ) )
00374       dir = AF_DIR_NONE;
00375 
00376     return dir;
00377   }
00378 
00379 
00380   FT_LOCAL_DEF( void )
00381   af_glyph_hints_init( AF_GlyphHints  hints,
00382                        FT_Memory      memory )
00383   {
00384     FT_ZERO( hints );
00385     hints->memory = memory;
00386   }
00387 
00388 
00389   FT_LOCAL_DEF( void )
00390   af_glyph_hints_done( AF_GlyphHints  hints )
00391   {
00392     if ( hints && hints->memory )
00393     {
00394       FT_Memory  memory = hints->memory;
00395       int        dim;
00396 
00397 
00398       /*
00399        *  note that we don't need to free the segment and edge
00400        *  buffers, since they are really within the hints->points array
00401        */
00402       for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
00403       {
00404         AF_AxisHints  axis = &hints->axis[dim];
00405 
00406 
00407         axis->num_segments = 0;
00408         axis->max_segments = 0;
00409         FT_FREE( axis->segments );
00410 
00411         axis->num_edges    = 0;
00412         axis->max_edges    = 0;
00413         FT_FREE( axis->edges );
00414       }
00415 
00416       FT_FREE( hints->contours );
00417       hints->max_contours = 0;
00418       hints->num_contours = 0;
00419 
00420       FT_FREE( hints->points );
00421       hints->num_points = 0;
00422       hints->max_points = 0;
00423 
00424       hints->memory = NULL;
00425     }
00426   }
00427 
00428 
00429   FT_LOCAL_DEF( void )
00430   af_glyph_hints_rescale( AF_GlyphHints     hints,
00431                           AF_ScriptMetrics  metrics )
00432   {
00433     hints->metrics      = metrics;
00434     hints->scaler_flags = metrics->scaler.flags;
00435   }
00436 
00437 
00438   FT_LOCAL_DEF( FT_Error )
00439   af_glyph_hints_reload( AF_GlyphHints  hints,
00440                          FT_Outline*    outline )
00441   {
00442     FT_Error   error   = AF_Err_Ok;
00443     AF_Point   points;
00444     FT_UInt    old_max, new_max;
00445     FT_Fixed   x_scale = hints->x_scale;
00446     FT_Fixed   y_scale = hints->y_scale;
00447     FT_Pos     x_delta = hints->x_delta;
00448     FT_Pos     y_delta = hints->y_delta;
00449     FT_Memory  memory  = hints->memory;
00450 
00451 
00452     hints->num_points   = 0;
00453     hints->num_contours = 0;
00454 
00455     hints->axis[0].num_segments = 0;
00456     hints->axis[0].num_edges    = 0;
00457     hints->axis[1].num_segments = 0;
00458     hints->axis[1].num_edges    = 0;
00459 
00460     /* first of all, reallocate the contours array when necessary */
00461     new_max = (FT_UInt)outline->n_contours;
00462     old_max = hints->max_contours;
00463     if ( new_max > old_max )
00464     {
00465       new_max = ( new_max + 3 ) & ~3;
00466 
00467       if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
00468         goto Exit;
00469 
00470       hints->max_contours = new_max;
00471     }
00472 
00473     /*
00474      *  then reallocate the points arrays if necessary --
00475      *  note that we reserve two additional point positions, used to
00476      *  hint metrics appropriately
00477      */
00478     new_max = (FT_UInt)( outline->n_points + 2 );
00479     old_max = hints->max_points;
00480     if ( new_max > old_max )
00481     {
00482       new_max = ( new_max + 2 + 7 ) & ~7;
00483 
00484       if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
00485         goto Exit;
00486 
00487       hints->max_points = new_max;
00488     }
00489 
00490     hints->num_points   = outline->n_points;
00491     hints->num_contours = outline->n_contours;
00492 
00493     /* We can't rely on the value of `FT_Outline.flags' to know the fill   */
00494     /* direction used for a glyph, given that some fonts are broken (e.g., */
00495     /* the Arphic ones).  We thus recompute it each time we need to.       */
00496     /*                                                                     */
00497     hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
00498     hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
00499 
00500     if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
00501     {
00502       hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
00503       hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
00504     }
00505 
00506     hints->x_scale = x_scale;
00507     hints->y_scale = y_scale;
00508     hints->x_delta = x_delta;
00509     hints->y_delta = y_delta;
00510 
00511     hints->xmin_delta = 0;
00512     hints->xmax_delta = 0;
00513 
00514     points = hints->points;
00515     if ( hints->num_points == 0 )
00516       goto Exit;
00517 
00518     {
00519       AF_Point  point;
00520       AF_Point  point_limit = points + hints->num_points;
00521 
00522 
00523       /* compute coordinates & Bezier flags, next and prev */
00524       {
00525         FT_Vector*  vec           = outline->points;
00526         char*       tag           = outline->tags;
00527         AF_Point    end           = points + outline->contours[0];
00528         AF_Point    prev          = end;
00529         FT_Int      contour_index = 0;
00530 
00531 
00532         for ( point = points; point < point_limit; point++, vec++, tag++ )
00533         {
00534           point->fx = (FT_Short)vec->x;
00535           point->fy = (FT_Short)vec->y;
00536           point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
00537           point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
00538 
00539           switch ( FT_CURVE_TAG( *tag ) )
00540           {
00541           case FT_CURVE_TAG_CONIC:
00542             point->flags = AF_FLAG_CONIC;
00543             break;
00544           case FT_CURVE_TAG_CUBIC:
00545             point->flags = AF_FLAG_CUBIC;
00546             break;
00547           default:
00548             point->flags = 0;
00549           }
00550 
00551           point->prev = prev;
00552           prev->next  = point;
00553           prev        = point;
00554 
00555           if ( point == end )
00556           {
00557             if ( ++contour_index < outline->n_contours )
00558             {
00559               end  = points + outline->contours[contour_index];
00560               prev = end;
00561             }
00562           }
00563         }
00564       }
00565 
00566       /* set-up the contours array */
00567       {
00568         AF_Point*  contour       = hints->contours;
00569         AF_Point*  contour_limit = contour + hints->num_contours;
00570         short*     end           = outline->contours;
00571         short      idx           = 0;
00572 
00573 
00574         for ( ; contour < contour_limit; contour++, end++ )
00575         {
00576           contour[0] = points + idx;
00577           idx        = (short)( end[0] + 1 );
00578         }
00579       }
00580 
00581       /* compute directions of in & out vectors */
00582       {
00583         AF_Point      first  = points;
00584         AF_Point      prev   = NULL;
00585         FT_Pos        in_x   = 0;
00586         FT_Pos        in_y   = 0;
00587         AF_Direction  in_dir = AF_DIR_NONE;
00588 
00589 
00590         for ( point = points; point < point_limit; point++ )
00591         {
00592           AF_Point  next;
00593           FT_Pos    out_x, out_y;
00594 
00595 
00596           if ( point == first )
00597           {
00598             prev   = first->prev;
00599             in_x   = first->fx - prev->fx;
00600             in_y   = first->fy - prev->fy;
00601             in_dir = af_direction_compute( in_x, in_y );
00602             first  = prev + 1;
00603           }
00604 
00605           point->in_dir = (FT_Char)in_dir;
00606 
00607           next  = point->next;
00608           out_x = next->fx - point->fx;
00609           out_y = next->fy - point->fy;
00610 
00611           in_dir         = af_direction_compute( out_x, out_y );
00612           point->out_dir = (FT_Char)in_dir;
00613 
00614           if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
00615           {
00616           Is_Weak_Point:
00617             point->flags |= AF_FLAG_WEAK_INTERPOLATION;
00618           }
00619           else if ( point->out_dir == point->in_dir )
00620           {
00621             if ( point->out_dir != AF_DIR_NONE )
00622               goto Is_Weak_Point;
00623 
00624             if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
00625               goto Is_Weak_Point;
00626           }
00627           else if ( point->in_dir == -point->out_dir )
00628             goto Is_Weak_Point;
00629 
00630           in_x = out_x;
00631           in_y = out_y;
00632           prev = point;
00633         }
00634       }
00635     }
00636 
00637   Exit:
00638     return error;
00639   }
00640 
00641 
00642   FT_LOCAL_DEF( void )
00643   af_glyph_hints_save( AF_GlyphHints  hints,
00644                        FT_Outline*    outline )
00645   {
00646     AF_Point    point = hints->points;
00647     AF_Point    limit = point + hints->num_points;
00648     FT_Vector*  vec   = outline->points;
00649     char*       tag   = outline->tags;
00650 
00651 
00652     for ( ; point < limit; point++, vec++, tag++ )
00653     {
00654       vec->x = point->x;
00655       vec->y = point->y;
00656 
00657       if ( point->flags & AF_FLAG_CONIC )
00658         tag[0] = FT_CURVE_TAG_CONIC;
00659       else if ( point->flags & AF_FLAG_CUBIC )
00660         tag[0] = FT_CURVE_TAG_CUBIC;
00661       else
00662         tag[0] = FT_CURVE_TAG_ON;
00663     }
00664   }
00665 
00666 
00667   /****************************************************************
00668    *
00669    *                     EDGE POINT GRID-FITTING
00670    *
00671    ****************************************************************/
00672 
00673 
00674   FT_LOCAL_DEF( void )
00675   af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
00676                                     AF_Dimension   dim )
00677   {
00678     AF_AxisHints  axis          = & hints->axis[dim];
00679     AF_Segment    segments      = axis->segments;
00680     AF_Segment    segment_limit = segments + axis->num_segments;
00681     AF_Segment    seg;
00682 
00683 
00684     if ( dim == AF_DIMENSION_HORZ )
00685     {
00686       for ( seg = segments; seg < segment_limit; seg++ )
00687       {
00688         AF_Edge   edge = seg->edge;
00689         AF_Point  point, first, last;
00690 
00691 
00692         if ( edge == NULL )
00693           continue;
00694 
00695         first = seg->first;
00696         last  = seg->last;
00697         point = first;
00698         for (;;)
00699         {
00700           point->x      = edge->pos;
00701           point->flags |= AF_FLAG_TOUCH_X;
00702 
00703           if ( point == last )
00704             break;
00705 
00706           point = point->next;
00707 
00708         }
00709       }
00710     }
00711     else
00712     {
00713       for ( seg = segments; seg < segment_limit; seg++ )
00714       {
00715         AF_Edge   edge = seg->edge;
00716         AF_Point  point, first, last;
00717 
00718 
00719         if ( edge == NULL )
00720           continue;
00721 
00722         first = seg->first;
00723         last  = seg->last;
00724         point = first;
00725         for (;;)
00726         {
00727           point->y      = edge->pos;
00728           point->flags |= AF_FLAG_TOUCH_Y;
00729 
00730           if ( point == last )
00731             break;
00732 
00733           point = point->next;
00734         }
00735       }
00736     }
00737   }
00738 
00739 
00740   /****************************************************************
00741    *
00742    *                    STRONG POINT INTERPOLATION
00743    *
00744    ****************************************************************/
00745 
00746 
00747   /* hint the strong points -- this is equivalent to the TrueType `IP' */
00748   /* hinting instruction                                               */
00749 
00750   FT_LOCAL_DEF( void )
00751   af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
00752                                       AF_Dimension   dim )
00753   {
00754     AF_Point      points      = hints->points;
00755     AF_Point      point_limit = points + hints->num_points;
00756     AF_AxisHints  axis        = &hints->axis[dim];
00757     AF_Edge       edges       = axis->edges;
00758     AF_Edge       edge_limit  = edges + axis->num_edges;
00759     AF_Flags      touch_flag;
00760 
00761 
00762     if ( dim == AF_DIMENSION_HORZ )
00763       touch_flag = AF_FLAG_TOUCH_X;
00764     else
00765       touch_flag  = AF_FLAG_TOUCH_Y;
00766 
00767     if ( edges < edge_limit )
00768     {
00769       AF_Point  point;
00770       AF_Edge   edge;
00771 
00772 
00773       for ( point = points; point < point_limit; point++ )
00774       {
00775         FT_Pos  u, ou, fu;  /* point position */
00776         FT_Pos  delta;
00777 
00778 
00779         if ( point->flags & touch_flag )
00780           continue;
00781 
00782         /* if this point is candidate to weak interpolation, we       */
00783         /* interpolate it after all strong points have been processed */
00784 
00785         if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
00786              !( point->flags & AF_FLAG_INFLECTION )         )
00787           continue;
00788 
00789         if ( dim == AF_DIMENSION_VERT )
00790         {
00791           u  = point->fy;
00792           ou = point->oy;
00793         }
00794         else
00795         {
00796           u  = point->fx;
00797           ou = point->ox;
00798         }
00799 
00800         fu = u;
00801 
00802         /* is the point before the first edge? */
00803         edge  = edges;
00804         delta = edge->fpos - u;
00805         if ( delta >= 0 )
00806         {
00807           u = edge->pos - ( edge->opos - ou );
00808           goto Store_Point;
00809         }
00810 
00811         /* is the point after the last edge? */
00812         edge  = edge_limit - 1;
00813         delta = u - edge->fpos;
00814         if ( delta >= 0 )
00815         {
00816           u = edge->pos + ( ou - edge->opos );
00817           goto Store_Point;
00818         }
00819 
00820         {
00821           FT_PtrDist  min, max, mid;
00822           FT_Pos      fpos;
00823 
00824 
00825           /* find enclosing edges */
00826           min = 0;
00827           max = edge_limit - edges;
00828 
00829 #if 1
00830           /* for small edge counts, a linear search is better */
00831           if ( max <= 8 )
00832           {
00833             FT_PtrDist  nn;
00834 
00835             for ( nn = 0; nn < max; nn++ )
00836               if ( edges[nn].fpos >= u )
00837                 break;
00838 
00839             if ( edges[nn].fpos == u )
00840             {
00841               u = edges[nn].pos;
00842               goto Store_Point;
00843             }
00844             min = nn;
00845           }
00846           else
00847 #endif
00848           while ( min < max )
00849           {
00850             mid  = ( max + min ) >> 1;
00851             edge = edges + mid;
00852             fpos = edge->fpos;
00853 
00854             if ( u < fpos )
00855               max = mid;
00856             else if ( u > fpos )
00857               min = mid + 1;
00858             else
00859             {
00860               /* we are on the edge */
00861               u = edge->pos;
00862               goto Store_Point;
00863             }
00864           }
00865 
00866           {
00867             AF_Edge  before = edges + min - 1;
00868             AF_Edge  after  = edges + min + 0;
00869 
00870 
00871             /* assert( before && after && before != after ) */
00872             if ( before->scale == 0 )
00873               before->scale = FT_DivFix( after->pos - before->pos,
00874                                          after->fpos - before->fpos );
00875 
00876             u = before->pos + FT_MulFix( fu - before->fpos,
00877                                          before->scale );
00878           }
00879         }
00880 
00881       Store_Point:
00882         /* save the point position */
00883         if ( dim == AF_DIMENSION_HORZ )
00884           point->x = u;
00885         else
00886           point->y = u;
00887 
00888         point->flags |= touch_flag;
00889       }
00890     }
00891   }
00892 
00893 
00894   /****************************************************************
00895    *
00896    *                    WEAK POINT INTERPOLATION
00897    *
00898    ****************************************************************/
00899 
00900 
00901   static void
00902   af_iup_shift( AF_Point  p1,
00903                 AF_Point  p2,
00904                 AF_Point  ref )
00905   {
00906     AF_Point  p;
00907     FT_Pos    delta = ref->u - ref->v;
00908 
00909     if ( delta == 0 )
00910       return;
00911 
00912     for ( p = p1; p < ref; p++ )
00913       p->u = p->v + delta;
00914 
00915     for ( p = ref + 1; p <= p2; p++ )
00916       p->u = p->v + delta;
00917   }
00918 
00919 
00920   static void
00921   af_iup_interp( AF_Point  p1,
00922                  AF_Point  p2,
00923                  AF_Point  ref1,
00924                  AF_Point  ref2 )
00925   {
00926     AF_Point  p;
00927     FT_Pos    u;
00928     FT_Pos    v1 = ref1->v;
00929     FT_Pos    v2 = ref2->v;
00930     FT_Pos    d1 = ref1->u - v1;
00931     FT_Pos    d2 = ref2->u - v2;
00932 
00933 
00934     if ( p1 > p2 )
00935       return;
00936 
00937     if ( v1 == v2 )
00938     {
00939       for ( p = p1; p <= p2; p++ )
00940       {
00941         u = p->v;
00942 
00943         if ( u <= v1 )
00944           u += d1;
00945         else
00946           u += d2;
00947 
00948         p->u = u;
00949       }
00950       return;
00951     }
00952 
00953     if ( v1 < v2 )
00954     {
00955       for ( p = p1; p <= p2; p++ )
00956       {
00957         u = p->v;
00958 
00959         if ( u <= v1 )
00960           u += d1;
00961         else if ( u >= v2 )
00962           u += d2;
00963         else
00964           u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
00965 
00966         p->u = u;
00967       }
00968     }
00969     else
00970     {
00971       for ( p = p1; p <= p2; p++ )
00972       {
00973         u = p->v;
00974 
00975         if ( u <= v2 )
00976           u += d2;
00977         else if ( u >= v1 )
00978           u += d1;
00979         else
00980           u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
00981 
00982         p->u = u;
00983       }
00984     }
00985   }
00986 
00987 
00988   FT_LOCAL_DEF( void )
00989   af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
00990                                     AF_Dimension   dim )
00991   {
00992     AF_Point   points        = hints->points;
00993     AF_Point   point_limit   = points + hints->num_points;
00994     AF_Point*  contour       = hints->contours;
00995     AF_Point*  contour_limit = contour + hints->num_contours;
00996     AF_Flags   touch_flag;
00997     AF_Point   point;
00998     AF_Point   end_point;
00999     AF_Point   first_point;
01000 
01001 
01002     /* PASS 1: Move segment points to edge positions */
01003 
01004     if ( dim == AF_DIMENSION_HORZ )
01005     {
01006       touch_flag = AF_FLAG_TOUCH_X;
01007 
01008       for ( point = points; point < point_limit; point++ )
01009       {
01010         point->u = point->x;
01011         point->v = point->ox;
01012       }
01013     }
01014     else
01015     {
01016       touch_flag = AF_FLAG_TOUCH_Y;
01017 
01018       for ( point = points; point < point_limit; point++ )
01019       {
01020         point->u = point->y;
01021         point->v = point->oy;
01022       }
01023     }
01024 
01025     point = points;
01026 
01027     for ( ; contour < contour_limit; contour++ )
01028     {
01029       AF_Point  first_touched, last_touched;
01030 
01031 
01032       point       = *contour;
01033       end_point   = point->prev;
01034       first_point = point;
01035 
01036       /* find first touched point */
01037       for (;;)
01038       {
01039         if ( point > end_point )  /* no touched point in contour */
01040           goto NextContour;
01041 
01042         if ( point->flags & touch_flag )
01043           break;
01044 
01045         point++;
01046       }
01047 
01048       first_touched = point;
01049       last_touched  = point;
01050 
01051       for (;;)
01052       {
01053         FT_ASSERT( point <= end_point &&
01054                    ( point->flags & touch_flag ) != 0 );
01055 
01056         /* skip any touched neighbhours */
01057         while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
01058           point++;
01059 
01060         last_touched = point;
01061 
01062         /* find the next touched point, if any */
01063         point ++;
01064         for (;;)
01065         {
01066           if ( point > end_point )
01067             goto EndContour;
01068 
01069           if ( ( point->flags & touch_flag ) != 0 )
01070             break;
01071 
01072           point++;
01073         }
01074 
01075         /* interpolate between last_touched and point */
01076         af_iup_interp( last_touched + 1, point - 1,
01077                        last_touched, point );
01078       }
01079 
01080     EndContour:
01081       /* special case: only one point was touched */
01082       if ( last_touched == first_touched )
01083       {
01084         af_iup_shift( first_point, end_point, first_touched );
01085       }
01086       else /* interpolate the last part */
01087       {
01088         if ( last_touched < end_point )
01089           af_iup_interp( last_touched + 1, end_point,
01090                          last_touched, first_touched );
01091 
01092         if ( first_touched > points )
01093           af_iup_interp( first_point, first_touched - 1,
01094                          last_touched, first_touched );
01095       }
01096 
01097     NextContour:
01098       ;
01099     }
01100 
01101     /* now save the interpolated values back to x/y */
01102     if ( dim == AF_DIMENSION_HORZ )
01103     {
01104       for ( point = points; point < point_limit; point++ )
01105         point->x = point->u;
01106     }
01107     else
01108     {
01109       for ( point = points; point < point_limit; point++ )
01110         point->y = point->u;
01111     }
01112   }
01113 
01114 
01115 #ifdef AF_USE_WARPER
01116 
01117   FT_LOCAL_DEF( void )
01118   af_glyph_hints_scale_dim( AF_GlyphHints  hints,
01119                             AF_Dimension   dim,
01120                             FT_Fixed       scale,
01121                             FT_Pos         delta )
01122   {
01123     AF_Point  points       = hints->points;
01124     AF_Point  points_limit = points + hints->num_points;
01125     AF_Point  point;
01126 
01127 
01128     if ( dim == AF_DIMENSION_HORZ )
01129     {
01130       for ( point = points; point < points_limit; point++ )
01131         point->x = FT_MulFix( point->fx, scale ) + delta;
01132     }
01133     else
01134     {
01135       for ( point = points; point < points_limit; point++ )
01136         point->y = FT_MulFix( point->fy, scale ) + delta;
01137     }
01138   }
01139 
01140 #endif /* AF_USE_WARPER */
01141 
01142 /* END */

Generated on Sun May 27 2012 04:33:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.