ReactOS 0.4.15-dev-7994-gb388cb6
pshalgo.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* pshalgo.c */
4/* */
5/* PostScript hinting algorithm (body). */
6/* */
7/* Copyright 2001-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 <ft2build.h>
20#include FT_INTERNAL_OBJECTS_H
21#include FT_INTERNAL_DEBUG_H
22#include FT_INTERNAL_CALC_H
23#include "pshalgo.h"
24
25#include "pshnterr.h"
26
27
28#undef FT_COMPONENT
29#define FT_COMPONENT trace_pshalgo
30
31
32#ifdef DEBUG_HINTER
33 PSH_Hint_Table ps_debug_hint_table = NULL;
34 PSH_HintFunc ps_debug_hint_func = NULL;
35 PSH_Glyph ps_debug_glyph = NULL;
36#endif
37
38
39#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */
40 /* and similar glyphs */
41
42
43 /*************************************************************************/
44 /*************************************************************************/
45 /***** *****/
46 /***** BASIC HINTS RECORDINGS *****/
47 /***** *****/
48 /*************************************************************************/
49 /*************************************************************************/
50
51 /* return true if two stem hints overlap */
52 static FT_Int
54 PSH_Hint hint2 )
55 {
56 return hint1->org_pos + hint1->org_len >= hint2->org_pos &&
57 hint2->org_pos + hint2->org_len >= hint1->org_pos;
58 }
59
60
61 /* destroy hints table */
62 static void
65 {
66 FT_FREE( table->zones );
67 table->num_zones = 0;
68 table->zone = NULL;
69
70 FT_FREE( table->sort );
71 FT_FREE( table->hints );
72 table->num_hints = 0;
73 table->max_hints = 0;
74 table->sort_global = NULL;
75 }
76
77
78 /* deactivate all hints in a table */
79 static void
81 {
82 FT_UInt count = table->max_hints;
83 PSH_Hint hint = table->hints;
84
85
86 for ( ; count > 0; count--, hint++ )
87 {
89 hint->order = -1;
90 }
91 }
92
93
94 /* internal function to record a new hint */
95 static void
97 FT_UInt idx )
98 {
99 PSH_Hint hint = table->hints + idx;
100
101
102 if ( idx >= table->max_hints )
103 {
104 FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx ));
105 return;
106 }
107
108 /* ignore active hints */
109 if ( psh_hint_is_active( hint ) )
110 return;
111
113
114 /* now scan the current active hint set to check */
115 /* whether `hint' overlaps with another hint */
116 {
117 PSH_Hint* sorted = table->sort_global;
118 FT_UInt count = table->num_hints;
119 PSH_Hint hint2;
120
121
122 hint->parent = NULL;
123 for ( ; count > 0; count--, sorted++ )
124 {
125 hint2 = sorted[0];
126
127 if ( psh_hint_overlap( hint, hint2 ) )
128 {
129 hint->parent = hint2;
130 break;
131 }
132 }
133 }
134
135 if ( table->num_hints < table->max_hints )
136 table->sort_global[table->num_hints++] = hint;
137 else
138 FT_TRACE0(( "psh_hint_table_record: too many sorted hints! BUG!\n" ));
139 }
140
141
142 static void
144 PS_Mask hint_mask )
145 {
146 FT_Int mask = 0, val = 0;
147 FT_Byte* cursor = hint_mask->bytes;
149
150
151 limit = hint_mask->num_bits;
152
153 for ( idx = 0; idx < limit; idx++ )
154 {
155 if ( mask == 0 )
156 {
157 val = *cursor++;
158 mask = 0x80;
159 }
160
161 if ( val & mask )
163
164 mask >>= 1;
165 }
166 }
167
168
169 /* create hints table */
170 static FT_Error
173 PS_Mask_Table hint_masks,
174 PS_Mask_Table counter_masks,
176 {
179
180 FT_UNUSED( counter_masks );
181
182
183 count = hints->num_hints;
184
185 /* allocate our tables */
186 if ( FT_NEW_ARRAY( table->sort, 2 * count ) ||
187 FT_NEW_ARRAY( table->hints, count ) ||
188 FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
189 goto Exit;
190
191 table->max_hints = count;
192 table->sort_global = table->sort + count;
193 table->num_hints = 0;
194 table->num_zones = 0;
195 table->zone = NULL;
196
197 /* initialize the `table->hints' array */
198 {
199 PSH_Hint write = table->hints;
200 PS_Hint read = hints->hints;
201
202
203 for ( ; count > 0; count--, write++, read++ )
204 {
205 write->org_pos = read->pos;
206 write->org_len = read->len;
207 write->flags = read->flags;
208 }
209 }
210
211 /* we now need to determine the initial `parent' stems; first */
212 /* activate the hints that are given by the initial hint masks */
213 if ( hint_masks )
214 {
215 PS_Mask mask = hint_masks->masks;
216
217
218 count = hint_masks->num_masks;
219 table->hint_masks = hint_masks;
220
221 for ( ; count > 0; count--, mask++ )
223 }
224
225 /* finally, do a linear parse in case some hints were left alone */
226 if ( table->num_hints != table->max_hints )
227 {
228 FT_UInt idx;
229
230
231 FT_TRACE0(( "psh_hint_table_init: missing/incorrect hint masks\n" ));
232
233 count = table->max_hints;
234 for ( idx = 0; idx < count; idx++ )
236 }
237
238 Exit:
239 return error;
240 }
241
242
243 static void
245 PS_Mask hint_mask )
246 {
247 FT_Int mask = 0, val = 0;
248 FT_Byte* cursor = hint_mask->bytes;
250
251
252 limit = hint_mask->num_bits;
253 count = 0;
254
256
257 for ( idx = 0; idx < limit; idx++ )
258 {
259 if ( mask == 0 )
260 {
261 val = *cursor++;
262 mask = 0x80;
263 }
264
265 if ( val & mask )
266 {
267 PSH_Hint hint = &table->hints[idx];
268
269
270 if ( !psh_hint_is_active( hint ) )
271 {
272 FT_UInt count2;
273
274#if 0
275 PSH_Hint* sort = table->sort;
276 PSH_Hint hint2;
277
278
279 for ( count2 = count; count2 > 0; count2--, sort++ )
280 {
281 hint2 = sort[0];
282 if ( psh_hint_overlap( hint, hint2 ) )
283 FT_TRACE0(( "psh_hint_table_activate_mask:"
284 " found overlapping hints\n" ))
285 }
286#else
287 count2 = 0;
288#endif
289
290 if ( count2 == 0 )
291 {
293 if ( count < table->max_hints )
294 table->sort[count++] = hint;
295 else
296 FT_TRACE0(( "psh_hint_tableactivate_mask:"
297 " too many active hints\n" ));
298 }
299 }
300 }
301
302 mask >>= 1;
303 }
304 table->num_hints = count;
305
306 /* now, sort the hints; they are guaranteed to not overlap */
307 /* so we can compare their "org_pos" field directly */
308 {
309 FT_Int i1, i2;
310 PSH_Hint hint1, hint2;
311 PSH_Hint* sort = table->sort;
312
313
314 /* a simple bubble sort will do, since in 99% of cases, the hints */
315 /* will be already sorted -- and the sort will be linear */
316 for ( i1 = 1; i1 < (FT_Int)count; i1++ )
317 {
318 hint1 = sort[i1];
319 for ( i2 = i1 - 1; i2 >= 0; i2-- )
320 {
321 hint2 = sort[i2];
322
323 if ( hint2->org_pos < hint1->org_pos )
324 break;
325
326 sort[i2 + 1] = hint2;
327 sort[i2] = hint1;
328 }
329 }
330 }
331 }
332
333
334 /*************************************************************************/
335 /*************************************************************************/
336 /***** *****/
337 /***** HINTS GRID-FITTING AND OPTIMIZATION *****/
338 /***** *****/
339 /*************************************************************************/
340 /*************************************************************************/
341
342#if 1
343 static FT_Pos
345 FT_Pos len,
346 FT_Bool do_snapping )
347 {
348 if ( len <= 64 )
349 len = 64;
350 else
351 {
352 FT_Pos delta = len - dim->stdw.widths[0].cur;
353
354
355 if ( delta < 0 )
356 delta = -delta;
357
358 if ( delta < 40 )
359 {
360 len = dim->stdw.widths[0].cur;
361 if ( len < 48 )
362 len = 48;
363 }
364
365 if ( len < 3 * 64 )
366 {
367 delta = ( len & 63 );
368 len &= -64;
369
370 if ( delta < 10 )
371 len += delta;
372
373 else if ( delta < 32 )
374 len += 10;
375
376 else if ( delta < 54 )
377 len += 54;
378
379 else
380 len += delta;
381 }
382 else
383 len = FT_PIX_ROUND( len );
384 }
385
386 if ( do_snapping )
387 len = FT_PIX_ROUND( len );
388
389 return len;
390 }
391#endif /* 0 */
392
393
394#ifdef DEBUG_HINTER
395
396 static void
397 ps_simple_scale( PSH_Hint_Table table,
399 FT_Fixed delta,
400 FT_Int dimension )
401 {
403
404
405 for ( count = 0; count < table->max_hints; count++ )
406 {
407 PSH_Hint hint = table->hints + count;
408
409
410 hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
411 hint->cur_len = FT_MulFix( hint->org_len, scale );
412
413 if ( ps_debug_hint_func )
414 ps_debug_hint_func( hint, dimension );
415 }
416 }
417
418#endif /* DEBUG_HINTER */
419
420
421 static FT_Fixed
423 FT_Fixed len )
424 {
425 FT_Fixed delta1 = FT_PIX_ROUND( pos ) - pos;
426 FT_Fixed delta2 = FT_PIX_ROUND( pos + len ) - pos - len;
427
428
429 if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) )
430 return delta1;
431 else
432 return delta2;
433 }
434
435
436 static void
438 PSH_Globals globals,
439 FT_Int dimension,
440 PSH_Glyph glyph )
441 {
442 PSH_Dimension dim = &globals->dimension[dimension];
444 FT_Fixed delta = dim->scale_delta;
445
446
447 if ( !psh_hint_is_fitted( hint ) )
448 {
449 FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;
450 FT_Pos len = FT_MulFix( hint->org_len, scale );
451
452 FT_Int do_snapping;
453 FT_Pos fit_len;
455
456
457 /* ignore stem alignments when requested through the hint flags */
458 if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
459 ( dimension == 1 && !glyph->do_vert_hints ) )
460 {
461 hint->cur_pos = pos;
462 hint->cur_len = len;
463
465 return;
466 }
467
468 /* perform stem snapping when requested - this is necessary
469 * for monochrome and LCD hinting modes only
470 */
471 do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
472 ( dimension == 1 && glyph->do_vert_snapping );
473
474 hint->cur_len = fit_len = len;
475
476 /* check blue zones for horizontal stems */
478 align.align_bot = align.align_top = 0;
479
480 if ( dimension == 1 )
481 psh_blues_snap_stem( &globals->blues,
482 hint->org_pos + hint->org_len,
483 hint->org_pos,
484 &align );
485
486 switch ( align.align )
487 {
489 /* the top of the stem is aligned against a blue zone */
490 hint->cur_pos = align.align_top - fit_len;
491 break;
492
494 /* the bottom of the stem is aligned against a blue zone */
495 hint->cur_pos = align.align_bot;
496 break;
497
499 /* both edges of the stem are aligned against blue zones */
500 hint->cur_pos = align.align_bot;
501 hint->cur_len = align.align_top - align.align_bot;
502 break;
503
504 default:
505 {
506 PSH_Hint parent = hint->parent;
507
508
509 if ( parent )
510 {
511 FT_Pos par_org_center, par_cur_center;
512 FT_Pos cur_org_center, cur_delta;
513
514
515 /* ensure that parent is already fitted */
516 if ( !psh_hint_is_fitted( parent ) )
517 psh_hint_align( parent, globals, dimension, glyph );
518
519 /* keep original relation between hints, this is, use the */
520 /* scaled distance between the centers of the hints to */
521 /* compute the new position */
522 par_org_center = parent->org_pos + ( parent->org_len >> 1 );
523 par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 );
524 cur_org_center = hint->org_pos + ( hint->org_len >> 1 );
525
526 cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
527 pos = par_cur_center + cur_delta - ( len >> 1 );
528 }
529
530 hint->cur_pos = pos;
531 hint->cur_len = fit_len;
532
533 /* Stem adjustment tries to snap stem widths to standard
534 * ones. This is important to prevent unpleasant rounding
535 * artefacts.
536 */
537 if ( glyph->do_stem_adjust )
538 {
539 if ( len <= 64 )
540 {
541 /* the stem is less than one pixel; we will center it
542 * around the nearest pixel center
543 */
544 if ( len >= 32 )
545 {
546 /* This is a special case where we also widen the stem
547 * and align it to the pixel grid.
548 *
549 * stem_center = pos + (len/2)
550 * nearest_pixel_center = FT_ROUND(stem_center-32)+32
551 * new_pos = nearest_pixel_center-32
552 * = FT_ROUND(stem_center-32)
553 * = FT_FLOOR(stem_center-32+32)
554 * = FT_FLOOR(stem_center)
555 * new_len = 64
556 */
557 pos = FT_PIX_FLOOR( pos + ( len >> 1 ) );
558 len = 64;
559 }
560 else if ( len > 0 )
561 {
562 /* This is a very small stem; we simply align it to the
563 * pixel grid, trying to find the minimum displacement.
564 *
565 * left = pos
566 * right = pos + len
567 * left_nearest_edge = ROUND(pos)
568 * right_nearest_edge = ROUND(right)
569 *
570 * if ( ABS(left_nearest_edge - left) <=
571 * ABS(right_nearest_edge - right) )
572 * new_pos = left
573 * else
574 * new_pos = right
575 */
576 FT_Pos left_nearest = FT_PIX_ROUND( pos );
577 FT_Pos right_nearest = FT_PIX_ROUND( pos + len );
578 FT_Pos left_disp = left_nearest - pos;
579 FT_Pos right_disp = right_nearest - ( pos + len );
580
581
582 if ( left_disp < 0 )
583 left_disp = -left_disp;
584 if ( right_disp < 0 )
585 right_disp = -right_disp;
586 if ( left_disp <= right_disp )
587 pos = left_nearest;
588 else
589 pos = right_nearest;
590 }
591 else
592 {
593 /* this is a ghost stem; we simply round it */
594 pos = FT_PIX_ROUND( pos );
595 }
596 }
597 else
598 {
600 }
601 }
602
603 /* now that we have a good hinted stem width, try to position */
604 /* the stem along a pixel grid integer coordinate */
606 hint->cur_len = len;
607 }
608 }
609
610 if ( do_snapping )
611 {
612 pos = hint->cur_pos;
613 len = hint->cur_len;
614
615 if ( len < 64 )
616 len = 64;
617 else
618 len = FT_PIX_ROUND( len );
619
620 switch ( align.align )
621 {
623 hint->cur_pos = align.align_top - len;
624 hint->cur_len = len;
625 break;
626
628 hint->cur_len = len;
629 break;
630
632 /* don't touch */
633 break;
634
635
636 default:
637 hint->cur_len = len;
638 if ( len & 64 )
639 pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32;
640 else
641 pos = FT_PIX_ROUND( pos + ( len >> 1 ) );
642
643 hint->cur_pos = pos - ( len >> 1 );
644 hint->cur_len = len;
645 }
646 }
647
649
650#ifdef DEBUG_HINTER
651 if ( ps_debug_hint_func )
652 ps_debug_hint_func( hint, dimension );
653#endif
654 }
655 }
656
657
658#if 0 /* not used for now, experimental */
659
660 /*
661 * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
662 * of stems
663 */
664 static void
665 psh_hint_align_light( PSH_Hint hint,
666 PSH_Globals globals,
667 FT_Int dimension,
668 PSH_Glyph glyph )
669 {
670 PSH_Dimension dim = &globals->dimension[dimension];
672 FT_Fixed delta = dim->scale_delta;
673
674
675 if ( !psh_hint_is_fitted( hint ) )
676 {
677 FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;
678 FT_Pos len = FT_MulFix( hint->org_len, scale );
679
680 FT_Pos fit_len;
681
683
684
685 /* ignore stem alignments when requested through the hint flags */
686 if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
687 ( dimension == 1 && !glyph->do_vert_hints ) )
688 {
689 hint->cur_pos = pos;
690 hint->cur_len = len;
691
693 return;
694 }
695
696 fit_len = len;
697
698 hint->cur_len = fit_len;
699
700 /* check blue zones for horizontal stems */
702 align.align_bot = align.align_top = 0;
703
704 if ( dimension == 1 )
705 psh_blues_snap_stem( &globals->blues,
706 hint->org_pos + hint->org_len,
707 hint->org_pos,
708 &align );
709
710 switch ( align.align )
711 {
713 /* the top of the stem is aligned against a blue zone */
714 hint->cur_pos = align.align_top - fit_len;
715 break;
716
718 /* the bottom of the stem is aligned against a blue zone */
719 hint->cur_pos = align.align_bot;
720 break;
721
723 /* both edges of the stem are aligned against blue zones */
724 hint->cur_pos = align.align_bot;
725 hint->cur_len = align.align_top - align.align_bot;
726 break;
727
728 default:
729 {
730 PSH_Hint parent = hint->parent;
731
732
733 if ( parent )
734 {
735 FT_Pos par_org_center, par_cur_center;
736 FT_Pos cur_org_center, cur_delta;
737
738
739 /* ensure that parent is already fitted */
740 if ( !psh_hint_is_fitted( parent ) )
741 psh_hint_align_light( parent, globals, dimension, glyph );
742
743 par_org_center = parent->org_pos + ( parent->org_len / 2 );
744 par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );
745 cur_org_center = hint->org_pos + ( hint->org_len / 2 );
746
747 cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
748 pos = par_cur_center + cur_delta - ( len >> 1 );
749 }
750
751 /* Stems less than one pixel wide are easy -- we want to
752 * make them as dark as possible, so they must fall within
753 * one pixel. If the stem is split between two pixels
754 * then snap the edge that is nearer to the pixel boundary
755 * to the pixel boundary.
756 */
757 if ( len <= 64 )
758 {
759 if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 )
761 }
762
763 /* Position stems other to minimize the amount of mid-grays.
764 * There are, in general, two positions that do this,
765 * illustrated as A) and B) below.
766 *
767 * + + + +
768 *
769 * A) |--------------------------------|
770 * B) |--------------------------------|
771 * C) |--------------------------------|
772 *
773 * Position A) (split the excess stem equally) should be better
774 * for stems of width N + f where f < 0.5.
775 *
776 * Position B) (split the deficiency equally) should be better
777 * for stems of width N + f where f > 0.5.
778 *
779 * It turns out though that minimizing the total number of lit
780 * pixels is also important, so position C), with one edge
781 * aligned with a pixel boundary is actually preferable
782 * to A). There are also more possible positions for C) than
783 * for A) or B), so it involves less distortion of the overall
784 * character shape.
785 */
786 else /* len > 64 */
787 {
788 FT_Fixed frac_len = len & 63;
789 FT_Fixed center = pos + ( len >> 1 );
790 FT_Fixed delta_a, delta_b;
791
792
793 if ( ( len / 64 ) & 1 )
794 {
795 delta_a = FT_PIX_FLOOR( center ) + 32 - center;
796 delta_b = FT_PIX_ROUND( center ) - center;
797 }
798 else
799 {
800 delta_a = FT_PIX_ROUND( center ) - center;
801 delta_b = FT_PIX_FLOOR( center ) + 32 - center;
802 }
803
804 /* We choose between B) and C) above based on the amount
805 * of fractional stem width; for small amounts, choose
806 * C) always, for large amounts, B) always, and inbetween,
807 * pick whichever one involves less stem movement.
808 */
809 if ( frac_len < 32 )
810 {
812 }
813 else if ( frac_len < 48 )
814 {
816 len );
817
818 if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) )
819 pos += side_delta;
820 else
821 pos += delta_b;
822 }
823 else
824 {
825 pos += delta_b;
826 }
827 }
828
829 hint->cur_pos = pos;
830 }
831 } /* switch */
832
834
835#ifdef DEBUG_HINTER
836 if ( ps_debug_hint_func )
837 ps_debug_hint_func( hint, dimension );
838#endif
839 }
840 }
841
842#endif /* 0 */
843
844
845 static void
847 PSH_Globals globals,
848 FT_Int dimension,
849 PSH_Glyph glyph )
850 {
853
854#ifdef DEBUG_HINTER
855
856 PSH_Dimension dim = &globals->dimension[dimension];
858 FT_Fixed delta = dim->scale_delta;
859
860
861 if ( ps_debug_no_vert_hints && dimension == 0 )
862 {
863 ps_simple_scale( table, scale, delta, dimension );
864 return;
865 }
866
867 if ( ps_debug_no_horz_hints && dimension == 1 )
868 {
869 ps_simple_scale( table, scale, delta, dimension );
870 return;
871 }
872
873#endif /* DEBUG_HINTER*/
874
875 hint = table->hints;
876 count = table->max_hints;
877
878 for ( ; count > 0; count--, hint++ )
879 psh_hint_align( hint, globals, dimension, glyph );
880 }
881
882
883 /*************************************************************************/
884 /*************************************************************************/
885 /***** *****/
886 /***** POINTS INTERPOLATION ROUTINES *****/
887 /***** *****/
888 /*************************************************************************/
889 /*************************************************************************/
890
891#define xxDEBUG_ZONES
892
893
894#ifdef DEBUG_ZONES
895
896#include FT_CONFIG_STANDARD_LIBRARY_H
897
898 static void
899 psh_print_zone( PSH_Zone zone )
900 {
901 printf( "zone [scale,delta,min,max] = [%.5f,%.2f,%d,%d]\n",
902 zone->scale / 65536.0,
903 zone->delta / 64.0,
904 zone->min,
905 zone->max );
906 }
907
908#endif /* DEBUG_ZONES */
909
910
911 /*************************************************************************/
912 /*************************************************************************/
913 /***** *****/
914 /***** HINTER GLYPH MANAGEMENT *****/
915 /***** *****/
916 /*************************************************************************/
917 /*************************************************************************/
918
919#define psh_corner_is_flat ft_corner_is_flat
920#define psh_corner_orientation ft_corner_orientation
921
922
923#ifdef COMPUTE_INFLEXS
924
925 /* compute all inflex points in a given glyph */
926 static void
928 {
929 FT_UInt n;
930
931
932 for ( n = 0; n < glyph->num_contours; n++ )
933 {
935 FT_Pos in_x, in_y, out_x, out_y;
936 FT_Int orient_prev, orient_cur;
937 FT_Int finished = 0;
938
939
940 /* we need at least 4 points to create an inflection point */
941 if ( glyph->contours[n].count < 4 )
942 continue;
943
944 /* compute first segment in contour */
945 first = glyph->contours[n].start;
946
947 start = end = first;
948 do
949 {
950 end = end->next;
951 if ( end == first )
952 goto Skip;
953
954 in_x = end->org_u - start->org_u;
955 in_y = end->org_v - start->org_v;
956
957 } while ( in_x == 0 && in_y == 0 );
958
959 /* extend the segment start whenever possible */
960 before = start;
961 do
962 {
963 do
964 {
965 start = before;
966 before = before->prev;
967 if ( before == first )
968 goto Skip;
969
970 out_x = start->org_u - before->org_u;
971 out_y = start->org_v - before->org_v;
972
973 } while ( out_x == 0 && out_y == 0 );
974
975 orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y );
976
977 } while ( orient_prev == 0 );
978
979 first = start;
980 in_x = out_x;
981 in_y = out_y;
982
983 /* now, process all segments in the contour */
984 do
985 {
986 /* first, extend current segment's end whenever possible */
987 after = end;
988 do
989 {
990 do
991 {
992 end = after;
993 after = after->next;
994 if ( after == first )
995 finished = 1;
996
997 out_x = after->org_u - end->org_u;
998 out_y = after->org_v - end->org_v;
999
1000 } while ( out_x == 0 && out_y == 0 );
1001
1002 orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y );
1003
1004 } while ( orient_cur == 0 );
1005
1006 if ( ( orient_cur ^ orient_prev ) < 0 )
1007 {
1008 do
1009 {
1011 start = start->next;
1012 }
1013 while ( start != end );
1014
1016 }
1017
1018 start = end;
1019 end = after;
1020 orient_prev = orient_cur;
1021 in_x = out_x;
1022 in_y = out_y;
1023
1024 } while ( !finished );
1025
1026 Skip:
1027 ;
1028 }
1029 }
1030
1031#endif /* COMPUTE_INFLEXS */
1032
1033
1034 static void
1036 {
1037 FT_Memory memory = glyph->memory;
1038
1039
1040 psh_hint_table_done( &glyph->hint_tables[1], memory );
1041 psh_hint_table_done( &glyph->hint_tables[0], memory );
1042
1043 FT_FREE( glyph->points );
1044 FT_FREE( glyph->contours );
1045
1046 glyph->num_points = 0;
1047 glyph->num_contours = 0;
1048
1049 glyph->memory = NULL;
1050 }
1051
1052
1053 static int
1055 FT_Pos dy )
1056 {
1057 FT_Pos ax, ay;
1058 int result = PSH_DIR_NONE;
1059
1060
1061 ax = FT_ABS( dx );
1062 ay = FT_ABS( dy );
1063
1064 if ( ay * 12 < ax )
1065 {
1066 /* |dy| <<< |dx| means a near-horizontal segment */
1067 result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT;
1068 }
1069 else if ( ax * 12 < ay )
1070 {
1071 /* |dx| <<< |dy| means a near-vertical segment */
1072 result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN;
1073 }
1074
1075 return result;
1076 }
1077
1078
1079 /* load outline point coordinates into hinter glyph */
1080 static void
1082 FT_Int dimension )
1083 {
1084 FT_Vector* vec = glyph->outline->points;
1085 PSH_Point point = glyph->points;
1086 FT_UInt count = glyph->num_points;
1087
1088
1089 for ( ; count > 0; count--, point++, vec++ )
1090 {
1091 point->flags2 = 0;
1092 point->hint = NULL;
1093 if ( dimension == 0 )
1094 {
1095 point->org_u = vec->x;
1096 point->org_v = vec->y;
1097 }
1098 else
1099 {
1100 point->org_u = vec->y;
1101 point->org_v = vec->x;
1102 }
1103
1104#ifdef DEBUG_HINTER
1105 point->org_x = vec->x;
1106 point->org_y = vec->y;
1107#endif
1108
1109 }
1110 }
1111
1112
1113 /* save hinted point coordinates back to outline */
1114 static void
1116 FT_Int dimension )
1117 {
1118 FT_UInt n;
1119 PSH_Point point = glyph->points;
1120 FT_Vector* vec = glyph->outline->points;
1121 char* tags = glyph->outline->tags;
1122
1123
1124 for ( n = 0; n < glyph->num_points; n++ )
1125 {
1126 if ( dimension == 0 )
1127 vec[n].x = point->cur_u;
1128 else
1129 vec[n].y = point->cur_u;
1130
1131 if ( psh_point_is_strong( point ) )
1132 tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );
1133
1134#ifdef DEBUG_HINTER
1135
1136 if ( dimension == 0 )
1137 {
1138 point->cur_x = point->cur_u;
1139 point->flags_x = point->flags2 | point->flags;
1140 }
1141 else
1142 {
1143 point->cur_y = point->cur_u;
1144 point->flags_y = point->flags2 | point->flags;
1145 }
1146
1147#endif
1148
1149 point++;
1150 }
1151 }
1152
1153
1154 static FT_Error
1157 PS_Hints ps_hints,
1158 PSH_Globals globals )
1159 {
1162
1163
1164 /* clear all fields */
1165 FT_ZERO( glyph );
1166
1167 memory = glyph->memory = globals->memory;
1168
1169 /* allocate and setup points + contours arrays */
1170 if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) ||
1171 FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
1172 goto Exit;
1173
1174 glyph->num_points = (FT_UInt)outline->n_points;
1175 glyph->num_contours = (FT_UInt)outline->n_contours;
1176
1177 {
1178 FT_UInt first = 0, next, n;
1179 PSH_Point points = glyph->points;
1180 PSH_Contour contour = glyph->contours;
1181
1182
1183 for ( n = 0; n < glyph->num_contours; n++ )
1184 {
1185 FT_UInt count;
1187
1188
1189 next = (FT_UInt)outline->contours[n] + 1;
1190 count = next - first;
1191
1192 contour->start = points + first;
1193 contour->count = count;
1194
1195 if ( count > 0 )
1196 {
1197 point = points + first;
1198
1199 point->prev = points + next - 1;
1200 point->contour = contour;
1201
1202 for ( ; count > 1; count-- )
1203 {
1204 point[0].next = point + 1;
1205 point[1].prev = point;
1206 point++;
1207 point->contour = contour;
1208 }
1209 point->next = points + first;
1210 }
1211
1212 contour++;
1213 first = next;
1214 }
1215 }
1216
1217 {
1218 PSH_Point points = glyph->points;
1220 FT_Vector* vec = outline->points;
1221 FT_UInt n;
1222
1223
1224 for ( n = 0; n < glyph->num_points; n++, point++ )
1225 {
1226 FT_Int n_prev = (FT_Int)( point->prev - points );
1227 FT_Int n_next = (FT_Int)( point->next - points );
1228 FT_Pos dxi, dyi, dxo, dyo;
1229
1230
1231 if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
1232 point->flags = PSH_POINT_OFF;
1233
1234 dxi = vec[n].x - vec[n_prev].x;
1235 dyi = vec[n].y - vec[n_prev].y;
1236
1237 point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );
1238
1239 dxo = vec[n_next].x - vec[n].x;
1240 dyo = vec[n_next].y - vec[n].y;
1241
1242 point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );
1243
1244 /* detect smooth points */
1245 if ( point->flags & PSH_POINT_OFF )
1246 point->flags |= PSH_POINT_SMOOTH;
1247
1248 else if ( point->dir_in == point->dir_out )
1249 {
1250 if ( point->dir_out != PSH_DIR_NONE ||
1251 psh_corner_is_flat( dxi, dyi, dxo, dyo ) )
1252 point->flags |= PSH_POINT_SMOOTH;
1253 }
1254 }
1255 }
1256
1257 glyph->outline = outline;
1258 glyph->globals = globals;
1259
1260#ifdef COMPUTE_INFLEXS
1261 psh_glyph_load_points( glyph, 0 );
1263#endif /* COMPUTE_INFLEXS */
1264
1265 /* now deal with hints tables */
1266 error = psh_hint_table_init( &glyph->hint_tables [0],
1267 &ps_hints->dimension[0].hints,
1268 &ps_hints->dimension[0].masks,
1269 &ps_hints->dimension[0].counters,
1270 memory );
1271 if ( error )
1272 goto Exit;
1273
1274 error = psh_hint_table_init( &glyph->hint_tables [1],
1275 &ps_hints->dimension[1].hints,
1276 &ps_hints->dimension[1].masks,
1277 &ps_hints->dimension[1].counters,
1278 memory );
1279 if ( error )
1280 goto Exit;
1281
1282 Exit:
1283 return error;
1284 }
1285
1286
1287 /* compute all extrema in a glyph for a given dimension */
1288 static void
1290 {
1291 FT_UInt n;
1292
1293
1294 /* first of all, compute all local extrema */
1295 for ( n = 0; n < glyph->num_contours; n++ )
1296 {
1297 PSH_Point first = glyph->contours[n].start;
1299
1300
1301 if ( glyph->contours[n].count == 0 )
1302 continue;
1303
1304 point = first;
1305 before = point;
1306
1307 do
1308 {
1309 before = before->prev;
1310 if ( before == first )
1311 goto Skip;
1312
1313 } while ( before->org_u == point->org_u );
1314
1315 first = point = before->next;
1316
1317 for (;;)
1318 {
1319 after = point;
1320 do
1321 {
1322 after = after->next;
1323 if ( after == first )
1324 goto Next;
1325
1326 } while ( after->org_u == point->org_u );
1327
1328 if ( before->org_u < point->org_u )
1329 {
1330 if ( after->org_u < point->org_u )
1331 {
1332 /* local maximum */
1333 goto Extremum;
1334 }
1335 }
1336 else /* before->org_u > point->org_u */
1337 {
1338 if ( after->org_u > point->org_u )
1339 {
1340 /* local minimum */
1341 Extremum:
1342 do
1343 {
1345 point = point->next;
1346
1347 } while ( point != after );
1348 }
1349 }
1350
1351 before = after->prev;
1352 point = after;
1353
1354 } /* for */
1355
1356 Next:
1357 ;
1358 }
1359
1360 /* for each extremum, determine its direction along the */
1361 /* orthogonal axis */
1362 for ( n = 0; n < glyph->num_points; n++ )
1363 {
1365
1366
1367 point = &glyph->points[n];
1368 before = point;
1369 after = point;
1370
1372 {
1373 do
1374 {
1375 before = before->prev;
1376 if ( before == point )
1377 goto Skip;
1378
1379 } while ( before->org_v == point->org_v );
1380
1381 do
1382 {
1383 after = after->next;
1384 if ( after == point )
1385 goto Skip;
1386
1387 } while ( after->org_v == point->org_v );
1388 }
1389
1390 if ( before->org_v < point->org_v &&
1391 after->org_v > point->org_v )
1392 {
1394 }
1395 else if ( before->org_v > point->org_v &&
1396 after->org_v < point->org_v )
1397 {
1399 }
1400
1401 Skip:
1402 ;
1403 }
1404 }
1405
1406
1407 /* major_dir is the direction for points on the bottom/left of the stem; */
1408 /* Points on the top/right of the stem will have a direction of */
1409 /* -major_dir. */
1410
1411 static void
1414 FT_UInt count,
1415 FT_Int threshold,
1416 FT_Int major_dir )
1417 {
1418 PSH_Hint* sort = table->sort;
1419 FT_UInt num_hints = table->num_hints;
1420
1421
1422 for ( ; count > 0; count--, point++ )
1423 {
1424 FT_Int point_dir = 0;
1425 FT_Pos org_u = point->org_u;
1426
1427
1428 if ( psh_point_is_strong( point ) )
1429 continue;
1430
1431 if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
1432 point_dir = point->dir_in;
1433
1434 else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
1435 point_dir = point->dir_out;
1436
1437 if ( point_dir )
1438 {
1439 if ( point_dir == major_dir )
1440 {
1441 FT_UInt nn;
1442
1443
1444 for ( nn = 0; nn < num_hints; nn++ )
1445 {
1446 PSH_Hint hint = sort[nn];
1447 FT_Pos d = org_u - hint->org_pos;
1448
1449
1450 if ( d < threshold && -d < threshold )
1451 {
1453 point->flags2 |= PSH_POINT_EDGE_MIN;
1454 point->hint = hint;
1455 break;
1456 }
1457 }
1458 }
1459 else if ( point_dir == -major_dir )
1460 {
1461 FT_UInt nn;
1462
1463
1464 for ( nn = 0; nn < num_hints; nn++ )
1465 {
1466 PSH_Hint hint = sort[nn];
1467 FT_Pos d = org_u - hint->org_pos - hint->org_len;
1468
1469
1470 if ( d < threshold && -d < threshold )
1471 {
1473 point->flags2 |= PSH_POINT_EDGE_MAX;
1474 point->hint = hint;
1475 break;
1476 }
1477 }
1478 }
1479 }
1480
1481#if 1
1482 else if ( psh_point_is_extremum( point ) )
1483 {
1484 /* treat extrema as special cases for stem edge alignment */
1485 FT_UInt nn, min_flag, max_flag;
1486
1487
1488 if ( major_dir == PSH_DIR_HORIZONTAL )
1489 {
1490 min_flag = PSH_POINT_POSITIVE;
1491 max_flag = PSH_POINT_NEGATIVE;
1492 }
1493 else
1494 {
1495 min_flag = PSH_POINT_NEGATIVE;
1496 max_flag = PSH_POINT_POSITIVE;
1497 }
1498
1499 if ( point->flags2 & min_flag )
1500 {
1501 for ( nn = 0; nn < num_hints; nn++ )
1502 {
1503 PSH_Hint hint = sort[nn];
1504 FT_Pos d = org_u - hint->org_pos;
1505
1506
1507 if ( d < threshold && -d < threshold )
1508 {
1509 point->flags2 |= PSH_POINT_EDGE_MIN;
1510 point->hint = hint;
1512 break;
1513 }
1514 }
1515 }
1516 else if ( point->flags2 & max_flag )
1517 {
1518 for ( nn = 0; nn < num_hints; nn++ )
1519 {
1520 PSH_Hint hint = sort[nn];
1521 FT_Pos d = org_u - hint->org_pos - hint->org_len;
1522
1523
1524 if ( d < threshold && -d < threshold )
1525 {
1526 point->flags2 |= PSH_POINT_EDGE_MAX;
1527 point->hint = hint;
1529 break;
1530 }
1531 }
1532 }
1533
1534 if ( !point->hint )
1535 {
1536 for ( nn = 0; nn < num_hints; nn++ )
1537 {
1538 PSH_Hint hint = sort[nn];
1539
1540
1541 if ( org_u >= hint->org_pos &&
1542 org_u <= hint->org_pos + hint->org_len )
1543 {
1544 point->hint = hint;
1545 break;
1546 }
1547 }
1548 }
1549 }
1550
1551#endif /* 1 */
1552 }
1553 }
1554
1555
1556 /* the accepted shift for strong points in fractional pixels */
1557#define PSH_STRONG_THRESHOLD 32
1558
1559 /* the maximum shift value in font units */
1560#define PSH_STRONG_THRESHOLD_MAXIMUM 30
1561
1562
1563 /* find strong points in a glyph */
1564 static void
1566 FT_Int dimension )
1567 {
1568 /* a point is `strong' if it is located on a stem edge and */
1569 /* has an `in' or `out' tangent parallel to the hint's direction */
1570
1571 PSH_Hint_Table table = &glyph->hint_tables[dimension];
1572 PS_Mask mask = table->hint_masks->masks;
1573 FT_UInt num_masks = table->hint_masks->num_masks;
1574 FT_UInt first = 0;
1575 FT_Int major_dir = ( dimension == 0 ) ? PSH_DIR_VERTICAL
1577 PSH_Dimension dim = &glyph->globals->dimension[dimension];
1578 FT_Fixed scale = dim->scale_mult;
1579 FT_Int threshold;
1580
1581
1582 threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale );
1583 if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM )
1584 threshold = PSH_STRONG_THRESHOLD_MAXIMUM;
1585
1586 /* process secondary hints to `selected' points */
1587 if ( num_masks > 1 && glyph->num_points > 0 )
1588 {
1589 /* the `endchar' op can reduce the number of points */
1590 first = mask->end_point > glyph->num_points
1591 ? glyph->num_points
1592 : mask->end_point;
1593 mask++;
1594 for ( ; num_masks > 1; num_masks--, mask++ )
1595 {
1596 FT_UInt next = FT_MIN( mask->end_point, glyph->num_points );
1597
1598
1599 if ( next > first )
1600 {
1601 FT_UInt count = next - first;
1602 PSH_Point point = glyph->points + first;
1603
1604
1606
1608 threshold, major_dir );
1609 }
1610 first = next;
1611 }
1612 }
1613
1614 /* process primary hints for all points */
1615 if ( num_masks == 1 )
1616 {
1617 FT_UInt count = glyph->num_points;
1618 PSH_Point point = glyph->points;
1619
1620
1621 psh_hint_table_activate_mask( table, table->hint_masks->masks );
1622
1624 threshold, major_dir );
1625 }
1626
1627 /* now, certain points may have been attached to a hint and */
1628 /* not marked as strong; update their flags then */
1629 {
1630 FT_UInt count = glyph->num_points;
1631 PSH_Point point = glyph->points;
1632
1633
1634 for ( ; count > 0; count--, point++ )
1635 if ( point->hint && !psh_point_is_strong( point ) )
1637 }
1638 }
1639
1640
1641 /* find points in a glyph which are in a blue zone and have `in' or */
1642 /* `out' tangents parallel to the horizontal axis */
1643 static void
1645 PSH_Glyph glyph )
1646 {
1649 FT_UInt glyph_count = glyph->num_points;
1650 FT_UInt blue_count;
1651 PSH_Point point = glyph->points;
1652
1653
1654 for ( ; glyph_count > 0; glyph_count--, point++ )
1655 {
1656 FT_Pos y;
1657
1658
1659 /* check tangents */
1660 if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) &&
1662 continue;
1663
1664 /* skip strong points */
1665 if ( psh_point_is_strong( point ) )
1666 continue;
1667
1668 y = point->org_u;
1669
1670 /* look up top zones */
1671 table = &blues->normal_top;
1672 blue_count = table->count;
1673 zone = table->zones;
1674
1675 for ( ; blue_count > 0; blue_count--, zone++ )
1676 {
1677 FT_Pos delta = y - zone->org_bottom;
1678
1679
1680 if ( delta < -blues->blue_fuzz )
1681 break;
1682
1683 if ( y <= zone->org_top + blues->blue_fuzz )
1684 if ( blues->no_overshoots || delta <= blues->blue_threshold )
1685 {
1686 point->cur_u = zone->cur_bottom;
1689 }
1690 }
1691
1692 /* look up bottom zones */
1693 table = &blues->normal_bottom;
1694 blue_count = table->count;
1695 zone = table->zones + blue_count - 1;
1696
1697 for ( ; blue_count > 0; blue_count--, zone-- )
1698 {
1699 FT_Pos delta = zone->org_top - y;
1700
1701
1702 if ( delta < -blues->blue_fuzz )
1703 break;
1704
1705 if ( y >= zone->org_bottom - blues->blue_fuzz )
1706 if ( blues->no_overshoots || delta < blues->blue_threshold )
1707 {
1708 point->cur_u = zone->cur_top;
1711 }
1712 }
1713 }
1714 }
1715
1716
1717 /* interpolate strong points with the help of hinted coordinates */
1718 static void
1720 FT_Int dimension )
1721 {
1722 PSH_Dimension dim = &glyph->globals->dimension[dimension];
1723 FT_Fixed scale = dim->scale_mult;
1724
1725 FT_UInt count = glyph->num_points;
1726 PSH_Point point = glyph->points;
1727
1728
1729 for ( ; count > 0; count--, point++ )
1730 {
1731 PSH_Hint hint = point->hint;
1732
1733
1734 if ( hint )
1735 {
1736 FT_Pos delta;
1737
1738
1740 point->cur_u = hint->cur_pos;
1741
1742 else if ( psh_point_is_edge_max( point ) )
1743 point->cur_u = hint->cur_pos + hint->cur_len;
1744
1745 else
1746 {
1747 delta = point->org_u - hint->org_pos;
1748
1749 if ( delta <= 0 )
1750 point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
1751
1752 else if ( delta >= hint->org_len )
1753 point->cur_u = hint->cur_pos + hint->cur_len +
1754 FT_MulFix( delta - hint->org_len, scale );
1755
1756 else /* hint->org_len > 0 */
1757 point->cur_u = hint->cur_pos +
1758 FT_MulDiv( delta, hint->cur_len,
1759 hint->org_len );
1760 }
1762 }
1763 }
1764 }
1765
1766
1767#define PSH_MAX_STRONG_INTERNAL 16
1768
1769 static void
1771 FT_Int dimension )
1772 {
1773
1774#if 1
1775 /* first technique: a point is strong if it is a local extremum */
1776
1777 PSH_Dimension dim = &glyph->globals->dimension[dimension];
1778 FT_Fixed scale = dim->scale_mult;
1779 FT_Memory memory = glyph->memory;
1780
1781 PSH_Point* strongs = NULL;
1783 FT_UInt num_strongs = 0;
1784
1785 PSH_Point points = glyph->points;
1786 PSH_Point points_end = points + glyph->num_points;
1788
1789
1790 /* first count the number of strong points */
1791 for ( point = points; point < points_end; point++ )
1792 {
1793 if ( psh_point_is_strong( point ) )
1794 num_strongs++;
1795 }
1796
1797 if ( num_strongs == 0 ) /* nothing to do here */
1798 return;
1799
1800 /* allocate an array to store a list of points, */
1801 /* stored in increasing org_u order */
1802 if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )
1803 strongs = strongs_0;
1804 else
1805 {
1807
1808
1809 if ( FT_NEW_ARRAY( strongs, num_strongs ) )
1810 return;
1811 }
1812
1813 num_strongs = 0;
1814 for ( point = points; point < points_end; point++ )
1815 {
1817
1818
1819 if ( !psh_point_is_strong( point ) )
1820 continue;
1821
1822 for ( insert = strongs + num_strongs; insert > strongs; insert-- )
1823 {
1824 if ( insert[-1]->org_u <= point->org_u )
1825 break;
1826
1827 insert[0] = insert[-1];
1828 }
1829 insert[0] = point;
1830 num_strongs++;
1831 }
1832
1833 /* now try to interpolate all normal points */
1834 for ( point = points; point < points_end; point++ )
1835 {
1836 if ( psh_point_is_strong( point ) )
1837 continue;
1838
1839 /* sometimes, some local extrema are smooth points */
1840 if ( psh_point_is_smooth( point ) )
1841 {
1842 if ( point->dir_in == PSH_DIR_NONE ||
1843 point->dir_in != point->dir_out )
1844 continue;
1845
1846 if ( !psh_point_is_extremum( point ) &&
1848 continue;
1849
1850 point->flags &= ~PSH_POINT_SMOOTH;
1851 }
1852
1853 /* find best enclosing point coordinates then interpolate */
1854 {
1856 FT_UInt nn;
1857
1858
1859 for ( nn = 0; nn < num_strongs; nn++ )
1860 if ( strongs[nn]->org_u > point->org_u )
1861 break;
1862
1863 if ( nn == 0 ) /* point before the first strong point */
1864 {
1865 after = strongs[0];
1866
1867 point->cur_u = after->cur_u +
1868 FT_MulFix( point->org_u - after->org_u,
1869 scale );
1870 }
1871 else
1872 {
1873 before = strongs[nn - 1];
1874
1875 for ( nn = num_strongs; nn > 0; nn-- )
1876 if ( strongs[nn - 1]->org_u < point->org_u )
1877 break;
1878
1879 if ( nn == num_strongs ) /* point is after last strong point */
1880 {
1881 before = strongs[nn - 1];
1882
1883 point->cur_u = before->cur_u +
1884 FT_MulFix( point->org_u - before->org_u,
1885 scale );
1886 }
1887 else
1888 {
1889 FT_Pos u;
1890
1891
1892 after = strongs[nn];
1893
1894 /* now interpolate point between before and after */
1895 u = point->org_u;
1896
1897 if ( u == before->org_u )
1898 point->cur_u = before->cur_u;
1899
1900 else if ( u == after->org_u )
1901 point->cur_u = after->cur_u;
1902
1903 else
1904 point->cur_u = before->cur_u +
1905 FT_MulDiv( u - before->org_u,
1906 after->cur_u - before->cur_u,
1907 after->org_u - before->org_u );
1908 }
1909 }
1911 }
1912 }
1913
1914 if ( strongs != strongs_0 )
1915 FT_FREE( strongs );
1916
1917#endif /* 1 */
1918
1919 }
1920
1921
1922 /* interpolate other points */
1923 static void
1925 FT_Int dimension )
1926 {
1927 PSH_Dimension dim = &glyph->globals->dimension[dimension];
1928 FT_Fixed scale = dim->scale_mult;
1929 FT_Fixed delta = dim->scale_delta;
1930 PSH_Contour contour = glyph->contours;
1931 FT_UInt num_contours = glyph->num_contours;
1932
1933
1934 for ( ; num_contours > 0; num_contours--, contour++ )
1935 {
1936 PSH_Point start = contour->start;
1938 FT_UInt fit_count;
1939
1940
1941 /* count the number of strong points in this contour */
1942 next = start + contour->count;
1943 fit_count = 0;
1944 first = NULL;
1945
1946 for ( point = start; point < next; point++ )
1947 if ( psh_point_is_fitted( point ) )
1948 {
1949 if ( !first )
1950 first = point;
1951
1952 fit_count++;
1953 }
1954
1955 /* if there are less than 2 fitted points in the contour, we */
1956 /* simply scale and eventually translate the contour points */
1957 if ( fit_count < 2 )
1958 {
1959 if ( fit_count == 1 )
1960 delta = first->cur_u - FT_MulFix( first->org_u, scale );
1961
1962 for ( point = start; point < next; point++ )
1963 if ( point != first )
1964 point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
1965
1966 goto Next_Contour;
1967 }
1968
1969 /* there are more than 2 strong points in this contour; we */
1970 /* need to interpolate weak points between them */
1971 start = first;
1972 do
1973 {
1974 /* skip consecutive fitted points */
1975 for (;;)
1976 {
1977 next = first->next;
1978 if ( next == start )
1979 goto Next_Contour;
1980
1981 if ( !psh_point_is_fitted( next ) )
1982 break;
1983
1984 first = next;
1985 }
1986
1987 /* find next fitted point after unfitted one */
1988 for (;;)
1989 {
1990 next = next->next;
1991 if ( psh_point_is_fitted( next ) )
1992 break;
1993 }
1994
1995 /* now interpolate between them */
1996 {
1997 FT_Pos org_a, org_ab, cur_a, cur_ab;
1998 FT_Pos org_c, org_ac, cur_c;
1999 FT_Fixed scale_ab;
2000
2001
2002 if ( first->org_u <= next->org_u )
2003 {
2004 org_a = first->org_u;
2005 cur_a = first->cur_u;
2006 org_ab = next->org_u - org_a;
2007 cur_ab = next->cur_u - cur_a;
2008 }
2009 else
2010 {
2011 org_a = next->org_u;
2012 cur_a = next->cur_u;
2013 org_ab = first->org_u - org_a;
2014 cur_ab = first->cur_u - cur_a;
2015 }
2016
2017 scale_ab = 0x10000L;
2018 if ( org_ab > 0 )
2019 scale_ab = FT_DivFix( cur_ab, org_ab );
2020
2021 point = first->next;
2022 do
2023 {
2024 org_c = point->org_u;
2025 org_ac = org_c - org_a;
2026
2027 if ( org_ac <= 0 )
2028 {
2029 /* on the left of the interpolation zone */
2030 cur_c = cur_a + FT_MulFix( org_ac, scale );
2031 }
2032 else if ( org_ac >= org_ab )
2033 {
2034 /* on the right on the interpolation zone */
2035 cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
2036 }
2037 else
2038 {
2039 /* within the interpolation zone */
2040 cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
2041 }
2042
2043 point->cur_u = cur_c;
2044
2045 point = point->next;
2046
2047 } while ( point != next );
2048 }
2049
2050 /* keep going until all points in the contours have been processed */
2051 first = next;
2052
2053 } while ( first != start );
2054
2055 Next_Contour:
2056 ;
2057 }
2058 }
2059
2060
2061 /*************************************************************************/
2062 /*************************************************************************/
2063 /***** *****/
2064 /***** HIGH-LEVEL INTERFACE *****/
2065 /***** *****/
2066 /*************************************************************************/
2067 /*************************************************************************/
2068
2069 FT_Error
2072 PSH_Globals globals,
2073 FT_Render_Mode hint_mode )
2074 {
2075 PSH_GlyphRec glyphrec;
2076 PSH_Glyph glyph = &glyphrec;
2078#ifdef DEBUG_HINTER
2080#endif
2081 FT_Int dimension;
2082
2083
2084 /* something to do? */
2085 if ( outline->n_points == 0 || outline->n_contours == 0 )
2086 return FT_Err_Ok;
2087
2088#ifdef DEBUG_HINTER
2089
2090 memory = globals->memory;
2091
2092 if ( ps_debug_glyph )
2093 {
2094 psh_glyph_done( ps_debug_glyph );
2095 FT_FREE( ps_debug_glyph );
2096 }
2097
2098 if ( FT_NEW( glyph ) )
2099 return error;
2100
2101 ps_debug_glyph = glyph;
2102
2103#endif /* DEBUG_HINTER */
2104
2105 error = psh_glyph_init( glyph, outline, ps_hints, globals );
2106 if ( error )
2107 goto Exit;
2108
2109 /* try to optimize the y_scale so that the top of non-capital letters
2110 * is aligned on a pixel boundary whenever possible
2111 */
2112 {
2113 PSH_Dimension dim_x = &glyph->globals->dimension[0];
2114 PSH_Dimension dim_y = &glyph->globals->dimension[1];
2115
2116 FT_Fixed x_scale = dim_x->scale_mult;
2117 FT_Fixed y_scale = dim_y->scale_mult;
2118
2119 FT_Fixed old_x_scale = x_scale;
2120 FT_Fixed old_y_scale = y_scale;
2121
2122 FT_Fixed scaled;
2123 FT_Fixed fitted;
2124
2125 FT_Bool rescale = FALSE;
2126
2127
2128 scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
2129 fitted = FT_PIX_ROUND( scaled );
2130
2131 if ( fitted != 0 && scaled != fitted )
2132 {
2133 rescale = TRUE;
2134
2135 y_scale = FT_MulDiv( y_scale, fitted, scaled );
2136
2137 if ( fitted < scaled )
2138 x_scale -= x_scale / 50;
2139
2140 psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
2141 }
2142
2143 glyph->do_horz_hints = 1;
2144 glyph->do_vert_hints = 1;
2145
2146 glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
2147 hint_mode == FT_RENDER_MODE_LCD );
2148
2149 glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
2150 hint_mode == FT_RENDER_MODE_LCD_V );
2151
2152 glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
2153
2154 for ( dimension = 0; dimension < 2; dimension++ )
2155 {
2156 /* load outline coordinates into glyph */
2157 psh_glyph_load_points( glyph, dimension );
2158
2159 /* compute local extrema */
2161
2162 /* compute aligned stem/hints positions */
2163 psh_hint_table_align_hints( &glyph->hint_tables[dimension],
2164 glyph->globals,
2165 dimension,
2166 glyph );
2167
2168 /* find strong points, align them, then interpolate others */
2169 psh_glyph_find_strong_points( glyph, dimension );
2170 if ( dimension == 1 )
2171 psh_glyph_find_blue_points( &globals->blues, glyph );
2172 psh_glyph_interpolate_strong_points( glyph, dimension );
2173 psh_glyph_interpolate_normal_points( glyph, dimension );
2174 psh_glyph_interpolate_other_points( glyph, dimension );
2175
2176 /* save hinted coordinates back to outline */
2177 psh_glyph_save_points( glyph, dimension );
2178
2179 if ( rescale )
2181 old_x_scale, old_y_scale, 0, 0 );
2182 }
2183 }
2184
2185 Exit:
2186
2187#ifndef DEBUG_HINTER
2188 psh_glyph_done( glyph );
2189#endif
2190
2191 return error;
2192 }
2193
2194
2195/* END */
_STLP_MOVE_TO_STD_NAMESPACE void sort(_RandomAccessIter __first, _RandomAccessIter __last)
Definition: _algo.c:993
#define read
Definition: acwin.h:96
#define write
Definition: acwin.h:97
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
unsigned char
Definition: typeof.h:29
r parent
Definition: btrfs.c:3010
int align(int length, int align)
Definition: dsound8.c:36
POINTL point
Definition: edittest.c:50
#define printf
Definition: freeldr.h:97
enum FT_Render_Mode_ FT_Render_Mode
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:608
@ FT_RENDER_MODE_MONO
Definition: freetype.h:3236
@ FT_RENDER_MODE_LIGHT
Definition: freetype.h:3235
@ FT_RENDER_MODE_LCD_V
Definition: freetype.h:3238
@ FT_RENDER_MODE_LCD
Definition: freetype.h:3237
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:416
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:509
FT_Vector * vec
Definition: ftbbox.c:448
return FT_Err_Ok
Definition: ftbbox.c:511
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_TRACE0(varformat)
Definition: ftdebug.h:157
#define FT_CURVE_TAG_ON
Definition: ftimage.h:453
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:333
#define FT_NEW(ptr)
Definition: ftmemory.h:331
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define FT_ABS(a)
Definition: ftobjs.h:74
#define FT_PIX_FLOOR(x)
Definition: ftobjs.h:92
#define FT_MIN(a, b)
Definition: ftobjs.h:71
#define FT_PIX_ROUND(x)
Definition: ftobjs.h:93
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
signed char FT_Char
Definition: fttypes.h:143
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned char FT_Byte
Definition: fttypes.h:154
signed long FT_Fixed
Definition: fttypes.h:288
int FT_Error
Definition: fttypes.h:300
unsigned int FT_UInt
Definition: fttypes.h:231
#define FT_BOOL(x)
Definition: fttypes.h:578
signed int FT_Int
Definition: fttypes.h:220
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLenum GLint GLuint mask
Definition: glext.h:6028
GLint limit
Definition: glext.h:10326
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLsizei const GLfloat * points
Definition: glext.h:8112
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
const char cursor[]
Definition: icontest.c:13
typedefFT_BEGIN_HEADER struct PSH_GlobalsRec_ * PSH_Globals
Definition: pshints.h:41
#define d
Definition: ke_i.h:81
GLint dy
Definition: linetemp.h:97
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
#define error(str)
Definition: mkdosfs.c:1605
const char * tags[7 *8]
Definition: apphelp.c:216
static char memory[1024 *256]
Definition: process.c:116
DWORD zone
Definition: sec_mgr.c:1754
static void psh_hint_table_record_mask(PSH_Hint_Table table, PS_Mask hint_mask)
Definition: pshalgo.c:143
#define psh_corner_is_flat
Definition: pshalgo.c:919
static void psh_hint_table_activate_mask(PSH_Hint_Table table, PS_Mask hint_mask)
Definition: pshalgo.c:244
static void psh_glyph_interpolate_other_points(PSH_Glyph glyph, FT_Int dimension)
Definition: pshalgo.c:1924
static void psh_glyph_compute_extrema(PSH_Glyph glyph)
Definition: pshalgo.c:1289
#define PSH_STRONG_THRESHOLD
Definition: pshalgo.c:1557
static void psh_hint_align(PSH_Hint hint, PSH_Globals globals, FT_Int dimension, PSH_Glyph glyph)
Definition: pshalgo.c:437
static int psh_compute_dir(FT_Pos dx, FT_Pos dy)
Definition: pshalgo.c:1054
static FT_Int psh_hint_overlap(PSH_Hint hint1, PSH_Hint hint2)
Definition: pshalgo.c:53
#define PSH_STRONG_THRESHOLD_MAXIMUM
Definition: pshalgo.c:1560
static void psh_glyph_interpolate_strong_points(PSH_Glyph glyph, FT_Int dimension)
Definition: pshalgo.c:1719
static void psh_glyph_find_strong_points(PSH_Glyph glyph, FT_Int dimension)
Definition: pshalgo.c:1565
FT_Error ps_hints_apply(PS_Hints ps_hints, FT_Outline *outline, PSH_Globals globals, FT_Render_Mode hint_mode)
Definition: pshalgo.c:2070
static FT_Pos psh_dimension_quantize_len(PSH_Dimension dim, FT_Pos len, FT_Bool do_snapping)
Definition: pshalgo.c:344
static void psh_glyph_find_blue_points(PSH_Blues blues, PSH_Glyph glyph)
Definition: pshalgo.c:1644
static void psh_glyph_save_points(PSH_Glyph glyph, FT_Int dimension)
Definition: pshalgo.c:1115
static void psh_glyph_done(PSH_Glyph glyph)
Definition: pshalgo.c:1035
static FT_Error psh_hint_table_init(PSH_Hint_Table table, PS_Hint_Table hints, PS_Mask_Table hint_masks, PS_Mask_Table counter_masks, FT_Memory memory)
Definition: pshalgo.c:171
#define PSH_MAX_STRONG_INTERNAL
Definition: pshalgo.c:1767
#define psh_corner_orientation
Definition: pshalgo.c:920
static void psh_glyph_load_points(PSH_Glyph glyph, FT_Int dimension)
Definition: pshalgo.c:1081
static void psh_hint_table_deactivate(PSH_Hint_Table table)
Definition: pshalgo.c:80
static void psh_hint_table_record(PSH_Hint_Table table, FT_UInt idx)
Definition: pshalgo.c:96
static void psh_hint_table_find_strong_points(PSH_Hint_Table table, PSH_Point point, FT_UInt count, FT_Int threshold, FT_Int major_dir)
Definition: pshalgo.c:1412
static void psh_hint_table_align_hints(PSH_Hint_Table table, PSH_Globals globals, FT_Int dimension, PSH_Glyph glyph)
Definition: pshalgo.c:846
static void psh_glyph_compute_inflections(PSH_Glyph glyph)
Definition: pshalgo.c:927
static void psh_hint_table_done(PSH_Hint_Table table, FT_Memory memory)
Definition: pshalgo.c:63
static void psh_glyph_interpolate_normal_points(PSH_Glyph glyph, FT_Int dimension)
Definition: pshalgo.c:1770
static FT_Fixed psh_hint_snap_stem_side_delta(FT_Fixed pos, FT_Fixed len)
Definition: pshalgo.c:422
static FT_Error psh_glyph_init(PSH_Glyph glyph, FT_Outline *outline, PS_Hints ps_hints, PSH_Globals globals)
Definition: pshalgo.c:1155
#define PSH_POINT_POSITIVE
Definition: pshalgo.h:133
#define psh_point_is_strong(p)
Definition: pshalgo.h:139
#define psh_hint_deactivate(x)
Definition: pshalgo.h:46
#define psh_point_set_inflex(p)
Definition: pshalgo.h:126
#define psh_point_is_inflex(p)
Definition: pshalgo.h:122
typedefFT_BEGIN_HEADER struct PSH_HintRec_ * PSH_Hint
Definition: pshalgo.h:31
#define psh_hint_is_active(x)
Definition: pshalgo.h:41
#define PSH_POINT_OFF
Definition: pshalgo.h:115
#define PSH_DIR_VERTICAL
Definition: pshalgo.h:106
#define psh_point_is_edge_max(p)
Definition: pshalgo.h:145
#define psh_hint_activate(x)
Definition: pshalgo.h:45
#define psh_point_is_smooth(p)
Definition: pshalgo.h:120
#define psh_point_is_extremum(p)
Definition: pshalgo.h:141
#define psh_point_set_negative(p)
Definition: pshalgo.h:151
#define psh_point_set_strong(p)
Definition: pshalgo.h:147
#define PSH_POINT_EDGE_MIN
Definition: pshalgo.h:135
#define psh_point_is_edge_min(p)
Definition: pshalgo.h:144
#define PSH_DIR_COMPARE(d1, d2)
Definition: pshalgo.h:108
#define psh_point_set_extremum(p)
Definition: pshalgo.h:149
#define psh_hint_set_fitted(x)
Definition: pshalgo.h:47
#define psh_point_set_positive(p)
Definition: pshalgo.h:150
#define psh_hint_is_fitted(x)
Definition: pshalgo.h:43
@ PSH_DIR_LEFT
Definition: pshalgo.h:101
@ PSH_DIR_UP
Definition: pshalgo.h:99
@ PSH_DIR_RIGHT
Definition: pshalgo.h:102
@ PSH_DIR_DOWN
Definition: pshalgo.h:100
@ PSH_DIR_NONE
Definition: pshalgo.h:98
#define PSH_POINT_NEGATIVE
Definition: pshalgo.h:134
#define psh_point_set_fitted(p)
Definition: pshalgo.h:148
#define psh_point_is_fitted(p)
Definition: pshalgo.h:140
#define PSH_POINT_EDGE_MAX
Definition: pshalgo.h:136
#define PSH_POINT_SMOOTH
Definition: pshalgo.h:116
#define PSH_DIR_HORIZONTAL
Definition: pshalgo.h:105
psh_blues_snap_stem(PSH_Blues blues, FT_Int stem_top, FT_Int stem_bot, PSH_Alignment alignment)
Definition: pshglob.c:548
psh_globals_set_scale(PSH_Globals globals, FT_Fixed x_scale, FT_Fixed y_scale, FT_Fixed x_delta, FT_Fixed y_delta)
Definition: pshglob.c:754
#define PSH_BLUE_ALIGN_BOT
Definition: pshglob.h:146
#define PSH_BLUE_ALIGN_NONE
Definition: pshglob.h:144
#define PSH_BLUE_ALIGN_TOP
Definition: pshglob.h:145
typedefFT_BEGIN_HEADER struct PS_HintRec_ * PS_Hint
Definition: pshrec.h:52
static unsigned __int64 next
Definition: rand_nt.c:6
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
static void Exit(void)
Definition: sock.c:1330
FT_Vector * points
Definition: ftimage.h:339
char * tags
Definition: ftimage.h:340
FT_Pos x
Definition: ftimage.h:76
FT_Pos y
Definition: ftimage.h:77
FT_Int blue_fuzz
Definition: pshglob.h:126
FT_Bool no_overshoots
Definition: pshglob.h:127
PSH_Blue_TableRec normal_top
Definition: pshglob.h:118
PSH_Blue_TableRec normal_bottom
Definition: pshglob.h:119
FT_UInt count
Definition: pshalgo.h:184
PSH_Point start
Definition: pshalgo.h:183
FT_Fixed scale_mult
Definition: pshglob.h:85
FT_Fixed scale_delta
Definition: pshglob.h:86
PSH_WidthsRec stdw
Definition: pshglob.h:84
PSH_Point points
Definition: pshalgo.h:194
FT_Memory memory
Definition: pshalgo.h:197
FT_UInt num_points
Definition: pshalgo.h:191
FT_UInt num_contours
Definition: pshalgo.h:192
FT_Outline * outline
Definition: pshalgo.h:198
FT_Bool do_vert_snapping
Definition: pshalgo.h:209
FT_Bool do_horz_hints
Definition: pshalgo.h:206
FT_Bool do_stem_adjust
Definition: pshalgo.h:210
FT_Bool do_vert_hints
Definition: pshalgo.h:207
PSH_Contour contours
Definition: pshalgo.h:195
FT_Bool do_horz_snapping
Definition: pshalgo.h:208
PSH_Globals globals
Definition: pshalgo.h:199
PSH_Hint_TableRec hint_tables[2]
Definition: pshalgo.h:200
FT_Pos cur
Definition: pshglob.h:67
PSH_WidthRec widths[PS_GLOBALS_MAX_STD_WIDTHS]
Definition: pshglob.h:77
PS_Mask_TableRec masks
Definition: pshrec.h:118
PS_Mask_TableRec counters
Definition: pshrec.h:119
PS_Hint_TableRec hints
Definition: pshrec.h:117
PS_DimensionRec dimension[2]
Definition: pshrec.h:133
FT_UInt num_bits
Definition: pshrec.h:96
FT_Byte * bytes
Definition: pshrec.h:98
PS_Mask masks
Definition: pshrec.h:109
FT_UInt num_masks
Definition: pshrec.h:107
Definition: mesh.c:5330
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx movl TEMP incl eax andl eax ecx incl ebx testl eax jnz xchgl ecx incl TEMP esp ecx subl ebx pushl ecx ecx edx ecx shrl ecx mm0 mm4 mm0 mm4 mm1 mm5 mm1 mm5 mm2 mm6 mm2 mm6 mm3 mm7 mm3 mm7 paddd mm0 paddd mm4 paddd mm0 paddd mm4 paddd mm0 paddd mm4 movq mm1 movq mm5 psrlq mm1 psrlq mm5 paddd mm0 paddd mm4 psrad mm0 psrad mm4 packssdw mm0 packssdw mm4 mm1 punpckldq mm0 pand mm1 pand mm0 por mm1 movq edi esi edx edi decl ecx jnz popl ecx andl ecx jecxz mm0 mm0 mm1 mm1 mm2 mm2 mm3 mm3 paddd mm0 paddd mm0 paddd mm0 movq mm1 psrlq mm1 paddd mm0 psrad mm0 packssdw mm0 movd eax movw ax
Definition: synth_sse3d.h:180
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
__inline int after(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2395
DWORD hint
Definition: vfdcmd.c:88
static int insert
Definition: xmllint.c:138