Lines 22-30
Link Here
|
22 |
#include <ft2build.h> |
22 |
#include <ft2build.h> |
23 |
#include "ahhint.h" |
23 |
#include "ahhint.h" |
24 |
#include "ahglyph.h" |
24 |
#include "ahglyph.h" |
25 |
#include "ahangles.h" |
|
|
26 |
#include "aherrors.h" |
25 |
#include "aherrors.h" |
27 |
#include FT_OUTLINE_H |
26 |
#include FT_OUTLINE_H |
|
|
27 |
#include FT_TRUETYPE_TABLES_H |
28 |
|
28 |
|
29 |
|
29 |
|
30 |
#define FACE_GLOBALS( face ) ( (AH_Face_Globals)(face)->autohint.data ) |
30 |
#define FACE_GLOBALS( face ) ( (AH_Face_Globals)(face)->autohint.data ) |
Lines 112-118
Link Here
|
112 |
|
112 |
|
113 |
if ( !hinter->do_stem_adjust ) |
113 |
if ( !hinter->do_stem_adjust ) |
114 |
{ |
114 |
{ |
115 |
/* leave stem widths unchanged */ |
115 |
if ( dist < 48 ) |
|
|
116 |
dist += ( 48 - dist )/2 ; |
116 |
} |
117 |
} |
117 |
else if ( ( vertical && !hinter->do_vert_snapping ) || |
118 |
else if ( ( vertical && !hinter->do_vert_snapping ) || |
118 |
( !vertical && !hinter->do_horz_snapping ) ) |
119 |
( !vertical && !hinter->do_horz_snapping ) ) |
Lines 120-125
Link Here
|
120 |
/* smooth hinting process: very lightly quantize the stem width */ |
121 |
/* smooth hinting process: very lightly quantize the stem width */ |
121 |
/* */ |
122 |
/* */ |
122 |
|
123 |
|
|
|
124 |
#if 0 |
123 |
/* leave the widths of serifs alone */ |
125 |
/* leave the widths of serifs alone */ |
124 |
|
126 |
|
125 |
if ( ( stem_flags & AH_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) ) |
127 |
if ( ( stem_flags & AH_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) ) |
Lines 132-155
Link Here
|
132 |
} |
134 |
} |
133 |
else if ( dist < 56 ) |
135 |
else if ( dist < 56 ) |
134 |
dist = 56; |
136 |
dist = 56; |
|
|
137 |
#endif |
135 |
|
138 |
|
136 |
{ |
139 |
{ |
137 |
FT_Pos delta = dist - globals->stds[vertical]; |
140 |
FT_Pos delta; |
138 |
|
141 |
|
139 |
|
142 |
|
140 |
if ( delta < 0 ) |
143 |
if ( ( vertical && globals->num_heights > 0 ) || |
141 |
delta = -delta; |
144 |
( !vertical && globals->num_widths > 0 ) ) |
142 |
|
|
|
143 |
if ( delta < 40 ) |
144 |
{ |
145 |
{ |
145 |
dist = globals->stds[vertical]; |
146 |
delta = dist - globals->stds[vertical]; |
146 |
if ( dist < 48 ) |
147 |
|
147 |
dist = 48; |
148 |
if ( delta < 0 ) |
|
|
149 |
delta = -delta; |
148 |
|
150 |
|
149 |
goto Done_Width; |
151 |
if ( delta < 40 ) |
|
|
152 |
{ |
153 |
dist = globals->stds[vertical]; |
154 |
if ( dist < 48 ) |
155 |
dist = 48; |
156 |
|
157 |
goto Done_Width; |
158 |
} |
150 |
} |
159 |
} |
151 |
|
160 |
|
152 |
if ( dist < 3 * 64 ) |
161 |
if ( dist < 54 ) |
|
|
162 |
{ |
163 |
dist += ( 54 - dist )/2 ; |
164 |
} |
165 |
else if ( dist < 3 * 64 ) |
153 |
{ |
166 |
{ |
154 |
delta = dist & 63; |
167 |
delta = dist & 63; |
155 |
dist &= -64; |
168 |
dist &= -64; |
Lines 157-173
Link Here
|
157 |
if ( delta < 10 ) |
170 |
if ( delta < 10 ) |
158 |
dist += delta; |
171 |
dist += delta; |
159 |
|
172 |
|
160 |
else if ( delta < 32 ) |
173 |
else if ( delta < 22 ) |
161 |
dist += 10; |
174 |
dist += 10; |
162 |
|
175 |
|
|
|
176 |
else if ( delta < 42 ) |
177 |
dist += delta; |
178 |
|
163 |
else if ( delta < 54 ) |
179 |
else if ( delta < 54 ) |
164 |
dist += 54; |
180 |
dist += 54; |
165 |
|
181 |
|
166 |
else |
182 |
else |
167 |
dist += delta; |
183 |
dist += delta; |
168 |
} |
184 |
} |
169 |
else |
|
|
170 |
dist = ( dist + 32 ) & -64; |
171 |
} |
185 |
} |
172 |
} |
186 |
} |
173 |
else |
187 |
else |
Lines 409-414
Link Here
|
409 |
serif->pos = base->pos + sign * dist; |
423 |
serif->pos = base->pos + sign * dist; |
410 |
} |
424 |
} |
411 |
|
425 |
|
|
|
426 |
|
427 |
static FT_Pos |
428 |
ah_hint_normal_stem( AH_Hinter hinter, |
429 |
AH_Edge edge, |
430 |
AH_Edge edge2, |
431 |
FT_Pos anchor, |
432 |
FT_Int vertical ) |
433 |
{ |
434 |
FT_Pos org_len, cur_len, org_center; |
435 |
FT_Pos cur_pos1, cur_pos2; |
436 |
FT_Pos d_off1, u_off1, d_off2, u_off2, delta; |
437 |
FT_Pos offset; |
438 |
FT_Pos threshold = 64; |
439 |
|
440 |
|
441 |
if ( !hinter->do_stem_adjust ) |
442 |
{ |
443 |
if ( ( edge->flags & AH_EDGE_ROUND ) && |
444 |
( edge2->flags & AH_EDGE_ROUND ) ) |
445 |
{ |
446 |
if ( vertical ) |
447 |
threshold = 64 - AH_LIGHT_MODE_MAX_HORZ_GAP; |
448 |
else |
449 |
threshold = 64 - AH_LIGHT_MODE_MAX_VERT_GAP; |
450 |
} |
451 |
else |
452 |
{ |
453 |
if ( vertical ) |
454 |
threshold = 64 - AH_LIGHT_MODE_MAX_HORZ_GAP/3; |
455 |
else |
456 |
threshold = 64 - AH_LIGHT_MODE_MAX_VERT_GAP/3; |
457 |
} |
458 |
} |
459 |
|
460 |
org_len = edge2->opos - edge->opos; |
461 |
cur_len = ah_compute_stem_width( hinter, vertical, org_len, |
462 |
edge->flags, edge2->flags ); |
463 |
org_center = ( edge->opos + edge2->opos ) / 2 + anchor; |
464 |
cur_pos1 = org_center - cur_len / 2; |
465 |
cur_pos2 = cur_pos1 + cur_len; |
466 |
d_off1 = cur_pos1 - ( cur_pos1 & -64 ); |
467 |
d_off2 = cur_pos2 - ( cur_pos2 & -64 ); |
468 |
u_off1 = 64 - d_off1; |
469 |
u_off2 = 64 - d_off2; |
470 |
delta = 0; |
471 |
|
472 |
|
473 |
if ( d_off1 == 0 || d_off2 == 0 ) |
474 |
goto Exit; |
475 |
|
476 |
if ( cur_len <= threshold ) |
477 |
{ |
478 |
if ( d_off2 < cur_len ) |
479 |
{ |
480 |
if ( u_off1 <= d_off2 ) |
481 |
delta = u_off1; |
482 |
else |
483 |
delta = -d_off2; |
484 |
} |
485 |
|
486 |
goto Exit; |
487 |
} |
488 |
|
489 |
if ( threshold < 64 ) |
490 |
{ |
491 |
if ( d_off1 >= threshold || u_off1 >= threshold || |
492 |
d_off2 >= threshold || u_off2 >= threshold ) |
493 |
goto Exit; |
494 |
} |
495 |
|
496 |
offset = cur_len % 64; |
497 |
|
498 |
if ( offset < 32 ) |
499 |
{ |
500 |
if ( u_off1 <= offset || d_off2 <= offset ) |
501 |
goto Exit; |
502 |
} |
503 |
else |
504 |
offset = 64 - threshold; |
505 |
|
506 |
d_off1 = threshold - u_off1; |
507 |
u_off1 = u_off1 - offset; |
508 |
u_off2 = threshold - d_off2; |
509 |
d_off2 = d_off2 - offset; |
510 |
|
511 |
if ( d_off1 <= u_off1 ) |
512 |
u_off1 = -d_off1; |
513 |
|
514 |
if ( d_off2 <= u_off2 ) |
515 |
u_off2 = -d_off2; |
516 |
|
517 |
if ( ABS( u_off1 ) <= ABS( u_off2 ) ) |
518 |
delta = u_off1; |
519 |
else |
520 |
delta = u_off2; |
521 |
|
522 |
Exit: |
523 |
#if 1 |
524 |
if ( !hinter->do_stem_adjust ) |
525 |
{ |
526 |
if ( delta > AH_LIGHT_MODE_MAX_DELTA_ABS ) |
527 |
delta = AH_LIGHT_MODE_MAX_DELTA_ABS; |
528 |
else if ( delta < -AH_LIGHT_MODE_MAX_DELTA_ABS ) |
529 |
delta = -AH_LIGHT_MODE_MAX_DELTA_ABS; |
530 |
} |
531 |
#endif |
532 |
|
533 |
cur_pos1 += delta; |
534 |
|
535 |
if ( edge->opos < edge2->opos ) |
536 |
{ |
537 |
edge->pos = cur_pos1; |
538 |
edge2->pos = cur_pos1 + cur_len; |
539 |
} |
540 |
else |
541 |
{ |
542 |
edge->pos = cur_pos1 + cur_len; |
543 |
edge2->pos = cur_pos1; |
544 |
} |
545 |
|
546 |
return delta; |
547 |
} |
548 |
|
412 |
|
549 |
|
413 |
/*************************************************************************/ |
550 |
/*************************************************************************/ |
414 |
/*************************************************************************/ |
551 |
/*************************************************************************/ |
Lines 438-443
Link Here
|
438 |
{ |
575 |
{ |
439 |
AH_Edge edge; |
576 |
AH_Edge edge; |
440 |
AH_Edge anchor = 0; |
577 |
AH_Edge anchor = 0; |
|
|
578 |
FT_Pos delta = 0; |
441 |
int has_serifs = 0; |
579 |
int has_serifs = 0; |
442 |
|
580 |
|
443 |
|
581 |
|
Lines 449-455
Link Here
|
449 |
|
587 |
|
450 |
/* we begin by aligning all stems relative to the blue zone */ |
588 |
/* we begin by aligning all stems relative to the blue zone */ |
451 |
/* if needed -- that's only for horizontal edges */ |
589 |
/* if needed -- that's only for horizontal edges */ |
452 |
if ( dimension ) |
590 |
if ( dimension && hinter->do_blue_hints ) |
453 |
{ |
591 |
{ |
454 |
for ( edge = edges; edge < edge_limit; edge++ ) |
592 |
for ( edge = edges; edge < edge_limit; edge++ ) |
455 |
{ |
593 |
{ |
Lines 486-499
Link Here
|
486 |
ah_align_linked_edge( hinter, edge1, edge2, dimension ); |
624 |
ah_align_linked_edge( hinter, edge1, edge2, dimension ); |
487 |
edge2->flags |= AH_EDGE_DONE; |
625 |
edge2->flags |= AH_EDGE_DONE; |
488 |
} |
626 |
} |
489 |
|
|
|
490 |
if ( !anchor ) |
491 |
anchor = edge; |
492 |
} |
627 |
} |
493 |
} |
628 |
} |
494 |
|
629 |
|
495 |
/* now we will align all stem edges, trying to maintain the */ |
630 |
/* now we will align all stem edges. */ |
496 |
/* relative order of stems in the glyph */ |
|
|
497 |
for ( edge = edges; edge < edge_limit; edge++ ) |
631 |
for ( edge = edges; edge < edge_limit; edge++ ) |
498 |
{ |
632 |
{ |
499 |
AH_EdgeRec* edge2; |
633 |
AH_EdgeRec* edge2; |
Lines 520-525
Link Here
|
520 |
continue; |
654 |
continue; |
521 |
} |
655 |
} |
522 |
|
656 |
|
|
|
657 |
#if 0 |
523 |
if ( !anchor ) |
658 |
if ( !anchor ) |
524 |
{ |
659 |
{ |
525 |
|
660 |
|
Lines 686-691
Link Here
|
686 |
if ( edge > edges && edge->pos < edge[-1].pos ) |
821 |
if ( edge > edges && edge->pos < edge[-1].pos ) |
687 |
edge->pos = edge[-1].pos; |
822 |
edge->pos = edge[-1].pos; |
688 |
} |
823 |
} |
|
|
824 |
#else /* 1 */ |
825 |
|
826 |
if ( !dimension && !anchor ) |
827 |
{ |
828 |
if ( hinter->globals->is_fixedpitch && !hinter->composite ) |
829 |
{ |
830 |
AH_Edge left = edge; |
831 |
AH_Edge right = edge_limit - 1; |
832 |
AH_EdgeRec left1, left2, right1, right2; |
833 |
FT_Pos target, center1, center2; |
834 |
FT_Pos delta1, delta2, d1, d2; |
835 |
|
836 |
|
837 |
while ( right > left && !right->link ) |
838 |
right--; |
839 |
|
840 |
left1 = *left; |
841 |
left2 = *left->link; |
842 |
right1 = *right->link; |
843 |
right2 = *right; |
844 |
|
845 |
delta = ( ( ( hinter->pp2.x + 32 ) & -64 ) - hinter->pp2.x )/2; |
846 |
target = left->opos + ( right->opos - left->opos )/2 + delta - 16; |
847 |
|
848 |
delta1 = delta; |
849 |
delta1 += ah_hint_normal_stem( hinter, left, left->link, |
850 |
delta1, 0 ); |
851 |
|
852 |
if ( left->link != right ) |
853 |
ah_hint_normal_stem( hinter, right->link, right, delta1, 0 ); |
854 |
|
855 |
center1 = left->pos + ( right->pos - left->pos )/2; |
856 |
|
857 |
if ( center1 >= target ) |
858 |
delta2 = delta - 32; |
859 |
else |
860 |
delta2 = delta + 32; |
861 |
|
862 |
delta2 += ah_hint_normal_stem( hinter, &left1, &left2, delta2, 0 ); |
863 |
|
864 |
if ( delta1 != delta2 ) |
865 |
{ |
866 |
if ( left->link != right ) |
867 |
ah_hint_normal_stem( hinter, &right1, &right2, delta2, 0 ); |
868 |
|
869 |
center2 = left1.pos + ( right2.pos - left1.pos )/2; |
870 |
|
871 |
d1 = center1 - target; |
872 |
d2 = center2 - target; |
873 |
|
874 |
if ( ABS( d2 ) < ABS( d1 ) ) |
875 |
{ |
876 |
left->pos = left1.pos; |
877 |
left->link->pos = left2.pos; |
878 |
|
879 |
if ( left->link != right ) |
880 |
{ |
881 |
right->link->pos = right1.pos; |
882 |
right->pos = right2.pos; |
883 |
} |
884 |
|
885 |
delta1 = delta2; |
886 |
} |
887 |
} |
888 |
|
889 |
delta = delta1; |
890 |
right->link->flags |= AH_EDGE_DONE; |
891 |
right->flags |= AH_EDGE_DONE; |
892 |
} |
893 |
else |
894 |
{ |
895 |
delta = ah_hint_normal_stem( hinter, edge, edge2, 0, 0 ); |
896 |
} |
897 |
|
898 |
anchor = edge; |
899 |
} |
900 |
else |
901 |
{ |
902 |
ah_hint_normal_stem( hinter, edge, edge2, |
903 |
delta, dimension ); |
904 |
anchor = edge; |
905 |
} |
906 |
|
907 |
edge->flags |= AH_EDGE_DONE; |
908 |
edge2->flags |= AH_EDGE_DONE; |
909 |
|
910 |
#endif /* 1 */ |
689 |
} |
911 |
} |
690 |
|
912 |
|
691 |
/* make sure that lowercase m's maintain their symmetry */ |
913 |
/* make sure that lowercase m's maintain their symmetry */ |
Lines 704-710
Link Here
|
704 |
/* one pixel higher or lower. */ |
926 |
/* one pixel higher or lower. */ |
705 |
|
927 |
|
706 |
n_edges = edge_limit - edges; |
928 |
n_edges = edge_limit - edges; |
707 |
if ( !dimension && ( n_edges == 6 || n_edges == 12 ) ) |
929 |
if ( hinter->do_blue_hints && |
|
|
930 |
!dimension && ( n_edges == 6 || n_edges == 12 ) ) |
708 |
{ |
931 |
{ |
709 |
AH_EdgeRec *edge1, *edge2, *edge3; |
932 |
AH_EdgeRec *edge1, *edge2, *edge3; |
710 |
FT_Pos dist1, dist2, span, delta; |
933 |
FT_Pos dist1, dist2, span, delta; |
Lines 730-736
Link Here
|
730 |
if ( span < 0 ) |
953 |
if ( span < 0 ) |
731 |
span = -span; |
954 |
span = -span; |
732 |
|
955 |
|
733 |
if ( span < 8 ) |
956 |
if ( edge1->link == edge1 + 1 && |
|
|
957 |
edge2->link == edge2 + 1 && |
958 |
edge3->link == edge3 + 1 && span < 8 ) |
734 |
{ |
959 |
{ |
735 |
delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); |
960 |
delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); |
736 |
edge3->pos -= delta; |
961 |
edge3->pos -= delta; |
Lines 761-785
Link Here
|
761 |
continue; |
986 |
continue; |
762 |
|
987 |
|
763 |
if ( edge->serif ) |
988 |
if ( edge->serif ) |
764 |
ah_align_serif_edge( hinter, edge->serif, edge, dimension ); |
|
|
765 |
else if ( !anchor ) |
766 |
{ |
989 |
{ |
767 |
edge->pos = ( edge->opos + 32 ) & -64; |
990 |
ah_align_serif_edge( hinter, edge->serif, edge, dimension ); |
768 |
anchor = edge; |
991 |
edge->flags |= AH_EDGE_DONE; |
|
|
992 |
has_serifs--; |
769 |
} |
993 |
} |
770 |
else |
994 |
} |
771 |
edge->pos = anchor->pos + |
995 |
|
772 |
( ( edge->opos-anchor->opos + 32 ) & -64 ); |
996 |
if ( !has_serifs ) |
|
|
997 |
goto Next_Dimension; |
998 |
|
999 |
for ( edge = edges; edge < edge_limit; edge++ ) |
1000 |
{ |
1001 |
AH_Edge before, after; |
773 |
|
1002 |
|
774 |
edge->flags |= AH_EDGE_DONE; |
|
|
775 |
|
1003 |
|
776 |
if ( edge > edges && edge->pos < edge[-1].pos ) |
1004 |
if ( edge->flags & AH_EDGE_DONE ) |
777 |
edge->pos = edge[-1].pos; |
1005 |
continue; |
|
|
1006 |
|
1007 |
before = after = edge; |
1008 |
|
1009 |
while ( --before >= edges ) |
1010 |
if ( before->flags & AH_EDGE_DONE ) |
1011 |
break; |
1012 |
|
1013 |
while ( ++after < edge_limit ) |
1014 |
if ( after->flags & AH_EDGE_DONE ) |
1015 |
break; |
1016 |
|
1017 |
if ( before >= edges || after < edge_limit ) |
1018 |
{ |
1019 |
if ( before < edges ) |
1020 |
edge->pos = edge->opos + ( after->pos - after->opos ); |
1021 |
|
1022 |
else if ( after >= edge_limit ) |
1023 |
edge->pos = edge->opos + ( before->pos - before->opos ); |
778 |
|
1024 |
|
779 |
if ( edge + 1 < edge_limit && |
1025 |
else |
780 |
edge[1].flags & AH_EDGE_DONE && |
1026 |
edge->pos = before->pos + |
781 |
edge->pos > edge[1].pos ) |
1027 |
FT_MulDiv( edge->fpos - before->fpos, |
782 |
edge->pos = edge[1].pos; |
1028 |
after->pos - before->pos, |
|
|
1029 |
after->fpos - before->fpos ); |
1030 |
} |
783 |
} |
1031 |
} |
784 |
|
1032 |
|
785 |
Next_Dimension: |
1033 |
Next_Dimension: |
Lines 806-815
Link Here
|
806 |
AH_Edge edges; |
1054 |
AH_Edge edges; |
807 |
AH_Edge edge_limit; |
1055 |
AH_Edge edge_limit; |
808 |
FT_Int dimension; |
1056 |
FT_Int dimension; |
|
|
1057 |
FT_Bool snapping; |
809 |
|
1058 |
|
810 |
|
1059 |
|
811 |
edges = outline->horz_edges; |
1060 |
edges = outline->horz_edges; |
812 |
edge_limit = edges + outline->num_hedges; |
1061 |
edge_limit = edges + outline->num_hedges; |
|
|
1062 |
snapping = hinter->do_vert_snapping; |
813 |
|
1063 |
|
814 |
for ( dimension = 1; dimension >= 0; dimension-- ) |
1064 |
for ( dimension = 1; dimension >= 0; dimension-- ) |
815 |
{ |
1065 |
{ |
Lines 821-827
Link Here
|
821 |
{ |
1071 |
{ |
822 |
/* move the points of each segment */ |
1072 |
/* move the points of each segment */ |
823 |
/* in each edge to the edge's position */ |
1073 |
/* in each edge to the edge's position */ |
824 |
AH_Segment seg = edge->first; |
1074 |
AH_Segment seg = edge->first; |
|
|
1075 |
FT_Pos delta = edge->pos - edge->opos; |
825 |
|
1076 |
|
826 |
|
1077 |
|
827 |
do |
1078 |
do |
Lines 829-851
Link Here
|
829 |
AH_Point point = seg->first; |
1080 |
AH_Point point = seg->first; |
830 |
|
1081 |
|
831 |
|
1082 |
|
832 |
for (;;) |
1083 |
if ( snapping ) |
833 |
{ |
1084 |
{ |
834 |
if ( dimension ) |
1085 |
for (;;) |
835 |
{ |
1086 |
{ |
836 |
point->y = edge->pos; |
1087 |
if ( dimension ) |
837 |
point->flags |= AH_FLAG_TOUCH_Y; |
1088 |
{ |
|
|
1089 |
point->y = edge->pos; |
1090 |
point->flags |= AH_FLAG_TOUCH_Y; |
1091 |
} |
1092 |
else |
1093 |
{ |
1094 |
point->x = edge->pos; |
1095 |
point->flags |= AH_FLAG_TOUCH_X; |
1096 |
} |
1097 |
|
1098 |
if ( point == seg->last ) |
1099 |
break; |
1100 |
|
1101 |
point = point->next; |
838 |
} |
1102 |
} |
839 |
else |
1103 |
} |
|
|
1104 |
else |
1105 |
{ |
1106 |
for (;;) |
840 |
{ |
1107 |
{ |
841 |
point->x = edge->pos; |
1108 |
if ( dimension ) |
842 |
point->flags |= AH_FLAG_TOUCH_X; |
1109 |
{ |
843 |
} |
1110 |
point->y += delta; |
|
|
1111 |
point->flags |= AH_FLAG_TOUCH_Y; |
1112 |
} |
1113 |
else |
1114 |
{ |
1115 |
point->x += delta; |
1116 |
point->flags |= AH_FLAG_TOUCH_X; |
1117 |
} |
844 |
|
1118 |
|
845 |
if ( point == seg->last ) |
1119 |
if ( point == seg->last ) |
846 |
break; |
1120 |
break; |
847 |
|
1121 |
|
848 |
point = point->next; |
1122 |
point = point->next; |
|
|
1123 |
} |
849 |
} |
1124 |
} |
850 |
|
1125 |
|
851 |
seg = seg->edge_next; |
1126 |
seg = seg->edge_next; |
Lines 855-860
Link Here
|
855 |
|
1130 |
|
856 |
edges = outline->vert_edges; |
1131 |
edges = outline->vert_edges; |
857 |
edge_limit = edges + outline->num_vedges; |
1132 |
edge_limit = edges + outline->num_vedges; |
|
|
1133 |
snapping = hinter->do_horz_snapping; |
858 |
} |
1134 |
} |
859 |
} |
1135 |
} |
860 |
|
1136 |
|
Lines 871-876
Link Here
|
871 |
AH_Point points; |
1147 |
AH_Point points; |
872 |
AH_Point point_limit; |
1148 |
AH_Point point_limit; |
873 |
AH_Flags touch_flag; |
1149 |
AH_Flags touch_flag; |
|
|
1150 |
AH_Flags strong_flag; |
874 |
|
1151 |
|
875 |
|
1152 |
|
876 |
points = outline->points; |
1153 |
points = outline->points; |
Lines 879-884
Link Here
|
879 |
edges = outline->horz_edges; |
1156 |
edges = outline->horz_edges; |
880 |
edge_limit = edges + outline->num_hedges; |
1157 |
edge_limit = edges + outline->num_hedges; |
881 |
touch_flag = AH_FLAG_TOUCH_Y; |
1158 |
touch_flag = AH_FLAG_TOUCH_Y; |
|
|
1159 |
strong_flag = AH_FLAG_STRONG_Y; |
882 |
|
1160 |
|
883 |
for ( dimension = 1; dimension >= 0; dimension-- ) |
1161 |
for ( dimension = 1; dimension >= 0; dimension-- ) |
884 |
{ |
1162 |
{ |
Lines 899-906
Link Here
|
899 |
#ifndef AH_OPTION_NO_WEAK_INTERPOLATION |
1177 |
#ifndef AH_OPTION_NO_WEAK_INTERPOLATION |
900 |
/* if this point is candidate to weak interpolation, we will */ |
1178 |
/* if this point is candidate to weak interpolation, we will */ |
901 |
/* interpolate it after all strong points have been processed */ |
1179 |
/* interpolate it after all strong points have been processed */ |
902 |
if ( ( point->flags & AH_FLAG_WEAK_INTERPOLATION ) && |
1180 |
if ( !( point->flags & strong_flag ) ) |
903 |
!( point->flags & AH_FLAG_INFLECTION ) ) |
|
|
904 |
continue; |
1181 |
continue; |
905 |
#endif |
1182 |
#endif |
906 |
|
1183 |
|
Lines 1034-1039
Link Here
|
1034 |
edges = outline->vert_edges; |
1311 |
edges = outline->vert_edges; |
1035 |
edge_limit = edges + outline->num_vedges; |
1312 |
edge_limit = edges + outline->num_vedges; |
1036 |
touch_flag = AH_FLAG_TOUCH_X; |
1313 |
touch_flag = AH_FLAG_TOUCH_X; |
|
|
1314 |
strong_flag = AH_FLAG_STRONG_X; |
1037 |
} |
1315 |
} |
1038 |
} |
1316 |
} |
1039 |
|
1317 |
|
Lines 1234-1243
Link Here
|
1234 |
|
1512 |
|
1235 |
|
1513 |
|
1236 |
FT_LOCAL_DEF( void ) |
1514 |
FT_LOCAL_DEF( void ) |
1237 |
ah_hinter_align_points( AH_Hinter hinter ) |
1515 |
ah_hinter_align_normal_points( AH_Hinter hinter ) |
1238 |
{ |
1516 |
{ |
1239 |
ah_hinter_align_edge_points( hinter ); |
|
|
1240 |
|
1241 |
#ifndef AH_OPTION_NO_STRONG_INTERPOLATION |
1517 |
#ifndef AH_OPTION_NO_STRONG_INTERPOLATION |
1242 |
ah_hinter_align_strong_points( hinter ); |
1518 |
ah_hinter_align_strong_points( hinter ); |
1243 |
#endif |
1519 |
#endif |
Lines 1263-1279
Link Here
|
1263 |
static void |
1539 |
static void |
1264 |
ah_hinter_scale_globals( AH_Hinter hinter, |
1540 |
ah_hinter_scale_globals( AH_Hinter hinter, |
1265 |
FT_Fixed x_scale, |
1541 |
FT_Fixed x_scale, |
1266 |
FT_Fixed y_scale ) |
1542 |
FT_Fixed y_scale, |
|
|
1543 |
FT_Byte type ) |
1267 |
{ |
1544 |
{ |
1268 |
FT_Int n; |
1545 |
FT_Int n; |
1269 |
AH_Face_Globals globals = hinter->globals; |
1546 |
AH_Face_Globals globals = hinter->globals; |
1270 |
AH_Globals design = &globals->design; |
1547 |
AH_Globals design = &globals->designs[type]; |
1271 |
AH_Globals scaled = &globals->scaled; |
1548 |
AH_Globals scaled = &globals->scaled; |
|
|
1549 |
FT_Pos baseline = design->baseline; |
1550 |
|
1272 |
|
1551 |
|
|
|
1552 |
globals->x_scale_linear = x_scale; |
1553 |
globals->y_scale_linear = y_scale; |
1554 |
globals->cur_type = type; |
1273 |
|
1555 |
|
1274 |
/* copy content */ |
1556 |
/* copy content */ |
1275 |
*scaled = *design; |
1557 |
*scaled = *design; |
1276 |
|
1558 |
|
|
|
1559 |
#ifdef FT_CONFIG_CHESTER_BLUE_SCALE |
1560 |
|
1561 |
/* try to optimize the y_scale so that the top of non-capital letters |
1562 |
* is aligned on a pixel boundary whenever possible |
1563 |
*/ |
1564 |
if ( design->has_blues ) |
1565 |
{ |
1566 |
FT_Pos shoot = design->blue_shoots[AH_BLUE_SMALL_TOP]; |
1567 |
FT_Pos ref = design->blue_refs[AH_BLUE_SMALL_TOP]; |
1568 |
|
1569 |
|
1570 |
baseline = FT_MulFix( baseline, y_scale ); |
1571 |
|
1572 |
/* the value of 'shoot' will be -1000 if the font doesn't have */ |
1573 |
/* small latin letters; we simply check the sign here... */ |
1574 |
if ( shoot > 0 ) |
1575 |
{ |
1576 |
FT_Pos fitted; |
1577 |
|
1578 |
|
1579 |
shoot = FT_MulFix( shoot, y_scale ); |
1580 |
ref = FT_MulFix( ref, y_scale ); |
1581 |
|
1582 |
if ( shoot < 6*64 ) |
1583 |
fitted = ( shoot + 44 ) & -64; |
1584 |
else if ( shoot < 8*64 ) |
1585 |
fitted = ( shoot + 38 ) & -64; |
1586 |
else |
1587 |
fitted = ( shoot + 32 ) & -64; |
1588 |
|
1589 |
|
1590 |
if ( ref <= fitted && fitted < shoot ) |
1591 |
fitted = shoot; |
1592 |
else if ( fitted < ref ) |
1593 |
shoot = ref; |
1594 |
|
1595 |
if ( fitted > shoot ) |
1596 |
{ |
1597 |
y_scale = FT_MulDiv( y_scale, fitted, shoot ); |
1598 |
baseline -= ( fitted - shoot )/2; |
1599 |
} |
1600 |
} |
1601 |
} |
1602 |
|
1603 |
#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */ |
1604 |
|
1277 |
/* scale the standard widths & heights */ |
1605 |
/* scale the standard widths & heights */ |
1278 |
for ( n = 0; n < design->num_widths; n++ ) |
1606 |
for ( n = 0; n < design->num_widths; n++ ) |
1279 |
scaled->widths[n] = FT_MulFix( design->widths[n], x_scale ); |
1607 |
scaled->widths[n] = FT_MulFix( design->widths[n], x_scale ); |
Lines 1284-1293
Link Here
|
1284 |
scaled->stds[0] = ( design->num_widths > 0 ) ? scaled->widths[0] : 32000; |
1612 |
scaled->stds[0] = ( design->num_widths > 0 ) ? scaled->widths[0] : 32000; |
1285 |
scaled->stds[1] = ( design->num_heights > 0 ) ? scaled->heights[0] : 32000; |
1613 |
scaled->stds[1] = ( design->num_heights > 0 ) ? scaled->heights[0] : 32000; |
1286 |
|
1614 |
|
|
|
1615 |
globals->x_scale = x_scale; |
1616 |
globals->y_scale = y_scale; |
1617 |
|
1618 |
if ( !design->has_blues ) |
1619 |
return; |
1620 |
|
1621 |
|
1622 |
scaled->baseline = ( baseline + 32 ) & -64; |
1623 |
|
1287 |
/* scale the blue zones */ |
1624 |
/* scale the blue zones */ |
1288 |
for ( n = 0; n < AH_BLUE_MAX; n++ ) |
1625 |
for ( n = 0; n < AH_BLUE_MAX; n++ ) |
1289 |
{ |
1626 |
{ |
1290 |
FT_Pos delta, delta2; |
1627 |
FT_Pos delta, delta2; |
|
|
1628 |
FT_Pos ref, shoot, delta3, delta4; |
1291 |
|
1629 |
|
1292 |
|
1630 |
|
1293 |
delta = design->blue_shoots[n] - design->blue_refs[n]; |
1631 |
delta = design->blue_shoots[n] - design->blue_refs[n]; |
Lines 1306-1318
Link Here
|
1306 |
if ( delta < 0 ) |
1644 |
if ( delta < 0 ) |
1307 |
delta2 = -delta2; |
1645 |
delta2 = -delta2; |
1308 |
|
1646 |
|
1309 |
scaled->blue_refs[n] = |
1647 |
if ( n == AH_BLUE_SMALL_BOTTOM ) |
1310 |
( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64; |
1648 |
{ |
1311 |
scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2; |
1649 |
scaled->blue_shoots[n] = delta2; |
1312 |
} |
1650 |
scaled->blue_refs[n] = 0; |
|
|
1651 |
continue; |
1652 |
} |
1313 |
|
1653 |
|
1314 |
globals->x_scale = x_scale; |
1654 |
shoot = FT_MulFix( design->blue_shoots[n], y_scale ); |
1315 |
globals->y_scale = y_scale; |
1655 |
ref = FT_MulFix( design->blue_refs[n], y_scale ); |
|
|
1656 |
delta3 = ( ( shoot + 32 ) & -64 ) - shoot; |
1657 |
delta4 = ( ( ref + 32 ) & -64 ) - ref; |
1658 |
|
1659 |
if ( !hinter->do_stem_adjust ) |
1660 |
{ |
1661 |
if ( delta3 > 16 ) delta3 = 16; |
1662 |
if ( delta3 < -16 ) delta3 = -16; |
1663 |
if ( delta4 > 16 ) delta4 = 16; |
1664 |
if ( delta4 < -16 ) delta4 = -16; |
1665 |
} |
1666 |
|
1667 |
shoot += delta3; |
1668 |
ref += delta4; |
1669 |
|
1670 |
if ( ABS( delta3 ) < ABS( delta4 ) ) |
1671 |
ref = shoot - delta2; |
1672 |
else |
1673 |
shoot = ref + delta2; |
1674 |
|
1675 |
scaled->blue_refs[n] = ref; |
1676 |
scaled->blue_shoots[n] = shoot; |
1677 |
} |
1316 |
} |
1678 |
} |
1317 |
|
1679 |
|
1318 |
|
1680 |
|
Lines 1320-1326
Link Here
|
1320 |
ah_hinter_align( AH_Hinter hinter ) |
1682 |
ah_hinter_align( AH_Hinter hinter ) |
1321 |
{ |
1683 |
{ |
1322 |
ah_hinter_align_edge_points( hinter ); |
1684 |
ah_hinter_align_edge_points( hinter ); |
1323 |
ah_hinter_align_points( hinter ); |
1685 |
ah_hinter_align_normal_points( hinter ); |
1324 |
} |
1686 |
} |
1325 |
|
1687 |
|
1326 |
|
1688 |
|
Lines 1401-1407
Link Here
|
1401 |
hinter->globals = face_globals; |
1763 |
hinter->globals = face_globals; |
1402 |
|
1764 |
|
1403 |
if ( globals ) |
1765 |
if ( globals ) |
1404 |
face_globals->design = *globals; |
1766 |
face_globals->designs[0] = *globals; |
1405 |
else |
1767 |
else |
1406 |
ah_hinter_compute_globals( hinter ); |
1768 |
ah_hinter_compute_globals( hinter ); |
1407 |
|
1769 |
|
Lines 1410-1415
Link Here
|
1410 |
ah_hinter_done_face_globals; |
1772 |
ah_hinter_done_face_globals; |
1411 |
face_globals->face = face; |
1773 |
face_globals->face = face; |
1412 |
|
1774 |
|
|
|
1775 |
ah_hinter_compute_char_table( hinter ); |
1776 |
|
1777 |
{ |
1778 |
TT_OS2* os2 = FT_Get_Sfnt_Table( face, ft_sfnt_os2 ); |
1779 |
|
1780 |
|
1781 |
if ( os2 && os2->version != 0xFFFFU ) |
1782 |
face_globals->is_fixedpitch = FT_BOOL( os2->panose[3] == 9 ); |
1783 |
else |
1784 |
face_globals->is_fixedpitch = FT_BOOL( FT_IS_FIXED_WIDTH( face ) != 0 ); |
1785 |
|
1786 |
|
1787 |
face_globals->has_tt_bytecode_interp = FALSE; |
1788 |
|
1789 |
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
1790 |
if ( !strcmp( face->driver->root.clazz->module_name, "truetype" ) || |
1791 |
!strcmp( face->driver->root.clazz->module_name, "type42" ) ) |
1792 |
face_globals->has_tt_bytecode_interp = TRUE; |
1793 |
#endif |
1794 |
} |
1795 |
|
1413 |
Exit: |
1796 |
Exit: |
1414 |
return error; |
1797 |
return error; |
1415 |
} |
1798 |
} |
Lines 1423-1428
Link Here
|
1423 |
FT_Memory memory = face->memory; |
1806 |
FT_Memory memory = face->memory; |
1424 |
|
1807 |
|
1425 |
|
1808 |
|
|
|
1809 |
FT_Done_Size( globals->size_EM ); |
1810 |
FT_FREE( globals->table ); |
1426 |
FT_FREE( globals ); |
1811 |
FT_FREE( globals ); |
1427 |
} |
1812 |
} |
1428 |
|
1813 |
|
Lines 1441-1452
Link Here
|
1441 |
FT_Error error; |
1826 |
FT_Error error; |
1442 |
AH_Outline outline = hinter->glyph; |
1827 |
AH_Outline outline = hinter->glyph; |
1443 |
AH_Loader gloader = hinter->loader; |
1828 |
AH_Loader gloader = hinter->loader; |
|
|
1829 |
FT_Pos baseline = 0; |
1830 |
FT_Byte type = hinter->globals->cur_type; |
1444 |
|
1831 |
|
1445 |
|
1832 |
|
1446 |
/* load the glyph */ |
1833 |
/* load the glyph */ |
1447 |
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
1834 |
if ( !hinter->globals->has_tt_bytecode_interp ) |
1448 |
if ( error ) |
1835 |
{ |
1449 |
goto Exit; |
1836 |
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
|
|
1837 |
if ( error ) |
1838 |
goto Exit; |
1839 |
} |
1450 |
|
1840 |
|
1451 |
/* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */ |
1841 |
/* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */ |
1452 |
hinter->transformed = internal->glyph_transformed; |
1842 |
hinter->transformed = internal->glyph_transformed; |
Lines 1463-1468
Link Here
|
1463 |
FT_Matrix_Invert( &imatrix ); |
1853 |
FT_Matrix_Invert( &imatrix ); |
1464 |
FT_Vector_Transform( &hinter->trans_delta, &imatrix ); |
1854 |
FT_Vector_Transform( &hinter->trans_delta, &imatrix ); |
1465 |
} |
1855 |
} |
|
|
1856 |
else |
1857 |
{ |
1858 |
hinter->trans_delta.x = 0; |
1859 |
hinter->trans_delta.y = 0; |
1860 |
} |
1466 |
|
1861 |
|
1467 |
/* set linear horizontal metrics */ |
1862 |
/* set linear horizontal metrics */ |
1468 |
slot->linearHoriAdvance = slot->metrics.horiAdvance; |
1863 |
slot->linearHoriAdvance = slot->metrics.horiAdvance; |
Lines 1472-1488
Link Here
|
1472 |
{ |
1867 |
{ |
1473 |
case FT_GLYPH_FORMAT_OUTLINE: |
1868 |
case FT_GLYPH_FORMAT_OUTLINE: |
1474 |
|
1869 |
|
|
|
1870 |
if ( hinter->do_blue_hints ) |
1871 |
baseline = hinter->globals->designs[type].baseline; |
1872 |
|
1475 |
/* translate glyph outline if we need to */ |
1873 |
/* translate glyph outline if we need to */ |
1476 |
if ( hinter->transformed ) |
1874 |
if ( hinter->transformed || baseline != 0 ) |
1477 |
{ |
1875 |
{ |
1478 |
FT_UInt n = slot->outline.n_points; |
1876 |
FT_UInt n = slot->outline.n_points; |
1479 |
FT_Vector* point = slot->outline.points; |
1877 |
FT_Vector* point = slot->outline.points; |
|
|
1878 |
FT_Pos x_off = hinter->trans_delta.x; |
1879 |
FT_Pos y_off = hinter->trans_delta.y - baseline; |
1480 |
|
1880 |
|
1481 |
|
1881 |
|
1482 |
for ( ; n > 0; point++, n-- ) |
1882 |
for ( ; n > 0; point++, n-- ) |
1483 |
{ |
1883 |
{ |
1484 |
point->x += hinter->trans_delta.x; |
1884 |
point->x += x_off; |
1485 |
point->y += hinter->trans_delta.y; |
1885 |
point->y += y_off; |
1486 |
} |
1886 |
} |
1487 |
} |
1887 |
} |
1488 |
|
1888 |
|
Lines 1524-1530
Link Here
|
1524 |
/* perform feature detection */ |
1924 |
/* perform feature detection */ |
1525 |
ah_outline_detect_features( outline ); |
1925 |
ah_outline_detect_features( outline ); |
1526 |
|
1926 |
|
1527 |
if ( hinter->do_vert_hints ) |
1927 |
if ( hinter->do_blue_hints ) |
1528 |
{ |
1928 |
{ |
1529 |
ah_outline_compute_blue_edges( outline, hinter->globals ); |
1929 |
ah_outline_compute_blue_edges( outline, hinter->globals ); |
1530 |
ah_outline_scale_blue_edges( outline, hinter->globals ); |
1930 |
ah_outline_scale_blue_edges( outline, hinter->globals ); |
Lines 1539-1544
Link Here
|
1539 |
|
1939 |
|
1540 |
/* we now need to hint the metrics according to the change in */ |
1940 |
/* we now need to hint the metrics according to the change in */ |
1541 |
/* width/positioning that occured during the hinting process */ |
1941 |
/* width/positioning that occured during the hinting process */ |
|
|
1942 |
if ( !hinter->globals->is_fixedpitch && !hinter->composite && |
1943 |
type <= AH_CHAR_TYPE_HORIZONTAL ) |
1542 |
{ |
1944 |
{ |
1543 |
FT_Pos old_advance, old_rsb, old_lsb, new_lsb; |
1945 |
FT_Pos old_advance, old_rsb, old_lsb, new_lsb; |
1544 |
AH_Edge edge1 = outline->vert_edges; /* leftmost edge */ |
1946 |
AH_Edge edge1 = outline->vert_edges; /* leftmost edge */ |
Lines 1551-1558
Link Here
|
1551 |
old_lsb = edge1->opos; |
1953 |
old_lsb = edge1->opos; |
1552 |
new_lsb = edge1->pos; |
1954 |
new_lsb = edge1->pos; |
1553 |
|
1955 |
|
1554 |
hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64; |
1956 |
hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64; |
1555 |
hinter->pp2.x = ( ( edge2->pos + old_rsb ) + 32 ) & -64; |
1957 |
hinter->pp2.x = ( ( edge2->pos + old_rsb ) + 40 ) & -64; |
1556 |
|
1958 |
|
1557 |
#if 0 |
1959 |
#if 0 |
1558 |
/* try to fix certain bad advance computations */ |
1960 |
/* try to fix certain bad advance computations */ |
Lines 1705-1710
Link Here
|
1705 |
FT_BBox bbox; |
2107 |
FT_BBox bbox; |
1706 |
|
2108 |
|
1707 |
|
2109 |
|
|
|
2110 |
if ( hinter->do_blue_hints ) |
2111 |
{ |
2112 |
if ( hinter->globals->scaled.baseline != 0 ) |
2113 |
FT_Outline_Translate( &gloader->base.outline, |
2114 |
0, hinter->globals->scaled.baseline ); |
2115 |
} |
2116 |
|
1708 |
/* transform the hinted outline if needed */ |
2117 |
/* transform the hinted outline if needed */ |
1709 |
if ( hinter->transformed ) |
2118 |
if ( hinter->transformed ) |
1710 |
FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix ); |
2119 |
FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix ); |
Lines 1725-1738
Link Here
|
1725 |
slot->metrics.horiBearingX = bbox.xMin; |
2134 |
slot->metrics.horiBearingX = bbox.xMin; |
1726 |
slot->metrics.horiBearingY = bbox.yMax; |
2135 |
slot->metrics.horiBearingY = bbox.yMax; |
1727 |
|
2136 |
|
1728 |
/* for mono-width fonts (like Andale, Courier, etc.) we need */ |
2137 |
slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x; |
1729 |
/* to keep the original rounded advance width */ |
|
|
1730 |
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) |
1731 |
slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x; |
1732 |
else |
1733 |
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, |
1734 |
x_scale ); |
1735 |
|
1736 |
slot->metrics.horiAdvance = ( slot->metrics.horiAdvance + 32 ) & -64; |
2138 |
slot->metrics.horiAdvance = ( slot->metrics.horiAdvance + 32 ) & -64; |
1737 |
|
2139 |
|
1738 |
/* now copy outline into glyph slot */ |
2140 |
/* now copy outline into glyph slot */ |
Lines 1754-1759
Link Here
|
1754 |
} |
2156 |
} |
1755 |
|
2157 |
|
1756 |
|
2158 |
|
|
|
2159 |
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
2160 |
|
2161 |
#define AH_MAX_COMPOSITE_RECURSE 5 |
2162 |
|
2163 |
static FT_Error |
2164 |
ah_hinter_load_truetype( AH_Hinter hinter, |
2165 |
FT_UInt glyph_index, |
2166 |
FT_Int32 load_flags, |
2167 |
int depth, |
2168 |
short **num_contours, |
2169 |
short **num_points, |
2170 |
int *num_simple_glyphs, |
2171 |
int *size_array ) |
2172 |
{ |
2173 |
FT_Face face = hinter->face; |
2174 |
FT_Memory memory = hinter->memory; |
2175 |
FT_GlyphSlot slot = face->glyph; |
2176 |
FT_Error error = FT_Err_Ok; |
2177 |
|
2178 |
|
2179 |
if ( depth == 0 ) |
2180 |
{ |
2181 |
*num_contours = 0; |
2182 |
*num_points = 0; |
2183 |
*num_simple_glyphs = 0; |
2184 |
*size_array = 0; |
2185 |
} |
2186 |
|
2187 |
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
2188 |
|
2189 |
if ( error ) |
2190 |
return error; |
2191 |
|
2192 |
switch ( slot->format ) |
2193 |
{ |
2194 |
case FT_GLYPH_FORMAT_OUTLINE: |
2195 |
{ |
2196 |
int size_cur = *size_array; |
2197 |
|
2198 |
|
2199 |
if ( depth == 0 ) |
2200 |
return ah_hinter_load( hinter, 0, load_flags, 0 ); |
2201 |
|
2202 |
if ( slot->outline.n_contours == 0 ) |
2203 |
break; |
2204 |
|
2205 |
if ( *num_simple_glyphs >= size_cur ) |
2206 |
{ |
2207 |
if ( FT_RENEW_ARRAY( *num_contours, size_cur, size_cur + 16 ) || |
2208 |
FT_RENEW_ARRAY( *num_points, size_cur, size_cur + 16 ) ) |
2209 |
goto Exit; |
2210 |
*size_array += 16; |
2211 |
} |
2212 |
|
2213 |
(*num_contours)[ (*num_simple_glyphs) ] = slot->outline.n_contours; |
2214 |
(*num_points)[ (*num_simple_glyphs)++ ] = slot->outline.n_points; |
2215 |
break; |
2216 |
} |
2217 |
|
2218 |
case FT_GLYPH_FORMAT_COMPOSITE: |
2219 |
if ( depth + 1 >= AH_MAX_COMPOSITE_RECURSE ) |
2220 |
return AH_Err_Invalid_Composite; |
2221 |
|
2222 |
if ( slot->num_subglyphs > 0 ) |
2223 |
{ |
2224 |
FT_UInt* indices; |
2225 |
int num_subglyphs = slot->num_subglyphs; |
2226 |
int i; |
2227 |
|
2228 |
|
2229 |
hinter->composite = TRUE; |
2230 |
|
2231 |
if ( FT_NEW_ARRAY( indices, num_subglyphs ) ) |
2232 |
goto Exit; |
2233 |
|
2234 |
for ( i = 0; i < num_subglyphs; i++ ) |
2235 |
indices[i] = slot->subglyphs[i].index; |
2236 |
|
2237 |
|
2238 |
for ( i = 0; i < num_subglyphs; i++ ) |
2239 |
{ |
2240 |
error = ah_hinter_load_truetype( hinter, |
2241 |
indices[i], |
2242 |
load_flags, |
2243 |
depth + 1, |
2244 |
num_contours, |
2245 |
num_points, |
2246 |
num_simple_glyphs, |
2247 |
size_array ); |
2248 |
if ( error ) |
2249 |
{ |
2250 |
FT_FREE( indices ); |
2251 |
goto Exit; |
2252 |
} |
2253 |
} |
2254 |
|
2255 |
FT_FREE( indices ); |
2256 |
|
2257 |
if ( depth == 0 ) |
2258 |
{ |
2259 |
FT_Size size_EM, size; |
2260 |
FT_Vector* points; |
2261 |
FT_Vector* limit; |
2262 |
int num = *num_simple_glyphs, j; |
2263 |
short n_contours, n_points; |
2264 |
short *array_c, *array_p; |
2265 |
|
2266 |
|
2267 |
if ( num == 0 ) |
2268 |
break; |
2269 |
|
2270 |
size = face->size; |
2271 |
size_EM = hinter->globals->size_EM; |
2272 |
|
2273 |
if ( !size_EM ) |
2274 |
{ |
2275 |
error = FT_New_Size( face, &hinter->globals->size_EM ); |
2276 |
if ( error ) |
2277 |
goto Exit; |
2278 |
|
2279 |
size_EM = hinter->globals->size_EM; |
2280 |
FT_Activate_Size( size_EM ); |
2281 |
|
2282 |
error = FT_Set_Pixel_Sizes( face, |
2283 |
face->units_per_EM, |
2284 |
face->units_per_EM ); |
2285 |
if ( error ) |
2286 |
{ |
2287 |
FT_Activate_Size( size ); |
2288 |
goto Exit; |
2289 |
} |
2290 |
} |
2291 |
else |
2292 |
FT_Activate_Size( size_EM ); |
2293 |
|
2294 |
|
2295 |
load_flags &= ~FT_LOAD_NO_RECURSE & |
2296 |
~FT_LOAD_NO_SCALE; |
2297 |
load_flags |= FT_LOAD_NO_BITMAP | |
2298 |
FT_LOAD_NO_AUTOHINT | |
2299 |
FT_LOAD_IGNORE_TRANSFORM; |
2300 |
|
2301 |
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
2302 |
|
2303 |
FT_Activate_Size( size ); |
2304 |
|
2305 |
if ( error ) |
2306 |
goto Exit; |
2307 |
|
2308 |
|
2309 |
array_c = *num_contours; |
2310 |
array_p = *num_points; |
2311 |
n_contours = 0; |
2312 |
n_points = 0; |
2313 |
|
2314 |
for ( i = 0; i < num; i++ ) |
2315 |
{ |
2316 |
n_contours += *array_c++; |
2317 |
n_points += *array_p++; |
2318 |
} |
2319 |
|
2320 |
if ( slot->outline.n_points != n_points || |
2321 |
slot->outline.n_contours != n_contours ) |
2322 |
{ |
2323 |
error = AH_Err_Invalid_Composite; |
2324 |
goto Exit; |
2325 |
} |
2326 |
|
2327 |
|
2328 |
points = slot->outline.points; |
2329 |
limit = points + slot->outline.n_points; |
2330 |
|
2331 |
while ( points < limit ) |
2332 |
{ |
2333 |
points->x >>= 6; |
2334 |
points->y >>= 6; |
2335 |
points++; |
2336 |
} |
2337 |
|
2338 |
slot->metrics.horiAdvance >>= 6; |
2339 |
slot->metrics.vertAdvance >>= 6; |
2340 |
|
2341 |
array_c = *num_contours; |
2342 |
array_p = *num_points; |
2343 |
|
2344 |
for ( i = 0; i < num - 1; i++ ) |
2345 |
{ |
2346 |
slot->outline.n_contours = *array_c++; |
2347 |
slot->outline.n_points = *array_p++; |
2348 |
|
2349 |
error = ah_hinter_load( hinter, 0, load_flags, 1 ); |
2350 |
if ( error ) |
2351 |
goto Exit; |
2352 |
|
2353 |
n_points = slot->outline.n_points; |
2354 |
slot->outline.points += n_points; |
2355 |
slot->outline.tags += n_points; |
2356 |
slot->outline.contours += slot->outline.n_contours; |
2357 |
n_contours -= slot->outline.n_contours; |
2358 |
|
2359 |
for ( j = 0; j < n_contours; j++ ) |
2360 |
slot->outline.contours[j] -= n_points; |
2361 |
} |
2362 |
|
2363 |
slot->outline.n_contours = *array_c; |
2364 |
slot->outline.n_points = *array_p; |
2365 |
|
2366 |
error = ah_hinter_load( hinter, 0, load_flags, 0 ); |
2367 |
} |
2368 |
} |
2369 |
break; |
2370 |
|
2371 |
default: |
2372 |
error = AH_Err_Unimplemented_Feature; |
2373 |
} |
2374 |
|
2375 |
|
2376 |
Exit: |
2377 |
if ( depth == 0 ) |
2378 |
{ |
2379 |
FT_FREE( *num_contours ); |
2380 |
FT_FREE( *num_points ); |
2381 |
} |
2382 |
|
2383 |
return error; |
2384 |
} |
2385 |
|
2386 |
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
2387 |
|
2388 |
|
1757 |
/* load and hint a given glyph */ |
2389 |
/* load and hint a given glyph */ |
1758 |
FT_LOCAL_DEF( FT_Error ) |
2390 |
FT_LOCAL_DEF( FT_Error ) |
1759 |
ah_hinter_load_glyph( AH_Hinter hinter, |
2391 |
ah_hinter_load_glyph( AH_Hinter hinter, |
Lines 1768-1773
Link Here
|
1768 |
FT_Fixed y_scale = size->metrics.y_scale; |
2400 |
FT_Fixed y_scale = size->metrics.y_scale; |
1769 |
AH_Face_Globals face_globals = FACE_GLOBALS( face ); |
2401 |
AH_Face_Globals face_globals = FACE_GLOBALS( face ); |
1770 |
FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE( load_flags ); |
2402 |
FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE( load_flags ); |
|
|
2403 |
FT_Byte type; |
1771 |
|
2404 |
|
1772 |
|
2405 |
|
1773 |
/* first of all, we need to check that we're using the correct face and */ |
2406 |
/* first of all, we need to check that we're using the correct face and */ |
Lines 1787-1832
Link Here
|
1787 |
|
2420 |
|
1788 |
} |
2421 |
} |
1789 |
|
2422 |
|
1790 |
#ifdef FT_CONFIG_CHESTER_BLUE_SCALE |
|
|
1791 |
|
1792 |
/* try to optimize the y_scale so that the top of non-capital letters |
1793 |
* is aligned on a pixel boundary whenever possible |
1794 |
*/ |
1795 |
{ |
1796 |
AH_Globals design = &face_globals->design; |
1797 |
FT_Pos shoot = design->blue_shoots[AH_BLUE_SMALL_TOP]; |
1798 |
|
1799 |
|
1800 |
/* the value of 'shoot' will be -1000 if the font doesn't have */ |
1801 |
/* small latin letters; we simply check the sign here... */ |
1802 |
if ( shoot > 0 ) |
1803 |
{ |
1804 |
FT_Pos scaled = FT_MulFix( shoot, y_scale ); |
1805 |
FT_Pos fitted = ( scaled + 32 ) & -64; |
1806 |
|
1807 |
|
1808 |
if ( scaled != fitted ) |
1809 |
{ |
1810 |
/* adjust y_scale |
1811 |
*/ |
1812 |
y_scale = FT_MulDiv( y_scale, fitted, scaled ); |
1813 |
|
1814 |
/* adust x_scale |
1815 |
*/ |
1816 |
if ( fitted < scaled ) |
1817 |
x_scale -= x_scale / 50; /* x_scale*0.98 with integers */ |
1818 |
} |
1819 |
} |
1820 |
} |
1821 |
|
1822 |
#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */ |
1823 |
|
1824 |
/* now, we must check the current character pixel size to see if we */ |
1825 |
/* need to rescale the global metrics */ |
1826 |
if ( face_globals->x_scale != x_scale || |
1827 |
face_globals->y_scale != y_scale ) |
1828 |
ah_hinter_scale_globals( hinter, x_scale, y_scale ); |
1829 |
|
1830 |
ah_loader_rewind( hinter->loader ); |
2423 |
ah_loader_rewind( hinter->loader ); |
1831 |
|
2424 |
|
1832 |
/* reset hinting flags according to load flags and current render target */ |
2425 |
/* reset hinting flags according to load flags and current render target */ |
Lines 1850-1860
Link Here
|
1850 |
|
2443 |
|
1851 |
hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); |
2444 |
hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); |
1852 |
|
2445 |
|
|
|
2446 |
type = ah_hinter_get_char_type( hinter, glyph_index ); |
2447 |
|
2448 |
hinter->do_blue_hints = face_globals->designs[type].has_blues; |
2449 |
hinter->composite = FALSE; |
2450 |
|
2451 |
/* now, we must check the current character pixel size to see if we */ |
2452 |
/* need to rescale the global metrics */ |
2453 |
if ( face_globals->x_scale_linear != x_scale || |
2454 |
face_globals->y_scale_linear != y_scale || |
2455 |
face_globals->cur_type != type ) |
2456 |
ah_hinter_scale_globals( hinter, x_scale, y_scale, type ); |
2457 |
|
1853 |
|
2458 |
|
1854 |
load_flags |= FT_LOAD_NO_SCALE |
2459 |
load_flags |= FT_LOAD_NO_SCALE |
1855 |
| FT_LOAD_IGNORE_TRANSFORM ; |
2460 |
| FT_LOAD_IGNORE_TRANSFORM ; |
1856 |
|
2461 |
|
1857 |
error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); |
2462 |
#ifndef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
|
|
2463 |
|
2464 |
error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); |
2465 |
|
2466 |
#else |
2467 |
|
2468 |
if ( face_globals->has_tt_bytecode_interp ) |
2469 |
{ |
2470 |
short* num_contours; |
2471 |
short* num_points; |
2472 |
int num_simple_glyphs; |
2473 |
int size_array; |
2474 |
|
2475 |
|
2476 |
load_flags |= FT_LOAD_NO_RECURSE; |
2477 |
|
2478 |
error = ah_hinter_load_truetype( hinter, |
2479 |
glyph_index, |
2480 |
load_flags, |
2481 |
0, |
2482 |
&num_contours, |
2483 |
&num_points, |
2484 |
&num_simple_glyphs, |
2485 |
&size_array ); |
2486 |
} |
2487 |
else |
2488 |
error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); |
2489 |
|
2490 |
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
1858 |
|
2491 |
|
1859 |
Exit: |
2492 |
Exit: |
1860 |
return error; |
2493 |
return error; |
Lines 1885-1891
Link Here
|
1885 |
goto Fail; |
2518 |
goto Fail; |
1886 |
} |
2519 |
} |
1887 |
|
2520 |
|
1888 |
*globals = FACE_GLOBALS( face )->design; |
2521 |
*globals = FACE_GLOBALS( face )->designs[0]; |
1889 |
*global_hints = globals; |
2522 |
*global_hints = globals; |
1890 |
*global_len = sizeof( *globals ); |
2523 |
*global_len = sizeof( *globals ); |
1891 |
|
2524 |
|