Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenafhints.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
1.7.6.1
|