mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / thirdparty / freetype-2.3.12 / src / autofit / afhints.c
blobfe38fba99548f5c837731dc5787160e66b258025
1 /***************************************************************************/
2 /* */
3 /* afhints.c */
4 /* */
5 /* Auto-fitter hinting routines (body). */
6 /* */
7 /* Copyright 2003, 2004, 2005, 2006, 2007, 2009 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 /***************************************************************************/
19 #include "afhints.h"
20 #include "aferrors.h"
21 #include FT_INTERNAL_CALC_H
24 FT_LOCAL_DEF( FT_Error )
25 af_axis_hints_new_segment( AF_AxisHints axis,
26 FT_Memory memory,
27 AF_Segment *asegment )
29 FT_Error error = AF_Err_Ok;
30 AF_Segment segment = NULL;
33 if ( axis->num_segments >= axis->max_segments )
35 FT_Int old_max = axis->max_segments;
36 FT_Int new_max = old_max;
37 FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );
40 if ( old_max >= big_max )
42 error = AF_Err_Out_Of_Memory;
43 goto Exit;
46 new_max += ( new_max >> 2 ) + 4;
47 if ( new_max < old_max || new_max > big_max )
48 new_max = big_max;
50 if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
51 goto Exit;
53 axis->max_segments = new_max;
56 segment = axis->segments + axis->num_segments++;
58 Exit:
59 *asegment = segment;
60 return error;
64 FT_LOCAL( FT_Error )
65 af_axis_hints_new_edge( AF_AxisHints axis,
66 FT_Int fpos,
67 AF_Direction dir,
68 FT_Memory memory,
69 AF_Edge *aedge )
71 FT_Error error = AF_Err_Ok;
72 AF_Edge edge = NULL;
73 AF_Edge edges;
76 if ( axis->num_edges >= axis->max_edges )
78 FT_Int old_max = axis->max_edges;
79 FT_Int new_max = old_max;
80 FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
83 if ( old_max >= big_max )
85 error = AF_Err_Out_Of_Memory;
86 goto Exit;
89 new_max += ( new_max >> 2 ) + 4;
90 if ( new_max < old_max || new_max > big_max )
91 new_max = big_max;
93 if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
94 goto Exit;
96 axis->max_edges = new_max;
99 edges = axis->edges;
100 edge = edges + axis->num_edges;
102 while ( edge > edges )
104 if ( edge[-1].fpos < fpos )
105 break;
107 /* we want the edge with same position and minor direction */
108 /* to appear before those in the major one in the list */
109 if ( edge[-1].fpos == fpos && dir == axis->major_dir )
110 break;
112 edge[0] = edge[-1];
113 edge--;
116 axis->num_edges++;
118 FT_ZERO( edge );
119 edge->fpos = (FT_Short)fpos;
120 edge->dir = (FT_Char)dir;
122 Exit:
123 *aedge = edge;
124 return error;
128 #ifdef AF_DEBUG
130 #include FT_CONFIG_STANDARD_LIBRARY_H
132 static const char*
133 af_dir_str( AF_Direction dir )
135 const char* result;
138 switch ( dir )
140 case AF_DIR_UP:
141 result = "up";
142 break;
143 case AF_DIR_DOWN:
144 result = "down";
145 break;
146 case AF_DIR_LEFT:
147 result = "left";
148 break;
149 case AF_DIR_RIGHT:
150 result = "right";
151 break;
152 default:
153 result = "none";
156 return result;
160 #define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
163 void
164 af_glyph_hints_dump_points( AF_GlyphHints hints )
166 AF_Point points = hints->points;
167 AF_Point limit = points + hints->num_points;
168 AF_Point point;
171 printf( "Table of points:\n" );
172 printf( " [ index | xorg | yorg | xscale | yscale "
173 "| xfit | yfit | flags ]\n" );
175 for ( point = points; point < limit; point++ )
177 printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f "
178 "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
179 point - points,
180 point->fx,
181 point->fy,
182 point->ox/64.0,
183 point->oy/64.0,
184 point->x/64.0,
185 point->y/64.0,
186 ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
187 ( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ',
188 ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ',
189 ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ',
190 ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ',
191 ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' ');
193 printf( "\n" );
197 static const char*
198 af_edge_flags_to_string( AF_Edge_Flags flags )
200 static char temp[32];
201 int pos = 0;
204 if ( flags & AF_EDGE_ROUND )
206 ft_memcpy( temp + pos, "round", 5 );
207 pos += 5;
209 if ( flags & AF_EDGE_SERIF )
211 if ( pos > 0 )
212 temp[pos++] = ' ';
213 ft_memcpy( temp + pos, "serif", 5 );
214 pos += 5;
216 if ( pos == 0 )
217 return "normal";
219 temp[pos] = 0;
221 return temp;
225 /* A function to dump the array of linked segments. */
226 void
227 af_glyph_hints_dump_segments( AF_GlyphHints hints )
229 FT_Int dimension;
232 for ( dimension = 1; dimension >= 0; dimension-- )
234 AF_AxisHints axis = &hints->axis[dimension];
235 AF_Segment segments = axis->segments;
236 AF_Segment limit = segments + axis->num_segments;
237 AF_Segment seg;
240 printf ( "Table of %s segments:\n",
241 dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
242 printf ( " [ index | pos | dir | link | serif |"
243 " height | extra | flags ]\n" );
245 for ( seg = segments; seg < limit; seg++ )
247 printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
248 seg - segments,
249 dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
250 : (int)seg->first->oy / 64.0,
251 af_dir_str( (AF_Direction)seg->dir ),
252 AF_INDEX_NUM( seg->link, segments ),
253 AF_INDEX_NUM( seg->serif, segments ),
254 seg->height,
255 seg->height - ( seg->max_coord - seg->min_coord ),
256 af_edge_flags_to_string( seg->flags ) );
258 printf( "\n" );
263 void
264 af_glyph_hints_dump_edges( AF_GlyphHints hints )
266 FT_Int dimension;
269 for ( dimension = 1; dimension >= 0; dimension-- )
271 AF_AxisHints axis = &hints->axis[dimension];
272 AF_Edge edges = axis->edges;
273 AF_Edge limit = edges + axis->num_edges;
274 AF_Edge edge;
278 * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
279 * since they have constant a X coordinate.
281 printf ( "Table of %s edges:\n",
282 dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
283 printf ( " [ index | pos | dir | link |"
284 " serif | blue | opos | pos | flags ]\n" );
286 for ( edge = edges; edge < limit; edge++ )
288 printf ( " [ %5d | %5.2g | %5s | %4d |"
289 " %5d | %c | %5.2f | %5.2f | %s ]\n",
290 edge - edges,
291 (int)edge->opos / 64.0,
292 af_dir_str( (AF_Direction)edge->dir ),
293 AF_INDEX_NUM( edge->link, edges ),
294 AF_INDEX_NUM( edge->serif, edges ),
295 edge->blue_edge ? 'y' : 'n',
296 edge->opos / 64.0,
297 edge->pos / 64.0,
298 af_edge_flags_to_string( edge->flags ) );
300 printf( "\n" );
304 #else /* !AF_DEBUG */
306 /* these empty stubs are only used to link the `ftgrid' test program */
307 /* when debugging is disabled */
309 void
310 af_glyph_hints_dump_points( AF_GlyphHints hints )
312 FT_UNUSED( hints );
316 void
317 af_glyph_hints_dump_segments( AF_GlyphHints hints )
319 FT_UNUSED( hints );
323 void
324 af_glyph_hints_dump_edges( AF_GlyphHints hints )
326 FT_UNUSED( hints );
329 #endif /* !AF_DEBUG */
332 /* compute the direction value of a given vector */
333 FT_LOCAL_DEF( AF_Direction )
334 af_direction_compute( FT_Pos dx,
335 FT_Pos dy )
337 FT_Pos ll, ss; /* long and short arm lengths */
338 AF_Direction dir; /* candidate direction */
341 if ( dy >= dx )
343 if ( dy >= -dx )
345 dir = AF_DIR_UP;
346 ll = dy;
347 ss = dx;
349 else
351 dir = AF_DIR_LEFT;
352 ll = -dx;
353 ss = dy;
356 else /* dy < dx */
358 if ( dy >= -dx )
360 dir = AF_DIR_RIGHT;
361 ll = dx;
362 ss = dy;
364 else
366 dir = AF_DIR_DOWN;
367 ll = dy;
368 ss = dx;
372 ss *= 14;
373 if ( FT_ABS( ll ) <= FT_ABS( ss ) )
374 dir = AF_DIR_NONE;
376 return dir;
380 /* compute all inflex points in a given glyph */
382 static void
383 af_glyph_hints_compute_inflections( AF_GlyphHints hints )
385 AF_Point* contour = hints->contours;
386 AF_Point* contour_limit = contour + hints->num_contours;
389 /* do each contour separately */
390 for ( ; contour < contour_limit; contour++ )
392 AF_Point point = contour[0];
393 AF_Point first = point;
394 AF_Point start = point;
395 AF_Point end = point;
396 AF_Point before;
397 AF_Point after;
398 FT_Pos in_x, in_y, out_x, out_y;
399 AF_Angle orient_prev, orient_cur;
400 FT_Int finished = 0;
403 /* compute first segment in contour */
404 first = point;
406 start = end = first;
409 end = end->next;
410 if ( end == first )
411 goto Skip;
413 in_x = end->fx - start->fx;
414 in_y = end->fy - start->fy;
416 } while ( in_x == 0 && in_y == 0 );
418 /* extend the segment start whenever possible */
419 before = start;
424 start = before;
425 before = before->prev;
426 if ( before == first )
427 goto Skip;
429 out_x = start->fx - before->fx;
430 out_y = start->fy - before->fy;
432 } while ( out_x == 0 && out_y == 0 );
434 orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y );
436 } while ( orient_prev == 0 );
438 first = start;
440 in_x = out_x;
441 in_y = out_y;
443 /* now process all segments in the contour */
446 /* first, extend current segment's end whenever possible */
447 after = end;
452 end = after;
453 after = after->next;
454 if ( after == first )
455 finished = 1;
457 out_x = after->fx - end->fx;
458 out_y = after->fy - end->fy;
460 } while ( out_x == 0 && out_y == 0 );
462 orient_cur = ft_corner_orientation( in_x, in_y, out_x, out_y );
464 } while ( orient_cur == 0 );
466 if ( ( orient_prev + orient_cur ) == 0 )
468 /* we have an inflection point here */
471 start->flags |= AF_FLAG_INFLECTION;
472 start = start->next;
474 } while ( start != end );
476 start->flags |= AF_FLAG_INFLECTION;
479 start = end;
480 end = after;
482 orient_prev = orient_cur;
483 in_x = out_x;
484 in_y = out_y;
486 } while ( !finished );
488 Skip:
494 FT_LOCAL_DEF( void )
495 af_glyph_hints_init( AF_GlyphHints hints,
496 FT_Memory memory )
498 FT_ZERO( hints );
499 hints->memory = memory;
503 FT_LOCAL_DEF( void )
504 af_glyph_hints_done( AF_GlyphHints hints )
506 if ( hints && hints->memory )
508 FT_Memory memory = hints->memory;
509 int dim;
513 * note that we don't need to free the segment and edge
514 * buffers, since they are really within the hints->points array
516 for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
518 AF_AxisHints axis = &hints->axis[dim];
521 axis->num_segments = 0;
522 axis->max_segments = 0;
523 FT_FREE( axis->segments );
525 axis->num_edges = 0;
526 axis->max_edges = 0;
527 FT_FREE( axis->edges );
530 FT_FREE( hints->contours );
531 hints->max_contours = 0;
532 hints->num_contours = 0;
534 FT_FREE( hints->points );
535 hints->num_points = 0;
536 hints->max_points = 0;
538 hints->memory = NULL;
543 FT_LOCAL_DEF( void )
544 af_glyph_hints_rescale( AF_GlyphHints hints,
545 AF_ScriptMetrics metrics )
547 hints->metrics = metrics;
548 hints->scaler_flags = metrics->scaler.flags;
552 FT_LOCAL_DEF( FT_Error )
553 af_glyph_hints_reload( AF_GlyphHints hints,
554 FT_Outline* outline,
555 FT_Bool get_inflections )
557 FT_Error error = AF_Err_Ok;
558 AF_Point points;
559 FT_UInt old_max, new_max;
560 FT_Fixed x_scale = hints->x_scale;
561 FT_Fixed y_scale = hints->y_scale;
562 FT_Pos x_delta = hints->x_delta;
563 FT_Pos y_delta = hints->y_delta;
564 FT_Memory memory = hints->memory;
567 hints->num_points = 0;
568 hints->num_contours = 0;
570 hints->axis[0].num_segments = 0;
571 hints->axis[0].num_edges = 0;
572 hints->axis[1].num_segments = 0;
573 hints->axis[1].num_edges = 0;
575 /* first of all, reallocate the contours array when necessary */
576 new_max = (FT_UInt)outline->n_contours;
577 old_max = hints->max_contours;
578 if ( new_max > old_max )
580 new_max = ( new_max + 3 ) & ~3;
582 if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
583 goto Exit;
585 hints->max_contours = new_max;
589 * then reallocate the points arrays if necessary --
590 * note that we reserve two additional point positions, used to
591 * hint metrics appropriately
593 new_max = (FT_UInt)( outline->n_points + 2 );
594 old_max = hints->max_points;
595 if ( new_max > old_max )
597 new_max = ( new_max + 2 + 7 ) & ~7;
599 if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
600 goto Exit;
602 hints->max_points = new_max;
605 hints->num_points = outline->n_points;
606 hints->num_contours = outline->n_contours;
608 /* We can't rely on the value of `FT_Outline.flags' to know the fill */
609 /* direction used for a glyph, given that some fonts are broken (e.g., */
610 /* the Arphic ones). We thus recompute it each time we need to. */
611 /* */
612 hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
613 hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
615 if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
617 hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
618 hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
621 hints->x_scale = x_scale;
622 hints->y_scale = y_scale;
623 hints->x_delta = x_delta;
624 hints->y_delta = y_delta;
626 hints->xmin_delta = 0;
627 hints->xmax_delta = 0;
629 points = hints->points;
630 if ( hints->num_points == 0 )
631 goto Exit;
634 AF_Point point;
635 AF_Point point_limit = points + hints->num_points;
638 /* compute coordinates & Bezier flags, next and prev */
640 FT_Vector* vec = outline->points;
641 char* tag = outline->tags;
642 AF_Point first = points;
643 AF_Point end = points + outline->contours[0];
644 AF_Point prev = end;
645 FT_Int contour_index = 0;
648 FT_UNUSED( first );
649 for ( point = points; point < point_limit; point++, vec++, tag++ )
651 point->fx = (FT_Short)vec->x;
652 point->fy = (FT_Short)vec->y;
653 point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
654 point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
656 switch ( FT_CURVE_TAG( *tag ) )
658 case FT_CURVE_TAG_CONIC:
659 point->flags = AF_FLAG_CONIC;
660 break;
661 case FT_CURVE_TAG_CUBIC:
662 point->flags = AF_FLAG_CUBIC;
663 break;
664 default:
665 point->flags = 0;
668 point->prev = prev;
669 prev->next = point;
670 prev = point;
672 if ( point == end )
674 if ( ++contour_index < outline->n_contours )
676 first = point + 1;
677 end = points + outline->contours[contour_index];
678 prev = end;
684 /* set-up the contours array */
686 AF_Point* contour = hints->contours;
687 AF_Point* contour_limit = contour + hints->num_contours;
688 short* end = outline->contours;
689 short idx = 0;
692 for ( ; contour < contour_limit; contour++, end++ )
694 contour[0] = points + idx;
695 idx = (short)( end[0] + 1 );
699 /* compute directions of in & out vectors */
701 AF_Point first = points;
702 AF_Point prev = NULL;
703 FT_Pos in_x = 0;
704 FT_Pos in_y = 0;
705 AF_Direction in_dir = AF_DIR_NONE;
708 for ( point = points; point < point_limit; point++ )
710 AF_Point next;
711 FT_Pos out_x, out_y;
714 if ( point == first )
716 prev = first->prev;
717 in_x = first->fx - prev->fx;
718 in_y = first->fy - prev->fy;
719 in_dir = af_direction_compute( in_x, in_y );
720 first = prev + 1;
723 point->in_dir = (FT_Char)in_dir;
725 next = point->next;
726 out_x = next->fx - point->fx;
727 out_y = next->fy - point->fy;
729 in_dir = af_direction_compute( out_x, out_y );
730 point->out_dir = (FT_Char)in_dir;
732 if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
734 Is_Weak_Point:
735 point->flags |= AF_FLAG_WEAK_INTERPOLATION;
737 else if ( point->out_dir == point->in_dir )
739 if ( point->out_dir != AF_DIR_NONE )
740 goto Is_Weak_Point;
742 if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
743 goto Is_Weak_Point;
745 else if ( point->in_dir == -point->out_dir )
746 goto Is_Weak_Point;
748 in_x = out_x;
749 in_y = out_y;
750 prev = point;
755 /* compute inflection points -- */
756 /* disabled due to no longer perceived benefits */
757 if ( 0 && get_inflections )
758 af_glyph_hints_compute_inflections( hints );
760 Exit:
761 return error;
765 FT_LOCAL_DEF( void )
766 af_glyph_hints_save( AF_GlyphHints hints,
767 FT_Outline* outline )
769 AF_Point point = hints->points;
770 AF_Point limit = point + hints->num_points;
771 FT_Vector* vec = outline->points;
772 char* tag = outline->tags;
775 for ( ; point < limit; point++, vec++, tag++ )
777 vec->x = point->x;
778 vec->y = point->y;
780 if ( point->flags & AF_FLAG_CONIC )
781 tag[0] = FT_CURVE_TAG_CONIC;
782 else if ( point->flags & AF_FLAG_CUBIC )
783 tag[0] = FT_CURVE_TAG_CUBIC;
784 else
785 tag[0] = FT_CURVE_TAG_ON;
790 /****************************************************************
792 * EDGE POINT GRID-FITTING
794 ****************************************************************/
797 FT_LOCAL_DEF( void )
798 af_glyph_hints_align_edge_points( AF_GlyphHints hints,
799 AF_Dimension dim )
801 AF_AxisHints axis = & hints->axis[dim];
802 AF_Segment segments = axis->segments;
803 AF_Segment segment_limit = segments + axis->num_segments;
804 AF_Segment seg;
807 if ( dim == AF_DIMENSION_HORZ )
809 for ( seg = segments; seg < segment_limit; seg++ )
811 AF_Edge edge = seg->edge;
812 AF_Point point, first, last;
815 if ( edge == NULL )
816 continue;
818 first = seg->first;
819 last = seg->last;
820 point = first;
821 for (;;)
823 point->x = edge->pos;
824 point->flags |= AF_FLAG_TOUCH_X;
826 if ( point == last )
827 break;
829 point = point->next;
834 else
836 for ( seg = segments; seg < segment_limit; seg++ )
838 AF_Edge edge = seg->edge;
839 AF_Point point, first, last;
842 if ( edge == NULL )
843 continue;
845 first = seg->first;
846 last = seg->last;
847 point = first;
848 for (;;)
850 point->y = edge->pos;
851 point->flags |= AF_FLAG_TOUCH_Y;
853 if ( point == last )
854 break;
856 point = point->next;
863 /****************************************************************
865 * STRONG POINT INTERPOLATION
867 ****************************************************************/
870 /* hint the strong points -- this is equivalent to the TrueType `IP' */
871 /* hinting instruction */
873 FT_LOCAL_DEF( void )
874 af_glyph_hints_align_strong_points( AF_GlyphHints hints,
875 AF_Dimension dim )
877 AF_Point points = hints->points;
878 AF_Point point_limit = points + hints->num_points;
879 AF_AxisHints axis = &hints->axis[dim];
880 AF_Edge edges = axis->edges;
881 AF_Edge edge_limit = edges + axis->num_edges;
882 AF_Flags touch_flag;
885 if ( dim == AF_DIMENSION_HORZ )
886 touch_flag = AF_FLAG_TOUCH_X;
887 else
888 touch_flag = AF_FLAG_TOUCH_Y;
890 if ( edges < edge_limit )
892 AF_Point point;
893 AF_Edge edge;
896 for ( point = points; point < point_limit; point++ )
898 FT_Pos u, ou, fu; /* point position */
899 FT_Pos delta;
902 if ( point->flags & touch_flag )
903 continue;
905 /* if this point is candidate to weak interpolation, we */
906 /* interpolate it after all strong points have been processed */
908 if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
909 !( point->flags & AF_FLAG_INFLECTION ) )
910 continue;
912 if ( dim == AF_DIMENSION_VERT )
914 u = point->fy;
915 ou = point->oy;
917 else
919 u = point->fx;
920 ou = point->ox;
923 fu = u;
925 /* is the point before the first edge? */
926 edge = edges;
927 delta = edge->fpos - u;
928 if ( delta >= 0 )
930 u = edge->pos - ( edge->opos - ou );
931 goto Store_Point;
934 /* is the point after the last edge? */
935 edge = edge_limit - 1;
936 delta = u - edge->fpos;
937 if ( delta >= 0 )
939 u = edge->pos + ( ou - edge->opos );
940 goto Store_Point;
944 FT_PtrDist min, max, mid;
945 FT_Pos fpos;
948 /* find enclosing edges */
949 min = 0;
950 max = edge_limit - edges;
952 #if 1
953 /* for small edge counts, a linear search is better */
954 if ( max <= 8 )
956 FT_PtrDist nn;
958 for ( nn = 0; nn < max; nn++ )
959 if ( edges[nn].fpos >= u )
960 break;
962 if ( edges[nn].fpos == u )
964 u = edges[nn].pos;
965 goto Store_Point;
967 min = nn;
969 else
970 #endif
971 while ( min < max )
973 mid = ( max + min ) >> 1;
974 edge = edges + mid;
975 fpos = edge->fpos;
977 if ( u < fpos )
978 max = mid;
979 else if ( u > fpos )
980 min = mid + 1;
981 else
983 /* we are on the edge */
984 u = edge->pos;
985 goto Store_Point;
990 AF_Edge before = edges + min - 1;
991 AF_Edge after = edges + min + 0;
994 /* assert( before && after && before != after ) */
995 if ( before->scale == 0 )
996 before->scale = FT_DivFix( after->pos - before->pos,
997 after->fpos - before->fpos );
999 u = before->pos + FT_MulFix( fu - before->fpos,
1000 before->scale );
1004 Store_Point:
1005 /* save the point position */
1006 if ( dim == AF_DIMENSION_HORZ )
1007 point->x = u;
1008 else
1009 point->y = u;
1011 point->flags |= touch_flag;
1017 /****************************************************************
1019 * WEAK POINT INTERPOLATION
1021 ****************************************************************/
1024 static void
1025 af_iup_shift( AF_Point p1,
1026 AF_Point p2,
1027 AF_Point ref )
1029 AF_Point p;
1030 FT_Pos delta = ref->u - ref->v;
1032 if ( delta == 0 )
1033 return;
1035 for ( p = p1; p < ref; p++ )
1036 p->u = p->v + delta;
1038 for ( p = ref + 1; p <= p2; p++ )
1039 p->u = p->v + delta;
1043 static void
1044 af_iup_interp( AF_Point p1,
1045 AF_Point p2,
1046 AF_Point ref1,
1047 AF_Point ref2 )
1049 AF_Point p;
1050 FT_Pos u;
1051 FT_Pos v1 = ref1->v;
1052 FT_Pos v2 = ref2->v;
1053 FT_Pos d1 = ref1->u - v1;
1054 FT_Pos d2 = ref2->u - v2;
1057 if ( p1 > p2 )
1058 return;
1060 if ( v1 == v2 )
1062 for ( p = p1; p <= p2; p++ )
1064 u = p->v;
1066 if ( u <= v1 )
1067 u += d1;
1068 else
1069 u += d2;
1071 p->u = u;
1073 return;
1076 if ( v1 < v2 )
1078 for ( p = p1; p <= p2; p++ )
1080 u = p->v;
1082 if ( u <= v1 )
1083 u += d1;
1084 else if ( u >= v2 )
1085 u += d2;
1086 else
1087 u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
1089 p->u = u;
1092 else
1094 for ( p = p1; p <= p2; p++ )
1096 u = p->v;
1098 if ( u <= v2 )
1099 u += d2;
1100 else if ( u >= v1 )
1101 u += d1;
1102 else
1103 u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
1105 p->u = u;
1111 FT_LOCAL_DEF( void )
1112 af_glyph_hints_align_weak_points( AF_GlyphHints hints,
1113 AF_Dimension dim )
1115 AF_Point points = hints->points;
1116 AF_Point point_limit = points + hints->num_points;
1117 AF_Point* contour = hints->contours;
1118 AF_Point* contour_limit = contour + hints->num_contours;
1119 AF_Flags touch_flag;
1120 AF_Point point;
1121 AF_Point end_point;
1122 AF_Point first_point;
1125 /* PASS 1: Move segment points to edge positions */
1127 if ( dim == AF_DIMENSION_HORZ )
1129 touch_flag = AF_FLAG_TOUCH_X;
1131 for ( point = points; point < point_limit; point++ )
1133 point->u = point->x;
1134 point->v = point->ox;
1137 else
1139 touch_flag = AF_FLAG_TOUCH_Y;
1141 for ( point = points; point < point_limit; point++ )
1143 point->u = point->y;
1144 point->v = point->oy;
1148 point = points;
1150 for ( ; contour < contour_limit; contour++ )
1152 AF_Point first_touched, last_touched;
1155 point = *contour;
1156 end_point = point->prev;
1157 first_point = point;
1159 /* find first touched point */
1160 for (;;)
1162 if ( point > end_point ) /* no touched point in contour */
1163 goto NextContour;
1165 if ( point->flags & touch_flag )
1166 break;
1168 point++;
1171 first_touched = point;
1172 last_touched = point;
1174 for (;;)
1176 FT_ASSERT( point <= end_point &&
1177 ( point->flags & touch_flag ) != 0 );
1179 /* skip any touched neighbhours */
1180 while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
1181 point++;
1183 last_touched = point;
1185 /* find the next touched point, if any */
1186 point ++;
1187 for (;;)
1189 if ( point > end_point )
1190 goto EndContour;
1192 if ( ( point->flags & touch_flag ) != 0 )
1193 break;
1195 point++;
1198 /* interpolate between last_touched and point */
1199 af_iup_interp( last_touched + 1, point - 1,
1200 last_touched, point );
1203 EndContour:
1204 /* special case: only one point was touched */
1205 if ( last_touched == first_touched )
1207 af_iup_shift( first_point, end_point, first_touched );
1209 else /* interpolate the last part */
1211 if ( last_touched < end_point )
1212 af_iup_interp( last_touched + 1, end_point,
1213 last_touched, first_touched );
1215 if ( first_touched > points )
1216 af_iup_interp( first_point, first_touched - 1,
1217 last_touched, first_touched );
1220 NextContour:
1224 /* now save the interpolated values back to x/y */
1225 if ( dim == AF_DIMENSION_HORZ )
1227 for ( point = points; point < point_limit; point++ )
1228 point->x = point->u;
1230 else
1232 for ( point = points; point < point_limit; point++ )
1233 point->y = point->u;
1238 #ifdef AF_USE_WARPER
1240 FT_LOCAL_DEF( void )
1241 af_glyph_hints_scale_dim( AF_GlyphHints hints,
1242 AF_Dimension dim,
1243 FT_Fixed scale,
1244 FT_Pos delta )
1246 AF_Point points = hints->points;
1247 AF_Point points_limit = points + hints->num_points;
1248 AF_Point point;
1251 if ( dim == AF_DIMENSION_HORZ )
1253 for ( point = points; point < points_limit; point++ )
1254 point->x = FT_MulFix( point->fx, scale ) + delta;
1256 else
1258 for ( point = points; point < points_limit; point++ )
1259 point->y = FT_MulFix( point->fy, scale ) + delta;
1263 #endif /* AF_USE_WARPER */
1265 /* END */