00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00108
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
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
00279
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
00305
00306
00307
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
00330
00331
00332
00333 FT_LOCAL_DEF( AF_Direction )
00334 af_direction_compute( FT_Pos dx,
00335 FT_Pos dy )
00336 {
00337 FT_Pos ll, ss;
00338 AF_Direction dir;
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
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
00381
00382 static void
00383 af_glyph_hints_compute_inflections( AF_GlyphHints hints )
00384 {
00385 AF_Point* contour = hints->contours;
00386 AF_Point* contour_limit = contour + hints->num_contours;
00387
00388
00389
00390 for ( ; contour < contour_limit; contour++ )
00391 {
00392 AF_Point point = contour[0];
00393 AF_Point first = point;
00394 AF_Point start = point;
00395 AF_Point end = point;
00396 AF_Point before;
00397 AF_Point after;
00398 FT_Pos in_x, in_y, out_x, out_y;
00399 AF_Angle orient_prev, orient_cur;
00400 FT_Int finished = 0;
00401
00402
00403
00404 first = point;
00405
00406 start = end = first;
00407 do
00408 {
00409 end = end->next;
00410 if ( end == first )
00411 goto Skip;
00412
00413 in_x = end->fx - start->fx;
00414 in_y = end->fy - start->fy;
00415
00416 } while ( in_x == 0 && in_y == 0 );
00417
00418
00419 before = start;
00420 do
00421 {
00422 do
00423 {
00424 start = before;
00425 before = before->prev;
00426 if ( before == first )
00427 goto Skip;
00428
00429 out_x = start->fx - before->fx;
00430 out_y = start->fy - before->fy;
00431
00432 } while ( out_x == 0 && out_y == 0 );
00433
00434 orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y );
00435
00436 } while ( orient_prev == 0 );
00437
00438 first = start;
00439
00440 in_x = out_x;
00441 in_y = out_y;
00442
00443
00444 do
00445 {
00446
00447 after = end;
00448 do
00449 {
00450 do
00451 {
00452 end = after;
00453 after = after->next;
00454 if ( after == first )
00455 finished = 1;
00456
00457 out_x = after->fx - end->fx;
00458 out_y = after->fy - end->fy;
00459
00460 } while ( out_x == 0 && out_y == 0 );
00461
00462 orient_cur = ft_corner_orientation( in_x, in_y, out_x, out_y );
00463
00464 } while ( orient_cur == 0 );
00465
00466 if ( ( orient_prev + orient_cur ) == 0 )
00467 {
00468
00469 do
00470 {
00471 start->flags |= AF_FLAG_INFLECTION;
00472 start = start->next;
00473
00474 } while ( start != end );
00475
00476 start->flags |= AF_FLAG_INFLECTION;
00477 }
00478
00479 start = end;
00480 end = after;
00481
00482 orient_prev = orient_cur;
00483 in_x = out_x;
00484 in_y = out_y;
00485
00486 } while ( !finished );
00487
00488 Skip:
00489 ;
00490 }
00491 }
00492
00493
00494 FT_LOCAL_DEF( void )
00495 af_glyph_hints_init( AF_GlyphHints hints,
00496 FT_Memory memory )
00497 {
00498 FT_ZERO( hints );
00499 hints->memory = memory;
00500 }
00501
00502
00503 FT_LOCAL_DEF( void )
00504 af_glyph_hints_done( AF_GlyphHints hints )
00505 {
00506 if ( hints && hints->memory )
00507 {
00508 FT_Memory memory = hints->memory;
00509 int dim;
00510
00511
00512
00513
00514
00515
00516 for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
00517 {
00518 AF_AxisHints axis = &hints->axis[dim];
00519
00520
00521 axis->num_segments = 0;
00522 axis->max_segments = 0;
00523 FT_FREE( axis->segments );
00524
00525 axis->num_edges = 0;
00526 axis->max_edges = 0;
00527 FT_FREE( axis->edges );
00528 }
00529
00530 FT_FREE( hints->contours );
00531 hints->max_contours = 0;
00532 hints->num_contours = 0;
00533
00534 FT_FREE( hints->points );
00535 hints->num_points = 0;
00536 hints->max_points = 0;
00537
00538 hints->memory = NULL;
00539 }
00540 }
00541
00542
00543 FT_LOCAL_DEF( void )
00544 af_glyph_hints_rescale( AF_GlyphHints hints,
00545 AF_ScriptMetrics metrics )
00546 {
00547 hints->metrics = metrics;
00548 hints->scaler_flags = metrics->scaler.flags;
00549 }
00550
00551
00552 FT_LOCAL_DEF( FT_Error )
00553 af_glyph_hints_reload( AF_GlyphHints hints,
00554 FT_Outline* outline,
00555 FT_Bool get_inflections )
00556 {
00557 FT_Error error = AF_Err_Ok;
00558 AF_Point points;
00559 FT_UInt old_max, new_max;
00560 FT_Fixed x_scale = hints->x_scale;
00561 FT_Fixed y_scale = hints->y_scale;
00562 FT_Pos x_delta = hints->x_delta;
00563 FT_Pos y_delta = hints->y_delta;
00564 FT_Memory memory = hints->memory;
00565
00566
00567 hints->num_points = 0;
00568 hints->num_contours = 0;
00569
00570 hints->axis[0].num_segments = 0;
00571 hints->axis[0].num_edges = 0;
00572 hints->axis[1].num_segments = 0;
00573 hints->axis[1].num_edges = 0;
00574
00575
00576 new_max = (FT_UInt)outline->n_contours;
00577 old_max = hints->max_contours;
00578 if ( new_max > old_max )
00579 {
00580 new_max = ( new_max + 3 ) & ~3;
00581
00582 if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
00583 goto Exit;
00584
00585 hints->max_contours = new_max;
00586 }
00587
00588
00589
00590
00591
00592
00593 new_max = (FT_UInt)( outline->n_points + 2 );
00594 old_max = hints->max_points;
00595 if ( new_max > old_max )
00596 {
00597 new_max = ( new_max + 2 + 7 ) & ~7;
00598
00599 if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
00600 goto Exit;
00601
00602 hints->max_points = new_max;
00603 }
00604
00605 hints->num_points = outline->n_points;
00606 hints->num_contours = outline->n_contours;
00607
00608
00609
00610
00611
00612 hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
00613 hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
00614
00615 if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
00616 {
00617 hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
00618 hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
00619 }
00620
00621 hints->x_scale = x_scale;
00622 hints->y_scale = y_scale;
00623 hints->x_delta = x_delta;
00624 hints->y_delta = y_delta;
00625
00626 hints->xmin_delta = 0;
00627 hints->xmax_delta = 0;
00628
00629 points = hints->points;
00630 if ( hints->num_points == 0 )
00631 goto Exit;
00632
00633 {
00634 AF_Point point;
00635 AF_Point point_limit = points + hints->num_points;
00636
00637
00638
00639 {
00640 FT_Vector* vec = outline->points;
00641 char* tag = outline->tags;
00642 AF_Point first = points;
00643 AF_Point end = points + outline->contours[0];
00644 AF_Point prev = end;
00645 FT_Int contour_index = 0;
00646
00647
00648 FT_UNUSED( first );
00649 for ( point = points; point < point_limit; point++, vec++, tag++ )
00650 {
00651 point->fx = (FT_Short)vec->x;
00652 point->fy = (FT_Short)vec->y;
00653 point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
00654 point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
00655
00656 switch ( FT_CURVE_TAG( *tag ) )
00657 {
00658 case FT_CURVE_TAG_CONIC:
00659 point->flags = AF_FLAG_CONIC;
00660 break;
00661 case FT_CURVE_TAG_CUBIC:
00662 point->flags = AF_FLAG_CUBIC;
00663 break;
00664 default:
00665 point->flags = 0;
00666 }
00667
00668 point->prev = prev;
00669 prev->next = point;
00670 prev = point;
00671
00672 if ( point == end )
00673 {
00674 if ( ++contour_index < outline->n_contours )
00675 {
00676 first = point + 1;
00677 end = points + outline->contours[contour_index];
00678 prev = end;
00679 }
00680 }
00681 }
00682 }
00683
00684
00685 {
00686 AF_Point* contour = hints->contours;
00687 AF_Point* contour_limit = contour + hints->num_contours;
00688 short* end = outline->contours;
00689 short idx = 0;
00690
00691
00692 for ( ; contour < contour_limit; contour++, end++ )
00693 {
00694 contour[0] = points + idx;
00695 idx = (short)( end[0] + 1 );
00696 }
00697 }
00698
00699
00700 {
00701 AF_Point first = points;
00702 AF_Point prev = NULL;
00703 FT_Pos in_x = 0;
00704 FT_Pos in_y = 0;
00705 AF_Direction in_dir = AF_DIR_NONE;
00706
00707
00708 for ( point = points; point < point_limit; point++ )
00709 {
00710 AF_Point next;
00711 FT_Pos out_x, out_y;
00712
00713
00714 if ( point == first )
00715 {
00716 prev = first->prev;
00717 in_x = first->fx - prev->fx;
00718 in_y = first->fy - prev->fy;
00719 in_dir = af_direction_compute( in_x, in_y );
00720 first = prev + 1;
00721 }
00722
00723 point->in_dir = (FT_Char)in_dir;
00724
00725 next = point->next;
00726 out_x = next->fx - point->fx;
00727 out_y = next->fy - point->fy;
00728
00729 in_dir = af_direction_compute( out_x, out_y );
00730 point->out_dir = (FT_Char)in_dir;
00731
00732 if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
00733 {
00734 Is_Weak_Point:
00735 point->flags |= AF_FLAG_WEAK_INTERPOLATION;
00736 }
00737 else if ( point->out_dir == point->in_dir )
00738 {
00739 if ( point->out_dir != AF_DIR_NONE )
00740 goto Is_Weak_Point;
00741
00742 if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
00743 goto Is_Weak_Point;
00744 }
00745 else if ( point->in_dir == -point->out_dir )
00746 goto Is_Weak_Point;
00747
00748 in_x = out_x;
00749 in_y = out_y;
00750 prev = point;
00751 }
00752 }
00753 }
00754
00755
00756
00757 if ( 0 && get_inflections )
00758 af_glyph_hints_compute_inflections( hints );
00759
00760 Exit:
00761 return error;
00762 }
00763
00764
00765 FT_LOCAL_DEF( void )
00766 af_glyph_hints_save( AF_GlyphHints hints,
00767 FT_Outline* outline )
00768 {
00769 AF_Point point = hints->points;
00770 AF_Point limit = point + hints->num_points;
00771 FT_Vector* vec = outline->points;
00772 char* tag = outline->tags;
00773
00774
00775 for ( ; point < limit; point++, vec++, tag++ )
00776 {
00777 vec->x = point->x;
00778 vec->y = point->y;
00779
00780 if ( point->flags & AF_FLAG_CONIC )
00781 tag[0] = FT_CURVE_TAG_CONIC;
00782 else if ( point->flags & AF_FLAG_CUBIC )
00783 tag[0] = FT_CURVE_TAG_CUBIC;
00784 else
00785 tag[0] = FT_CURVE_TAG_ON;
00786 }
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 FT_LOCAL_DEF( void )
00798 af_glyph_hints_align_edge_points( AF_GlyphHints hints,
00799 AF_Dimension dim )
00800 {
00801 AF_AxisHints axis = & hints->axis[dim];
00802 AF_Segment segments = axis->segments;
00803 AF_Segment segment_limit = segments + axis->num_segments;
00804 AF_Segment seg;
00805
00806
00807 if ( dim == AF_DIMENSION_HORZ )
00808 {
00809 for ( seg = segments; seg < segment_limit; seg++ )
00810 {
00811 AF_Edge edge = seg->edge;
00812 AF_Point point, first, last;
00813
00814
00815 if ( edge == NULL )
00816 continue;
00817
00818 first = seg->first;
00819 last = seg->last;
00820 point = first;
00821 for (;;)
00822 {
00823 point->x = edge->pos;
00824 point->flags |= AF_FLAG_TOUCH_X;
00825
00826 if ( point == last )
00827 break;
00828
00829 point = point->next;
00830
00831 }
00832 }
00833 }
00834 else
00835 {
00836 for ( seg = segments; seg < segment_limit; seg++ )
00837 {
00838 AF_Edge edge = seg->edge;
00839 AF_Point point, first, last;
00840
00841
00842 if ( edge == NULL )
00843 continue;
00844
00845 first = seg->first;
00846 last = seg->last;
00847 point = first;
00848 for (;;)
00849 {
00850 point->y = edge->pos;
00851 point->flags |= AF_FLAG_TOUCH_Y;
00852
00853 if ( point == last )
00854 break;
00855
00856 point = point->next;
00857 }
00858 }
00859 }
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 FT_LOCAL_DEF( void )
00874 af_glyph_hints_align_strong_points( AF_GlyphHints hints,
00875 AF_Dimension dim )
00876 {
00877 AF_Point points = hints->points;
00878 AF_Point point_limit = points + hints->num_points;
00879 AF_AxisHints axis = &hints->axis[dim];
00880 AF_Edge edges = axis->edges;
00881 AF_Edge edge_limit = edges + axis->num_edges;
00882 AF_Flags touch_flag;
00883
00884
00885 if ( dim == AF_DIMENSION_HORZ )
00886 touch_flag = AF_FLAG_TOUCH_X;
00887 else
00888 touch_flag = AF_FLAG_TOUCH_Y;
00889
00890 if ( edges < edge_limit )
00891 {
00892 AF_Point point;
00893 AF_Edge edge;
00894
00895
00896 for ( point = points; point < point_limit; point++ )
00897 {
00898 FT_Pos u, ou, fu;
00899 FT_Pos delta;
00900
00901
00902 if ( point->flags & touch_flag )
00903 continue;
00904
00905
00906
00907
00908 if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
00909 !( point->flags & AF_FLAG_INFLECTION ) )
00910 continue;
00911
00912 if ( dim == AF_DIMENSION_VERT )
00913 {
00914 u = point->fy;
00915 ou = point->oy;
00916 }
00917 else
00918 {
00919 u = point->fx;
00920 ou = point->ox;
00921 }
00922
00923 fu = u;
00924
00925
00926 edge = edges;
00927 delta = edge->fpos - u;
00928 if ( delta >= 0 )
00929 {
00930 u = edge->pos - ( edge->opos - ou );
00931 goto Store_Point;
00932 }
00933
00934
00935 edge = edge_limit - 1;
00936 delta = u - edge->fpos;
00937 if ( delta >= 0 )
00938 {
00939 u = edge->pos + ( ou - edge->opos );
00940 goto Store_Point;
00941 }
00942
00943 {
00944 FT_PtrDist min, max, mid;
00945 FT_Pos fpos;
00946
00947
00948
00949 min = 0;
00950 max = edge_limit - edges;
00951
00952 #if 1
00953
00954 if ( max <= 8 )
00955 {
00956 FT_PtrDist nn;
00957
00958 for ( nn = 0; nn < max; nn++ )
00959 if ( edges[nn].fpos >= u )
00960 break;
00961
00962 if ( edges[nn].fpos == u )
00963 {
00964 u = edges[nn].pos;
00965 goto Store_Point;
00966 }
00967 min = nn;
00968 }
00969 else
00970 #endif
00971 while ( min < max )
00972 {
00973 mid = ( max + min ) >> 1;
00974 edge = edges + mid;
00975 fpos = edge->fpos;
00976
00977 if ( u < fpos )
00978 max = mid;
00979 else if ( u > fpos )
00980 min = mid + 1;
00981 else
00982 {
00983
00984 u = edge->pos;
00985 goto Store_Point;
00986 }
00987 }
00988
00989 {
00990 AF_Edge before = edges + min - 1;
00991 AF_Edge after = edges + min + 0;
00992
00993
00994
00995 if ( before->scale == 0 )
00996 before->scale = FT_DivFix( after->pos - before->pos,
00997 after->fpos - before->fpos );
00998
00999 u = before->pos + FT_MulFix( fu - before->fpos,
01000 before->scale );
01001 }
01002 }
01003
01004 Store_Point:
01005
01006 if ( dim == AF_DIMENSION_HORZ )
01007 point->x = u;
01008 else
01009 point->y = u;
01010
01011 point->flags |= touch_flag;
01012 }
01013 }
01014 }
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 static void
01025 af_iup_shift( AF_Point p1,
01026 AF_Point p2,
01027 AF_Point ref )
01028 {
01029 AF_Point p;
01030 FT_Pos delta = ref->u - ref->v;
01031
01032 if ( delta == 0 )
01033 return;
01034
01035 for ( p = p1; p < ref; p++ )
01036 p->u = p->v + delta;
01037
01038 for ( p = ref + 1; p <= p2; p++ )
01039 p->u = p->v + delta;
01040 }
01041
01042
01043 static void
01044 af_iup_interp( AF_Point p1,
01045 AF_Point p2,
01046 AF_Point ref1,
01047 AF_Point ref2 )
01048 {
01049 AF_Point p;
01050 FT_Pos u;
01051 FT_Pos v1 = ref1->v;
01052 FT_Pos v2 = ref2->v;
01053 FT_Pos d1 = ref1->u - v1;
01054 FT_Pos d2 = ref2->u - v2;
01055
01056
01057 if ( p1 > p2 )
01058 return;
01059
01060 if ( v1 == v2 )
01061 {
01062 for ( p = p1; p <= p2; p++ )
01063 {
01064 u = p->v;
01065
01066 if ( u <= v1 )
01067 u += d1;
01068 else
01069 u += d2;
01070
01071 p->u = u;
01072 }
01073 return;
01074 }
01075
01076 if ( v1 < v2 )
01077 {
01078 for ( p = p1; p <= p2; p++ )
01079 {
01080 u = p->v;
01081
01082 if ( u <= v1 )
01083 u += d1;
01084 else if ( u >= v2 )
01085 u += d2;
01086 else
01087 u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
01088
01089 p->u = u;
01090 }
01091 }
01092 else
01093 {
01094 for ( p = p1; p <= p2; p++ )
01095 {
01096 u = p->v;
01097
01098 if ( u <= v2 )
01099 u += d2;
01100 else if ( u >= v1 )
01101 u += d1;
01102 else
01103 u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
01104
01105 p->u = u;
01106 }
01107 }
01108 }
01109
01110
01111 FT_LOCAL_DEF( void )
01112 af_glyph_hints_align_weak_points( AF_GlyphHints hints,
01113 AF_Dimension dim )
01114 {
01115 AF_Point points = hints->points;
01116 AF_Point point_limit = points + hints->num_points;
01117 AF_Point* contour = hints->contours;
01118 AF_Point* contour_limit = contour + hints->num_contours;
01119 AF_Flags touch_flag;
01120 AF_Point point;
01121 AF_Point end_point;
01122 AF_Point first_point;
01123
01124
01125
01126
01127 if ( dim == AF_DIMENSION_HORZ )
01128 {
01129 touch_flag = AF_FLAG_TOUCH_X;
01130
01131 for ( point = points; point < point_limit; point++ )
01132 {
01133 point->u = point->x;
01134 point->v = point->ox;
01135 }
01136 }
01137 else
01138 {
01139 touch_flag = AF_FLAG_TOUCH_Y;
01140
01141 for ( point = points; point < point_limit; point++ )
01142 {
01143 point->u = point->y;
01144 point->v = point->oy;
01145 }
01146 }
01147
01148 point = points;
01149
01150 for ( ; contour < contour_limit; contour++ )
01151 {
01152 AF_Point first_touched, last_touched;
01153
01154
01155 point = *contour;
01156 end_point = point->prev;
01157 first_point = point;
01158
01159
01160 for (;;)
01161 {
01162 if ( point > end_point )
01163 goto NextContour;
01164
01165 if ( point->flags & touch_flag )
01166 break;
01167
01168 point++;
01169 }
01170
01171 first_touched = point;
01172 last_touched = point;
01173
01174 for (;;)
01175 {
01176 FT_ASSERT( point <= end_point &&
01177 ( point->flags & touch_flag ) != 0 );
01178
01179
01180 while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
01181 point++;
01182
01183 last_touched = point;
01184
01185
01186 point ++;
01187 for (;;)
01188 {
01189 if ( point > end_point )
01190 goto EndContour;
01191
01192 if ( ( point->flags & touch_flag ) != 0 )
01193 break;
01194
01195 point++;
01196 }
01197
01198
01199 af_iup_interp( last_touched + 1, point - 1,
01200 last_touched, point );
01201 }
01202
01203 EndContour:
01204
01205 if ( last_touched == first_touched )
01206 {
01207 af_iup_shift( first_point, end_point, first_touched );
01208 }
01209 else
01210 {
01211 if ( last_touched < end_point )
01212 af_iup_interp( last_touched + 1, end_point,
01213 last_touched, first_touched );
01214
01215 if ( first_touched > points )
01216 af_iup_interp( first_point, first_touched - 1,
01217 last_touched, first_touched );
01218 }
01219
01220 NextContour:
01221 ;
01222 }
01223
01224
01225 if ( dim == AF_DIMENSION_HORZ )
01226 {
01227 for ( point = points; point < point_limit; point++ )
01228 point->x = point->u;
01229 }
01230 else
01231 {
01232 for ( point = points; point < point_limit; point++ )
01233 point->y = point->u;
01234 }
01235 }
01236
01237
01238 #ifdef AF_USE_WARPER
01239
01240 FT_LOCAL_DEF( void )
01241 af_glyph_hints_scale_dim( AF_GlyphHints hints,
01242 AF_Dimension dim,
01243 FT_Fixed scale,
01244 FT_Pos delta )
01245 {
01246 AF_Point points = hints->points;
01247 AF_Point points_limit = points + hints->num_points;
01248 AF_Point point;
01249
01250
01251 if ( dim == AF_DIMENSION_HORZ )
01252 {
01253 for ( point = points; point < points_limit; point++ )
01254 point->x = FT_MulFix( point->fx, scale ) + delta;
01255 }
01256 else
01257 {
01258 for ( point = points; point < points_limit; point++ )
01259 point->y = FT_MulFix( point->fy, scale ) + delta;
01260 }
01261 }
01262
01263 #endif
01264
01265