OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* pshalgo.c */ | 3 /* pshalgo.c */ |
4 /* */ | 4 /* */ |
5 /* PostScript hinting algorithm (body). */ | 5 /* PostScript hinting algorithm (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 2001-2010, 2012-2014 by */ | 7 /* Copyright 2001-2015 by */ |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used */ | 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 */ | 11 /* modified and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
18 | 18 |
19 #include <ft2build.h> | 19 #include <ft2build.h> |
20 #include FT_INTERNAL_OBJECTS_H | 20 #include FT_INTERNAL_OBJECTS_H |
21 #include FT_INTERNAL_DEBUG_H | 21 #include FT_INTERNAL_DEBUG_H |
22 #include FT_INTERNAL_CALC_H | 22 #include FT_INTERNAL_CALC_H |
23 #include "pshalgo.h" | 23 #include "pshalgo.h" |
24 | 24 |
25 #include "pshnterr.h" | 25 #include "pshnterr.h" |
26 | 26 |
27 | 27 |
28 #undef FT_COMPONENT | 28 #undef FT_COMPONENT |
29 #define FT_COMPONENT trace_pshalgo2 | 29 #define FT_COMPONENT trace_pshalgo2 |
30 | 30 |
31 | 31 |
32 #ifdef DEBUG_HINTER | 32 #ifdef DEBUG_HINTER |
33 PSH_Hint_Table ps_debug_hint_table = 0; | 33 PSH_Hint_Table ps_debug_hint_table = NULL; |
34 PSH_HintFunc ps_debug_hint_func = 0; | 34 PSH_HintFunc ps_debug_hint_func = NULL; |
35 PSH_Glyph ps_debug_glyph = 0; | 35 PSH_Glyph ps_debug_glyph = NULL; |
36 #endif | 36 #endif |
37 | 37 |
38 | 38 |
39 #define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */ | 39 #define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */ |
40 /* and similar glyphs */ | 40 /* and similar glyphs */ |
41 #define STRONGER /* slightly increase the contrast of smooth */ | |
42 /* hinting */ | |
43 | 41 |
44 | 42 |
45 /*************************************************************************/ | 43 /*************************************************************************/ |
46 /*************************************************************************/ | 44 /*************************************************************************/ |
47 /***** *****/ | 45 /***** *****/ |
48 /***** BASIC HINTS RECORDINGS *****/ | 46 /***** BASIC HINTS RECORDINGS *****/ |
49 /***** *****/ | 47 /***** *****/ |
50 /*************************************************************************/ | 48 /*************************************************************************/ |
51 /*************************************************************************/ | 49 /*************************************************************************/ |
52 | 50 |
53 /* return true if two stem hints overlap */ | 51 /* return true if two stem hints overlap */ |
54 static FT_Int | 52 static FT_Int |
55 psh_hint_overlap( PSH_Hint hint1, | 53 psh_hint_overlap( PSH_Hint hint1, |
56 PSH_Hint hint2 ) | 54 PSH_Hint hint2 ) |
57 { | 55 { |
58 return hint1->org_pos + hint1->org_len >= hint2->org_pos && | 56 return hint1->org_pos + hint1->org_len >= hint2->org_pos && |
59 hint2->org_pos + hint2->org_len >= hint1->org_pos; | 57 hint2->org_pos + hint2->org_len >= hint1->org_pos; |
60 } | 58 } |
61 | 59 |
62 | 60 |
63 /* destroy hints table */ | 61 /* destroy hints table */ |
64 static void | 62 static void |
65 psh_hint_table_done( PSH_Hint_Table table, | 63 psh_hint_table_done( PSH_Hint_Table table, |
66 FT_Memory memory ) | 64 FT_Memory memory ) |
67 { | 65 { |
68 FT_FREE( table->zones ); | 66 FT_FREE( table->zones ); |
69 table->num_zones = 0; | 67 table->num_zones = 0; |
70 table->zone = 0; | 68 table->zone = NULL; |
71 | 69 |
72 FT_FREE( table->sort ); | 70 FT_FREE( table->sort ); |
73 FT_FREE( table->hints ); | 71 FT_FREE( table->hints ); |
74 table->num_hints = 0; | 72 table->num_hints = 0; |
75 table->max_hints = 0; | 73 table->max_hints = 0; |
76 table->sort_global = 0; | 74 table->sort_global = NULL; |
77 } | 75 } |
78 | 76 |
79 | 77 |
80 /* deactivate all hints in a table */ | 78 /* deactivate all hints in a table */ |
81 static void | 79 static void |
82 psh_hint_table_deactivate( PSH_Hint_Table table ) | 80 psh_hint_table_deactivate( PSH_Hint_Table table ) |
83 { | 81 { |
84 FT_UInt count = table->max_hints; | 82 FT_UInt count = table->max_hints; |
85 PSH_Hint hint = table->hints; | 83 PSH_Hint hint = table->hints; |
86 | 84 |
(...skipping 27 matching lines...) Expand all Loading... |
114 psh_hint_activate( hint ); | 112 psh_hint_activate( hint ); |
115 | 113 |
116 /* now scan the current active hint set to check */ | 114 /* now scan the current active hint set to check */ |
117 /* whether `hint' overlaps with another hint */ | 115 /* whether `hint' overlaps with another hint */ |
118 { | 116 { |
119 PSH_Hint* sorted = table->sort_global; | 117 PSH_Hint* sorted = table->sort_global; |
120 FT_UInt count = table->num_hints; | 118 FT_UInt count = table->num_hints; |
121 PSH_Hint hint2; | 119 PSH_Hint hint2; |
122 | 120 |
123 | 121 |
124 hint->parent = 0; | 122 hint->parent = NULL; |
125 for ( ; count > 0; count--, sorted++ ) | 123 for ( ; count > 0; count--, sorted++ ) |
126 { | 124 { |
127 hint2 = sorted[0]; | 125 hint2 = sorted[0]; |
128 | 126 |
129 if ( psh_hint_overlap( hint, hint2 ) ) | 127 if ( psh_hint_overlap( hint, hint2 ) ) |
130 { | 128 { |
131 hint->parent = hint2; | 129 hint->parent = hint2; |
132 break; | 130 break; |
133 } | 131 } |
134 } | 132 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 /* allocate our tables */ | 185 /* allocate our tables */ |
188 if ( FT_NEW_ARRAY( table->sort, 2 * count ) || | 186 if ( FT_NEW_ARRAY( table->sort, 2 * count ) || |
189 FT_NEW_ARRAY( table->hints, count ) || | 187 FT_NEW_ARRAY( table->hints, count ) || |
190 FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) | 188 FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) |
191 goto Exit; | 189 goto Exit; |
192 | 190 |
193 table->max_hints = count; | 191 table->max_hints = count; |
194 table->sort_global = table->sort + count; | 192 table->sort_global = table->sort + count; |
195 table->num_hints = 0; | 193 table->num_hints = 0; |
196 table->num_zones = 0; | 194 table->num_zones = 0; |
197 table->zone = 0; | 195 table->zone = NULL; |
198 | 196 |
199 /* initialize the `table->hints' array */ | 197 /* initialize the `table->hints' array */ |
200 { | 198 { |
201 PSH_Hint write = table->hints; | 199 PSH_Hint write = table->hints; |
202 PS_Hint read = hints->hints; | 200 PS_Hint read = hints->hints; |
203 | 201 |
204 | 202 |
205 for ( ; count > 0; count--, write++, read++ ) | 203 for ( ; count > 0; count--, write++, read++ ) |
206 { | 204 { |
207 write->org_pos = read->pos; | 205 write->org_pos = read->pos; |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 | 881 |
884 | 882 |
885 /*************************************************************************/ | 883 /*************************************************************************/ |
886 /*************************************************************************/ | 884 /*************************************************************************/ |
887 /***** *****/ | 885 /***** *****/ |
888 /***** POINTS INTERPOLATION ROUTINES *****/ | 886 /***** POINTS INTERPOLATION ROUTINES *****/ |
889 /***** *****/ | 887 /***** *****/ |
890 /*************************************************************************/ | 888 /*************************************************************************/ |
891 /*************************************************************************/ | 889 /*************************************************************************/ |
892 | 890 |
893 #define PSH_ZONE_MIN -3200000L | |
894 #define PSH_ZONE_MAX +3200000L | |
895 | |
896 #define xxDEBUG_ZONES | 891 #define xxDEBUG_ZONES |
897 | 892 |
898 | 893 |
899 #ifdef DEBUG_ZONES | 894 #ifdef DEBUG_ZONES |
900 | 895 |
901 #include FT_CONFIG_STANDARD_LIBRARY_H | 896 #include FT_CONFIG_STANDARD_LIBRARY_H |
902 | 897 |
903 static void | 898 static void |
904 psh_print_zone( PSH_Zone zone ) | 899 psh_print_zone( PSH_Zone zone ) |
905 { | 900 { |
906 printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n", | 901 printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n", |
907 zone->scale / 65536.0, | 902 zone->scale / 65536.0, |
908 zone->delta / 64.0, | 903 zone->delta / 64.0, |
909 zone->min, | 904 zone->min, |
910 zone->max ); | 905 zone->max ); |
911 } | 906 } |
912 | 907 |
913 #else | |
914 | |
915 #define psh_print_zone( x ) do { } while ( 0 ) | |
916 | |
917 #endif /* DEBUG_ZONES */ | 908 #endif /* DEBUG_ZONES */ |
918 | 909 |
919 | 910 |
920 /*************************************************************************/ | 911 /*************************************************************************/ |
921 /*************************************************************************/ | 912 /*************************************************************************/ |
922 /***** *****/ | 913 /***** *****/ |
923 /***** HINTER GLYPH MANAGEMENT *****/ | 914 /***** HINTER GLYPH MANAGEMENT *****/ |
924 /***** *****/ | 915 /***** *****/ |
925 /*************************************************************************/ | 916 /*************************************************************************/ |
926 /*************************************************************************/ | 917 /*************************************************************************/ |
927 | 918 |
928 #if 1 | |
929 | |
930 #define psh_corner_is_flat ft_corner_is_flat | 919 #define psh_corner_is_flat ft_corner_is_flat |
931 #define psh_corner_orientation ft_corner_orientation | 920 #define psh_corner_orientation ft_corner_orientation |
932 | 921 |
933 #else | |
934 | |
935 FT_LOCAL_DEF( FT_Int ) | |
936 psh_corner_is_flat( FT_Pos x_in, | |
937 FT_Pos y_in, | |
938 FT_Pos x_out, | |
939 FT_Pos y_out ) | |
940 { | |
941 FT_Pos ax = x_in; | |
942 FT_Pos ay = y_in; | |
943 | |
944 FT_Pos d_in, d_out, d_corner; | |
945 | |
946 | |
947 if ( ax < 0 ) | |
948 ax = -ax; | |
949 if ( ay < 0 ) | |
950 ay = -ay; | |
951 d_in = ax + ay; | |
952 | |
953 ax = x_out; | |
954 if ( ax < 0 ) | |
955 ax = -ax; | |
956 ay = y_out; | |
957 if ( ay < 0 ) | |
958 ay = -ay; | |
959 d_out = ax + ay; | |
960 | |
961 ax = x_out + x_in; | |
962 if ( ax < 0 ) | |
963 ax = -ax; | |
964 ay = y_out + y_in; | |
965 if ( ay < 0 ) | |
966 ay = -ay; | |
967 d_corner = ax + ay; | |
968 | |
969 return ( d_in + d_out - d_corner ) < ( d_corner >> 4 ); | |
970 } | |
971 | |
972 static FT_Int | |
973 psh_corner_orientation( FT_Pos in_x, | |
974 FT_Pos in_y, | |
975 FT_Pos out_x, | |
976 FT_Pos out_y ) | |
977 { | |
978 FT_Int result; | |
979 | |
980 | |
981 /* deal with the trivial cases quickly */ | |
982 if ( in_y == 0 ) | |
983 { | |
984 if ( in_x >= 0 ) | |
985 result = out_y; | |
986 else | |
987 result = -out_y; | |
988 } | |
989 else if ( in_x == 0 ) | |
990 { | |
991 if ( in_y >= 0 ) | |
992 result = -out_x; | |
993 else | |
994 result = out_x; | |
995 } | |
996 else if ( out_y == 0 ) | |
997 { | |
998 if ( out_x >= 0 ) | |
999 result = in_y; | |
1000 else | |
1001 result = -in_y; | |
1002 } | |
1003 else if ( out_x == 0 ) | |
1004 { | |
1005 if ( out_y >= 0 ) | |
1006 result = -in_x; | |
1007 else | |
1008 result = in_x; | |
1009 } | |
1010 else /* general case */ | |
1011 { | |
1012 long long delta = (long long)in_x * out_y - (long long)in_y * out_x; | |
1013 | |
1014 if ( delta == 0 ) | |
1015 result = 0; | |
1016 else | |
1017 result = 1 - 2 * ( delta < 0 ); | |
1018 } | |
1019 | |
1020 return result; | |
1021 } | |
1022 | |
1023 #endif /* !1 */ | |
1024 | |
1025 | 922 |
1026 #ifdef COMPUTE_INFLEXS | 923 #ifdef COMPUTE_INFLEXS |
1027 | 924 |
1028 /* compute all inflex points in a given glyph */ | 925 /* compute all inflex points in a given glyph */ |
1029 static void | 926 static void |
1030 psh_glyph_compute_inflections( PSH_Glyph glyph ) | 927 psh_glyph_compute_inflections( PSH_Glyph glyph ) |
1031 { | 928 { |
1032 FT_UInt n; | 929 FT_UInt n; |
1033 | 930 |
1034 | 931 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 | 1039 |
1143 psh_hint_table_done( &glyph->hint_tables[1], memory ); | 1040 psh_hint_table_done( &glyph->hint_tables[1], memory ); |
1144 psh_hint_table_done( &glyph->hint_tables[0], memory ); | 1041 psh_hint_table_done( &glyph->hint_tables[0], memory ); |
1145 | 1042 |
1146 FT_FREE( glyph->points ); | 1043 FT_FREE( glyph->points ); |
1147 FT_FREE( glyph->contours ); | 1044 FT_FREE( glyph->contours ); |
1148 | 1045 |
1149 glyph->num_points = 0; | 1046 glyph->num_points = 0; |
1150 glyph->num_contours = 0; | 1047 glyph->num_contours = 0; |
1151 | 1048 |
1152 glyph->memory = 0; | 1049 glyph->memory = NULL; |
1153 } | 1050 } |
1154 | 1051 |
1155 | 1052 |
1156 static int | 1053 static int |
1157 psh_compute_dir( FT_Pos dx, | 1054 psh_compute_dir( FT_Pos dx, |
1158 FT_Pos dy ) | 1055 FT_Pos dy ) |
1159 { | 1056 { |
1160 FT_Pos ax, ay; | 1057 FT_Pos ax, ay; |
1161 int result = PSH_DIR_NONE; | 1058 int result = PSH_DIR_NONE; |
1162 | 1059 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1267 /* clear all fields */ | 1164 /* clear all fields */ |
1268 FT_MEM_ZERO( glyph, sizeof ( *glyph ) ); | 1165 FT_MEM_ZERO( glyph, sizeof ( *glyph ) ); |
1269 | 1166 |
1270 memory = glyph->memory = globals->memory; | 1167 memory = glyph->memory = globals->memory; |
1271 | 1168 |
1272 /* allocate and setup points + contours arrays */ | 1169 /* allocate and setup points + contours arrays */ |
1273 if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || | 1170 if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || |
1274 FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) | 1171 FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) |
1275 goto Exit; | 1172 goto Exit; |
1276 | 1173 |
1277 glyph->num_points = outline->n_points; | 1174 glyph->num_points = (FT_UInt)outline->n_points; |
1278 glyph->num_contours = outline->n_contours; | 1175 glyph->num_contours = (FT_UInt)outline->n_contours; |
1279 | 1176 |
1280 { | 1177 { |
1281 FT_UInt first = 0, next, n; | 1178 FT_UInt first = 0, next, n; |
1282 PSH_Point points = glyph->points; | 1179 PSH_Point points = glyph->points; |
1283 PSH_Contour contour = glyph->contours; | 1180 PSH_Contour contour = glyph->contours; |
1284 | 1181 |
1285 | 1182 |
1286 for ( n = 0; n < glyph->num_contours; n++ ) | 1183 for ( n = 0; n < glyph->num_contours; n++ ) |
1287 { | 1184 { |
1288 FT_Int count; | 1185 FT_UInt count; |
1289 PSH_Point point; | 1186 PSH_Point point; |
1290 | 1187 |
1291 | 1188 |
1292 next = outline->contours[n] + 1; | 1189 next = (FT_UInt)outline->contours[n] + 1; |
1293 count = next - first; | 1190 count = next - first; |
1294 | 1191 |
1295 contour->start = points + first; | 1192 contour->start = points + first; |
1296 contour->count = (FT_UInt)count; | 1193 contour->count = count; |
1297 | 1194 |
1298 if ( count > 0 ) | 1195 if ( count > 0 ) |
1299 { | 1196 { |
1300 point = points + first; | 1197 point = points + first; |
1301 | 1198 |
1302 point->prev = points + next - 1; | 1199 point->prev = points + next - 1; |
1303 point->contour = contour; | 1200 point->contour = contour; |
1304 | 1201 |
1305 for ( ; count > 1; count-- ) | 1202 for ( ; count > 1; count-- ) |
1306 { | 1203 { |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1689 /* process secondary hints to `selected' points */ | 1586 /* process secondary hints to `selected' points */ |
1690 if ( num_masks > 1 && glyph->num_points > 0 ) | 1587 if ( num_masks > 1 && glyph->num_points > 0 ) |
1691 { | 1588 { |
1692 /* the `endchar' op can reduce the number of points */ | 1589 /* the `endchar' op can reduce the number of points */ |
1693 first = mask->end_point > glyph->num_points | 1590 first = mask->end_point > glyph->num_points |
1694 ? glyph->num_points | 1591 ? glyph->num_points |
1695 : mask->end_point; | 1592 : mask->end_point; |
1696 mask++; | 1593 mask++; |
1697 for ( ; num_masks > 1; num_masks--, mask++ ) | 1594 for ( ; num_masks > 1; num_masks--, mask++ ) |
1698 { | 1595 { |
1699 FT_UInt next; | 1596 FT_UInt next = FT_MIN( mask->end_point, glyph->num_points ); |
1700 FT_Int count; | |
1701 | 1597 |
1702 | 1598 |
1703 next = mask->end_point > glyph->num_points | 1599 if ( next > first ) |
1704 ? glyph->num_points | |
1705 : mask->end_point; | |
1706 count = next - first; | |
1707 if ( count > 0 ) | |
1708 { | 1600 { |
| 1601 FT_UInt count = next - first; |
1709 PSH_Point point = glyph->points + first; | 1602 PSH_Point point = glyph->points + first; |
1710 | 1603 |
1711 | 1604 |
1712 psh_hint_table_activate_mask( table, mask ); | 1605 psh_hint_table_activate_mask( table, mask ); |
1713 | 1606 |
1714 psh_hint_table_find_strong_points( table, point, count, | 1607 psh_hint_table_find_strong_points( table, point, count, |
1715 threshold, major_dir ); | 1608 threshold, major_dir ); |
1716 } | 1609 } |
1717 first = next; | 1610 first = next; |
1718 } | 1611 } |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2041 for ( ; num_contours > 0; num_contours--, contour++ ) | 1934 for ( ; num_contours > 0; num_contours--, contour++ ) |
2042 { | 1935 { |
2043 PSH_Point start = contour->start; | 1936 PSH_Point start = contour->start; |
2044 PSH_Point first, next, point; | 1937 PSH_Point first, next, point; |
2045 FT_UInt fit_count; | 1938 FT_UInt fit_count; |
2046 | 1939 |
2047 | 1940 |
2048 /* count the number of strong points in this contour */ | 1941 /* count the number of strong points in this contour */ |
2049 next = start + contour->count; | 1942 next = start + contour->count; |
2050 fit_count = 0; | 1943 fit_count = 0; |
2051 first = 0; | 1944 first = NULL; |
2052 | 1945 |
2053 for ( point = start; point < next; point++ ) | 1946 for ( point = start; point < next; point++ ) |
2054 if ( psh_point_is_fitted( point ) ) | 1947 if ( psh_point_is_fitted( point ) ) |
2055 { | 1948 { |
2056 if ( !first ) | 1949 if ( !first ) |
2057 first = point; | 1950 first = point; |
2058 | 1951 |
2059 fit_count++; | 1952 fit_count++; |
2060 } | 1953 } |
2061 | 1954 |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2293 | 2186 |
2294 #ifndef DEBUG_HINTER | 2187 #ifndef DEBUG_HINTER |
2295 psh_glyph_done( glyph ); | 2188 psh_glyph_done( glyph ); |
2296 #endif | 2189 #endif |
2297 | 2190 |
2298 return error; | 2191 return error; |
2299 } | 2192 } |
2300 | 2193 |
2301 | 2194 |
2302 /* END */ | 2195 /* END */ |
OLD | NEW |