< prev index next >

src/java.desktop/share/native/libfreetype/src/autofit/afhints.c

Print this page


   1 /***************************************************************************/
   2 /*                                                                         */
   3 /*  afhints.c                                                              */
   4 /*                                                                         */
   5 /*    Auto-fitter hinting routines (body).                                 */
   6 /*                                                                         */
   7 /*  Copyright 2003-2018 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 "afhints.h"
  20 #include "aferrors.h"
  21 #include FT_INTERNAL_CALC_H
  22 #include FT_INTERNAL_DEBUG_H
  23 
  24 
  25   /*************************************************************************/
  26   /*                                                                       */
  27   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  28   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  29   /* messages during execution.                                            */
  30   /*                                                                       */
  31 #undef  FT_COMPONENT
  32 #define FT_COMPONENT  trace_afhints
  33 
  34 
  35   /* Get new segment for given axis. */
  36 
  37   FT_LOCAL_DEF( FT_Error )
  38   af_axis_hints_new_segment( AF_AxisHints  axis,
  39                              FT_Memory     memory,
  40                              AF_Segment   *asegment )
  41   {
  42     FT_Error    error   = FT_Err_Ok;
  43     AF_Segment  segment = NULL;
  44 
  45 
  46     if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
  47     {
  48       if ( !axis->segments )
  49       {
  50         axis->segments     = axis->embedded.segments;
  51         axis->max_segments = AF_SEGMENTS_EMBEDDED;
  52       }


 280       return -1;
 281 
 282     return (int)( segment - segments );
 283   }
 284 
 285 
 286   static int
 287   af_get_edge_index( AF_GlyphHints  hints,
 288                      int            segment_idx,
 289                      int            dimension )
 290   {
 291     AF_AxisHints  axis    = &hints->axis[dimension];
 292     AF_Edge       edges   = axis->edges;
 293     AF_Segment    segment = axis->segments + segment_idx;
 294 
 295 
 296     return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
 297   }
 298 
 299 













 300 #ifdef __cplusplus
 301   extern "C" {
 302 #endif
 303   void
 304   af_glyph_hints_dump_points( AF_GlyphHints  hints,
 305                               FT_Bool        to_stdout )
 306   {
 307     AF_Point   points  = hints->points;
 308     AF_Point   limit   = points + hints->num_points;
 309     AF_Point*  contour = hints->contours;
 310     AF_Point*  climit  = contour + hints->num_contours;
 311     AF_Point   point;
 312 
 313 
 314     AF_DUMP(( "Table of points:\n" ));
 315 
 316     if ( hints->num_points )
 317     {
 318       AF_DUMP(( "  index  hedge  hseg  vedge  vseg  flags "
 319              /* "  XXXXX  XXXXX XXXXX  XXXXX XXXXX  XXXXXX" */
 320                 "  xorg  yorg  xscale  yscale   xfit    yfit" ));
 321              /* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */


 322     }
 323     else
 324       AF_DUMP(( "  (none)\n" ));
 325 
 326     for ( point = points; point < limit; point++ )
 327     {
 328       int  point_idx     = AF_INDEX_NUM( point, points );
 329       int  segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
 330       int  segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
 331 
 332       char  buf1[16], buf2[16], buf3[16], buf4[16];

 333 
 334 
 335       /* insert extra newline at the beginning of a contour */
 336       if ( contour < climit && *contour == point )
 337       {
 338         AF_DUMP(( "\n" ));
 339         contour++;
 340       }
 341 
 342       AF_DUMP(( "  %5d  %5s %5s  %5s %5s  %s"
 343                 " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",

 344                 point_idx,
 345                 af_print_idx( buf1,
 346                               af_get_edge_index( hints, segment_idx_1, 1 ) ),
 347                 af_print_idx( buf2, segment_idx_1 ),
 348                 af_print_idx( buf3,
 349                               af_get_edge_index( hints, segment_idx_0, 0 ) ),
 350                 af_print_idx( buf4, segment_idx_0 ),
 351                 ( point->flags & AF_FLAG_NEAR )
 352                   ? " near "
 353                   : ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
 354                     ? " weak "
 355                     : "strong",
 356 
 357                 point->fx,
 358                 point->fy,
 359                 point->ox / 64.0,
 360                 point->oy / 64.0,
 361                 point->x / 64.0,
 362                 point->y / 64.0 ));













 363     }
 364     AF_DUMP(( "\n" ));
 365   }
 366 #ifdef __cplusplus
 367   }
 368 #endif
 369 
 370 
 371   static const char*
 372   af_edge_flags_to_string( FT_UInt  flags )
 373   {
 374     static char  temp[32];
 375     int          pos = 0;
 376 
 377 
 378     if ( flags & AF_EDGE_ROUND )
 379     {
 380       ft_memcpy( temp + pos, "round", 5 );
 381       pos += 5;
 382     }


 502   {
 503     AF_Dimension  dim;
 504     AF_AxisHints  axis;
 505     AF_Segment    seg;
 506 
 507 
 508     if ( !offset )
 509       return FT_THROW( Invalid_Argument );
 510 
 511     dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
 512 
 513     axis = &hints->axis[dim];
 514 
 515     if ( idx < 0 || idx >= axis->num_segments )
 516       return FT_THROW( Invalid_Argument );
 517 
 518     seg      = &axis->segments[idx];
 519     *offset  = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx
 520                                             : seg->first->fy;
 521     if ( seg->edge )
 522       *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
 523     else
 524       *is_blue = FALSE;
 525 
 526     if ( *is_blue )
 527       *blue_offset = seg->edge->blue_edge->org;
 528     else
 529       *blue_offset = 0;
 530 
 531     return FT_Err_Ok;
 532   }
 533 #ifdef __cplusplus
 534   }
 535 #endif
 536 
 537 
 538   /* Dump the array of linked edges. */
 539 
 540 #ifdef __cplusplus
 541   extern "C" {
 542 #endif


 881 
 882           out_x = point->fx - prev->fx;
 883           out_y = point->fy - prev->fy;
 884 
 885           if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
 886             prev->flags |= AF_FLAG_NEAR;
 887 
 888           point->prev = prev;
 889           prev->next  = point;
 890           prev        = point;
 891 
 892           if ( point == end )
 893           {
 894             if ( ++contour_index < outline->n_contours )
 895             {
 896               endpoint = outline->contours[contour_index];
 897               end      = points + endpoint;
 898               prev     = end;
 899             }
 900           }








 901         }
 902       }
 903 
 904       /* set up the contours array */
 905       {
 906         AF_Point*  contour       = hints->contours;
 907         AF_Point*  contour_limit = contour + hints->num_contours;
 908         short*     end           = outline->contours;
 909         short      idx           = 0;
 910 
 911 
 912         for ( ; contour < contour_limit; contour++, end++ )
 913         {
 914           contour[0] = points + idx;
 915           idx        = (short)( end[0] + 1 );
 916         }
 917       }
 918 
 919       {
 920         /*


1292 
1293         if ( dim == AF_DIMENSION_VERT )
1294         {
1295           u  = point->fy;
1296           ou = point->oy;
1297         }
1298         else
1299         {
1300           u  = point->fx;
1301           ou = point->ox;
1302         }
1303 
1304         fu = u;
1305 
1306         /* is the point before the first edge? */
1307         edge  = edges;
1308         delta = edge->fpos - u;
1309         if ( delta >= 0 )
1310         {
1311           u = edge->pos - ( edge->opos - ou );






1312           goto Store_Point;
1313         }
1314 
1315         /* is the point after the last edge? */
1316         edge  = edge_limit - 1;
1317         delta = u - edge->fpos;
1318         if ( delta >= 0 )
1319         {
1320           u = edge->pos + ( ou - edge->opos );






1321           goto Store_Point;
1322         }
1323 
1324         {
1325           FT_PtrDist  min, max, mid;
1326           FT_Pos      fpos;
1327 
1328 
1329           /* find enclosing edges */
1330           min = 0;
1331           max = edge_limit - edges;
1332 
1333 #if 1
1334           /* for a small number of edges, a linear search is better */
1335           if ( max <= 8 )
1336           {
1337             FT_PtrDist  nn;
1338 
1339 
1340             for ( nn = 0; nn < max; nn++ )


1347               goto Store_Point;
1348             }
1349             min = nn;
1350           }
1351           else
1352 #endif
1353           while ( min < max )
1354           {
1355             mid  = ( max + min ) >> 1;
1356             edge = edges + mid;
1357             fpos = edge->fpos;
1358 
1359             if ( u < fpos )
1360               max = mid;
1361             else if ( u > fpos )
1362               min = mid + 1;
1363             else
1364             {
1365               /* we are on the edge */
1366               u = edge->pos;






1367               goto Store_Point;
1368             }
1369           }
1370 
1371           /* point is not on an edge */
1372           {
1373             AF_Edge  before = edges + min - 1;
1374             AF_Edge  after  = edges + min + 0;
1375 





1376 
1377             /* assert( before && after && before != after ) */
1378             if ( before->scale == 0 )
1379               before->scale = FT_DivFix( after->pos - before->pos,
1380                                          after->fpos - before->fpos );
1381 
1382             u = before->pos + FT_MulFix( fu - before->fpos,
1383                                          before->scale );
1384           }
1385         }
1386 
1387       Store_Point:
1388         /* save the point position */
1389         if ( dim == AF_DIMENSION_HORZ )
1390           point->x = u;
1391         else
1392           point->y = u;
1393 
1394         point->flags |= touch_flag;
1395       }


   1 /****************************************************************************
   2  *
   3  * afhints.c
   4  *
   5  *   Auto-fitter hinting routines (body).
   6  *
   7  * Copyright (C) 2003-2019 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 "afhints.h"
  20 #include "aferrors.h"
  21 #include FT_INTERNAL_CALC_H
  22 #include FT_INTERNAL_DEBUG_H
  23 
  24 
  25   /**************************************************************************
  26    *
  27    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  28    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  29    * messages during execution.
  30    */
  31 #undef  FT_COMPONENT
  32 #define FT_COMPONENT  afhints
  33 
  34 
  35   /* Get new segment for given axis. */
  36 
  37   FT_LOCAL_DEF( FT_Error )
  38   af_axis_hints_new_segment( AF_AxisHints  axis,
  39                              FT_Memory     memory,
  40                              AF_Segment   *asegment )
  41   {
  42     FT_Error    error   = FT_Err_Ok;
  43     AF_Segment  segment = NULL;
  44 
  45 
  46     if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
  47     {
  48       if ( !axis->segments )
  49       {
  50         axis->segments     = axis->embedded.segments;
  51         axis->max_segments = AF_SEGMENTS_EMBEDDED;
  52       }


 280       return -1;
 281 
 282     return (int)( segment - segments );
 283   }
 284 
 285 
 286   static int
 287   af_get_edge_index( AF_GlyphHints  hints,
 288                      int            segment_idx,
 289                      int            dimension )
 290   {
 291     AF_AxisHints  axis    = &hints->axis[dimension];
 292     AF_Edge       edges   = axis->edges;
 293     AF_Segment    segment = axis->segments + segment_idx;
 294 
 295 
 296     return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
 297   }
 298 
 299 
 300   static int
 301   af_get_strong_edge_index( AF_GlyphHints  hints,
 302                             AF_Edge*       strong_edges,
 303                             int            dimension )
 304   {
 305     AF_AxisHints  axis  = &hints->axis[dimension];
 306     AF_Edge       edges = axis->edges;
 307 
 308 
 309     return AF_INDEX_NUM( strong_edges[dimension], edges );
 310   }
 311 
 312 
 313 #ifdef __cplusplus
 314   extern "C" {
 315 #endif
 316   void
 317   af_glyph_hints_dump_points( AF_GlyphHints  hints,
 318                               FT_Bool        to_stdout )
 319   {
 320     AF_Point   points  = hints->points;
 321     AF_Point   limit   = points + hints->num_points;
 322     AF_Point*  contour = hints->contours;
 323     AF_Point*  climit  = contour + hints->num_contours;
 324     AF_Point   point;
 325 
 326 
 327     AF_DUMP(( "Table of points:\n" ));
 328 
 329     if ( hints->num_points )
 330     {
 331       AF_DUMP(( "  index  hedge  hseg  vedge  vseg  flags "
 332              /* "  XXXXX  XXXXX XXXXX  XXXXX XXXXX  XXXXXX" */
 333                 "  xorg  yorg  xscale  yscale   xfit    yfit "
 334              /* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */
 335                 "  hbef  haft  vbef  vaft" ));
 336              /* " XXXXX XXXXX XXXXX XXXXX" */
 337     }
 338     else
 339       AF_DUMP(( "  (none)\n" ));
 340 
 341     for ( point = points; point < limit; point++ )
 342     {
 343       int  point_idx     = AF_INDEX_NUM( point, points );
 344       int  segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
 345       int  segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
 346 
 347       char  buf1[16], buf2[16], buf3[16], buf4[16];
 348       char  buf5[16], buf6[16], buf7[16], buf8[16];
 349 
 350 
 351       /* insert extra newline at the beginning of a contour */
 352       if ( contour < climit && *contour == point )
 353       {
 354         AF_DUMP(( "\n" ));
 355         contour++;
 356       }
 357 
 358       AF_DUMP(( "  %5d  %5s %5s  %5s %5s  %s"
 359                 " %5d %5d %7.2f %7.2f %7.2f %7.2f"
 360                 " %5s %5s %5s %5s\n",
 361                 point_idx,
 362                 af_print_idx( buf1,
 363                               af_get_edge_index( hints, segment_idx_1, 1 ) ),
 364                 af_print_idx( buf2, segment_idx_1 ),
 365                 af_print_idx( buf3,
 366                               af_get_edge_index( hints, segment_idx_0, 0 ) ),
 367                 af_print_idx( buf4, segment_idx_0 ),
 368                 ( point->flags & AF_FLAG_NEAR )
 369                   ? " near "
 370                   : ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
 371                     ? " weak "
 372                     : "strong",
 373 
 374                 point->fx,
 375                 point->fy,
 376                 point->ox / 64.0,
 377                 point->oy / 64.0,
 378                 point->x / 64.0,
 379                 point->y / 64.0,
 380 
 381                 af_print_idx( buf5, af_get_strong_edge_index( hints,
 382                                                               point->before,
 383                                                               1 ) ),
 384                 af_print_idx( buf6, af_get_strong_edge_index( hints,
 385                                                               point->after,
 386                                                               1 ) ),
 387                 af_print_idx( buf7, af_get_strong_edge_index( hints,
 388                                                               point->before,
 389                                                               0 ) ),
 390                 af_print_idx( buf8, af_get_strong_edge_index( hints,
 391                                                               point->after,
 392                                                               0 ) ) ));
 393     }
 394     AF_DUMP(( "\n" ));
 395   }
 396 #ifdef __cplusplus
 397   }
 398 #endif
 399 
 400 
 401   static const char*
 402   af_edge_flags_to_string( FT_UInt  flags )
 403   {
 404     static char  temp[32];
 405     int          pos = 0;
 406 
 407 
 408     if ( flags & AF_EDGE_ROUND )
 409     {
 410       ft_memcpy( temp + pos, "round", 5 );
 411       pos += 5;
 412     }


 532   {
 533     AF_Dimension  dim;
 534     AF_AxisHints  axis;
 535     AF_Segment    seg;
 536 
 537 
 538     if ( !offset )
 539       return FT_THROW( Invalid_Argument );
 540 
 541     dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
 542 
 543     axis = &hints->axis[dim];
 544 
 545     if ( idx < 0 || idx >= axis->num_segments )
 546       return FT_THROW( Invalid_Argument );
 547 
 548     seg      = &axis->segments[idx];
 549     *offset  = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx
 550                                             : seg->first->fy;
 551     if ( seg->edge )
 552       *is_blue = FT_BOOL( seg->edge->blue_edge );
 553     else
 554       *is_blue = FALSE;
 555 
 556     if ( *is_blue )
 557       *blue_offset = seg->edge->blue_edge->org;
 558     else
 559       *blue_offset = 0;
 560 
 561     return FT_Err_Ok;
 562   }
 563 #ifdef __cplusplus
 564   }
 565 #endif
 566 
 567 
 568   /* Dump the array of linked edges. */
 569 
 570 #ifdef __cplusplus
 571   extern "C" {
 572 #endif


 911 
 912           out_x = point->fx - prev->fx;
 913           out_y = point->fy - prev->fy;
 914 
 915           if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
 916             prev->flags |= AF_FLAG_NEAR;
 917 
 918           point->prev = prev;
 919           prev->next  = point;
 920           prev        = point;
 921 
 922           if ( point == end )
 923           {
 924             if ( ++contour_index < outline->n_contours )
 925             {
 926               endpoint = outline->contours[contour_index];
 927               end      = points + endpoint;
 928               prev     = end;
 929             }
 930           }
 931 
 932 #ifdef FT_DEBUG_AUTOFIT
 933           point->before[0] = NULL;
 934           point->before[1] = NULL;
 935           point->after[0]  = NULL;
 936           point->after[1]  = NULL;
 937 #endif
 938 
 939         }
 940       }
 941 
 942       /* set up the contours array */
 943       {
 944         AF_Point*  contour       = hints->contours;
 945         AF_Point*  contour_limit = contour + hints->num_contours;
 946         short*     end           = outline->contours;
 947         short      idx           = 0;
 948 
 949 
 950         for ( ; contour < contour_limit; contour++, end++ )
 951         {
 952           contour[0] = points + idx;
 953           idx        = (short)( end[0] + 1 );
 954         }
 955       }
 956 
 957       {
 958         /*


1330 
1331         if ( dim == AF_DIMENSION_VERT )
1332         {
1333           u  = point->fy;
1334           ou = point->oy;
1335         }
1336         else
1337         {
1338           u  = point->fx;
1339           ou = point->ox;
1340         }
1341 
1342         fu = u;
1343 
1344         /* is the point before the first edge? */
1345         edge  = edges;
1346         delta = edge->fpos - u;
1347         if ( delta >= 0 )
1348         {
1349           u = edge->pos - ( edge->opos - ou );
1350 
1351 #ifdef FT_DEBUG_AUTOFIT
1352           point->before[dim] = edge;
1353           point->after[dim]  = NULL;
1354 #endif
1355 
1356           goto Store_Point;
1357         }
1358 
1359         /* is the point after the last edge? */
1360         edge  = edge_limit - 1;
1361         delta = u - edge->fpos;
1362         if ( delta >= 0 )
1363         {
1364           u = edge->pos + ( ou - edge->opos );
1365 
1366 #ifdef FT_DEBUG_AUTOFIT
1367           point->before[dim] = NULL;
1368           point->after[dim]  = edge;
1369 #endif
1370 
1371           goto Store_Point;
1372         }
1373 
1374         {
1375           FT_PtrDist  min, max, mid;
1376           FT_Pos      fpos;
1377 
1378 
1379           /* find enclosing edges */
1380           min = 0;
1381           max = edge_limit - edges;
1382 
1383 #if 1
1384           /* for a small number of edges, a linear search is better */
1385           if ( max <= 8 )
1386           {
1387             FT_PtrDist  nn;
1388 
1389 
1390             for ( nn = 0; nn < max; nn++ )


1397               goto Store_Point;
1398             }
1399             min = nn;
1400           }
1401           else
1402 #endif
1403           while ( min < max )
1404           {
1405             mid  = ( max + min ) >> 1;
1406             edge = edges + mid;
1407             fpos = edge->fpos;
1408 
1409             if ( u < fpos )
1410               max = mid;
1411             else if ( u > fpos )
1412               min = mid + 1;
1413             else
1414             {
1415               /* we are on the edge */
1416               u = edge->pos;
1417 
1418 #ifdef FT_DEBUG_AUTOFIT
1419               point->before[dim] = NULL;
1420               point->after[dim]  = NULL;
1421 #endif
1422 
1423               goto Store_Point;
1424             }
1425           }
1426 
1427           /* point is not on an edge */
1428           {
1429             AF_Edge  before = edges + min - 1;
1430             AF_Edge  after  = edges + min + 0;
1431 
1432 
1433 #ifdef FT_DEBUG_AUTOFIT
1434             point->before[dim] = before;
1435             point->after[dim]  = after;
1436 #endif
1437 
1438             /* assert( before && after && before != after ) */
1439             if ( before->scale == 0 )
1440               before->scale = FT_DivFix( after->pos - before->pos,
1441                                          after->fpos - before->fpos );
1442 
1443             u = before->pos + FT_MulFix( fu - before->fpos,
1444                                          before->scale );
1445           }
1446         }
1447 
1448       Store_Point:
1449         /* save the point position */
1450         if ( dim == AF_DIMENSION_HORZ )
1451           point->x = u;
1452         else
1453           point->y = u;
1454 
1455         point->flags |= touch_flag;
1456       }


< prev index next >