Craig White pushed to branch gsoc-craig-2023 at FreeType / FreeType
Commits:
-
62378cca
by Craig White at 2023-06-25T23:24:02-04:00
-
37e3e348
by Craig White at 2023-06-25T23:43:23-04:00
4 changed files:
- include/freetype/internal/fttrace.h
- src/autofit/afadjust.c
- src/autofit/afadjust.h
- src/autofit/aflatin.c
Changes:
... | ... | @@ -164,6 +164,7 @@ FT_TRACE_DEF( afhints ) |
164 | 164 | FT_TRACE_DEF( afmodule )
|
165 | 165 | FT_TRACE_DEF( aflatin )
|
166 | 166 | FT_TRACE_DEF( afshaper )
|
167 | +FT_TRACE_DEF( afadjust )
|
|
167 | 168 | |
168 | 169 | /* SDF components */
|
169 | 170 | FT_TRACE_DEF( sdf ) /* signed distance raster for outlines (ftsdf.c) */
|
... | ... | @@ -2,34 +2,59 @@ |
2 | 2 | #include <freetype/freetype.h>
|
3 | 3 | #include <freetype/internal/ftobjs.h>
|
4 | 4 | #include <freetype/internal/ftmemory.h>
|
5 | +#include <freetype/internal/ftdebug.h>
|
|
5 | 6 | |
6 | -#define AF_ADJUSTMENT_DATABASE_LENGTH 12
|
|
7 | +#define AF_ADJUSTMENT_DATABASE_LENGTH ( sizeof(adjustment_database)/sizeof(adjustment_database[0]) )
|
|
8 | +#undef FT_COMPONENT
|
|
9 | +#define FT_COMPONENT afadjust
|
|
7 | 10 | |
8 | 11 | /*TODO: find out whether capital u/U with accent entries are needed*/
|
9 | 12 | /*the accent won't merge with the rest of the glyph because the accent mark is sitting above empty space*/
|
10 | 13 | FT_LOCAL_ARRAY_DEF( AF_AdjustmentDatabaseEntry )
|
11 | -adjustment_database[AF_ADJUSTMENT_DATABASE_LENGTH] = {
|
|
12 | - {'i', AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE},
|
|
13 | - {'j', AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE},
|
|
14 | - {0xC8, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*E with grave*/
|
|
15 | - {0xCC, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*I with grave*/
|
|
16 | - {0xD9, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*U with grave*/
|
|
17 | - {0xE0, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*a with grave*/
|
|
18 | - {0xEC, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*i with grave*/
|
|
19 | - {0x114, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*E with macron*/
|
|
20 | - {0x12A, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*I with macron*/
|
|
21 | - {0x12B, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*i with macron*/
|
|
22 | - {0x16A, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*U with macron*/
|
|
23 | - {0x16B, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE} /*u with macron*/
|
|
24 | - /*TODO: find out why E won't work, even though it appears to be one-on-one*/
|
|
14 | +adjustment_database[] =
|
|
15 | +{
|
|
16 | + {0x21, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* ! */
|
|
17 | + {0x69, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* i */
|
|
18 | + {0x6A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* j */
|
|
19 | + {0xA1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*Inverted Exclamation Mark*/
|
|
20 | + {0xBF, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*Inverted Question Mark*/
|
|
21 | + {0xC0, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with grave*/
|
|
22 | + {0xC1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with acute*/
|
|
23 | + {0xC2, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with circumflex*/
|
|
24 | + {0xC3, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with tilde*/
|
|
25 | + {0xC8, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*E with grave*/
|
|
26 | + {0xCC, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*I with grave*/
|
|
27 | + {0xD9, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*U with grave*/
|
|
28 | + {0xE0, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*a with grave*/
|
|
29 | + {0xEC, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*i with grave*/
|
|
30 | + {0x114, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*E with macron*/
|
|
31 | + {0x12A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*I with macron*/
|
|
32 | + {0x12B, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*i with macron*/
|
|
33 | + {0x16A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*U with macron*/
|
|
34 | + {0x16B, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP} /*u with macron*/
|
|
25 | 35 | };
|
26 | 36 | |
27 | 37 | /*Helper function: get the adjustment database entry for a codepoint*/
|
28 | 38 | FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
|
29 | 39 | af_adjustment_database_lookup( FT_UInt32 codepoint ) {
|
30 | - for ( FT_Int entry = 0; entry < AF_ADJUSTMENT_DATABASE_LENGTH; entry++ ) {
|
|
31 | - if ( adjustment_database[entry].codepoint == codepoint ) {
|
|
32 | - return &adjustment_database[entry];
|
|
40 | + /* Binary search for database entry */
|
|
41 | + FT_Int low = 0;
|
|
42 | + FT_Int high = AF_ADJUSTMENT_DATABASE_LENGTH - 1;
|
|
43 | + while ( high > low )
|
|
44 | + {
|
|
45 | + FT_Int mid = ( low + high ) / 2;
|
|
46 | + FT_UInt32 mid_codepoint = adjustment_database[mid].codepoint;
|
|
47 | + if ( mid_codepoint < codepoint )
|
|
48 | + {
|
|
49 | + low = mid + 1;
|
|
50 | + }
|
|
51 | + else if ( mid_codepoint > codepoint )
|
|
52 | + {
|
|
53 | + high = mid - 1;
|
|
54 | + }
|
|
55 | + else
|
|
56 | + {
|
|
57 | + return &adjustment_database[mid];
|
|
33 | 58 | }
|
34 | 59 | }
|
35 | 60 | |
... | ... | @@ -40,31 +65,50 @@ FT_LOCAL_DEF( AF_VerticalSeparationAdjustmentType ) |
40 | 65 | af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
|
41 | 66 | FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
|
42 | 67 | const AF_AdjustmentDatabaseEntry *entry = af_adjustment_database_lookup( codepoint );
|
43 | - if ( entry == NULL ) {
|
|
68 | + if ( entry == NULL )
|
|
69 | + {
|
|
44 | 70 | return AF_VERTICAL_ADJUSTMENT_NONE;
|
45 | 71 | }
|
46 | 72 | return entry->vertical_separation_adjustment_type;
|
47 | 73 | }
|
48 | 74 | |
49 | -typedef struct AF_ReverseMapEntry_ {
|
|
75 | +typedef struct AF_ReverseMapEntry_
|
|
76 | +{
|
|
50 | 77 | FT_Int glyph_index;
|
51 | 78 | FT_UInt32 codepoint;
|
52 | 79 | } AF_ReverseMapEntry;
|
53 | 80 | |
54 | -typedef struct AF_ReverseCharacterMap_ {
|
|
81 | +typedef struct AF_ReverseCharacterMap_
|
|
82 | +{
|
|
55 | 83 | FT_UInt length;
|
56 | 84 | AF_ReverseMapEntry *entries;
|
57 | 85 | } AF_ReverseCharacterMap_Rec;
|
58 | 86 | |
59 | -FT_LOCAL_DEF(FT_UInt32)
|
|
60 | -af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
|
|
61 | - if ( map == NULL ) {
|
|
87 | +FT_LOCAL_DEF( FT_UInt32 )
|
|
88 | +af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index )
|
|
89 | +{
|
|
90 | + if ( map == NULL )
|
|
91 | + {
|
|
62 | 92 | return 0;
|
63 | 93 | }
|
64 | - |
|
65 | - for ( FT_UInt entry = 0; entry < map->length; entry++ ) {
|
|
66 | - if ( map->entries[entry].glyph_index == glyph_index ) {
|
|
67 | - return map->entries[entry].codepoint;
|
|
94 | + /* Binary search for reverse character map entry */
|
|
95 | + FT_Int low = 0;
|
|
96 | + FT_Int high = map->length - 1;
|
|
97 | + while ( high > low )
|
|
98 | + {
|
|
99 | + FT_Int mid = ( high + low ) / 2;
|
|
100 | + FT_Int mid_glyph_index = map->entries[mid].glyph_index;
|
|
101 | + if ( glyph_index < mid_glyph_index )
|
|
102 | + {
|
|
103 | + high = mid - 1;
|
|
104 | + }
|
|
105 | + else if ( glyph_index > mid_glyph_index )
|
|
106 | + {
|
|
107 | + low = mid + 1;
|
|
108 | + }
|
|
109 | + else
|
|
110 | + {
|
|
111 | + return map->entries[mid].codepoint;
|
|
68 | 112 | }
|
69 | 113 | }
|
70 | 114 | |
... | ... | @@ -72,64 +116,87 @@ af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index |
72 | 116 | }
|
73 | 117 | |
74 | 118 | FT_LOCAL_DEF( FT_Error )
|
75 | -af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map, FT_Memory memory ) {
|
|
119 | +af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map, FT_Memory memory )
|
|
120 | +{
|
|
76 | 121 | /* Search for a unicode charmap */
|
77 | 122 | /* If there isn't one, create a blank map */
|
78 | -
|
|
123 | + |
|
79 | 124 | /*TODO: change this to logic that searches for a "preferred" unicode charmap that maps the most codepoints*/
|
80 | 125 | /*see find_unicode_charmap*/
|
81 | 126 | /*TODO: use GSUB lookups */
|
127 | + FT_TRACE4(( "af_reverse_character_map_new: building reverse character map\n" ));
|
|
82 | 128 | FT_CMap unicode_charmap = NULL;
|
83 | - for ( FT_UInt i = 0; i < face->num_charmaps; i++ ) {
|
|
84 | - if ( face->charmaps[i]->encoding == FT_ENCODING_UNICODE ) {
|
|
129 | + for ( FT_UInt i = 0; i < face->num_charmaps; i++ )
|
|
130 | + {
|
|
131 | + if ( face->charmaps[i]->encoding == FT_ENCODING_UNICODE )
|
|
132 | + {
|
|
85 | 133 | unicode_charmap = FT_CMAP( face->charmaps[i] );
|
86 | 134 | }
|
87 | 135 | }
|
88 | -
|
|
89 | - if ( unicode_charmap == NULL ) {
|
|
136 | + |
|
137 | + if ( unicode_charmap == NULL )
|
|
138 | + {
|
|
90 | 139 | *map = NULL;
|
91 | 140 | return FT_Err_Ok;
|
92 | 141 | }
|
93 | 142 | |
94 | 143 | FT_Error error;
|
95 | 144 | |
96 | - if ( FT_NEW( *map ) ) {
|
|
145 | + if ( FT_NEW( *map ) )
|
|
146 | + {
|
|
97 | 147 | goto Exit;
|
98 | 148 | }
|
99 | 149 | |
100 | 150 | FT_Int capacity = 10;
|
101 | 151 | FT_Int size = 0;
|
102 | -
|
|
103 | - if ( FT_NEW_ARRAY((*map)->entries, capacity) ) {
|
|
152 | + |
|
153 | + if ( FT_NEW_ARRAY( ( *map )->entries, capacity) )
|
|
154 | + {
|
|
104 | 155 | goto Exit;
|
105 | 156 | }
|
106 | - for ( FT_Int i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ ) {
|
|
157 | +#ifdef FT_DEBUG_LEVEL_TRACE
|
|
158 | + int failed_lookups = 0;
|
|
159 | +#endif
|
|
160 | + for ( FT_Int i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ )
|
|
161 | + {
|
|
107 | 162 | FT_UInt32 codepoint = adjustment_database[i].codepoint;
|
108 | 163 | FT_Int glyph = unicode_charmap->clazz->char_index(unicode_charmap, codepoint);
|
109 | - if ( glyph == 0 ) {
|
|
164 | + if ( glyph == 0 )
|
|
165 | + {
|
|
166 | +#ifdef FT_DEBUG_LEVEL_TRACE
|
|
167 | + failed_lookups++;
|
|
168 | +#endif
|
|
110 | 169 | continue;
|
111 | 170 | }
|
112 | - if (size == capacity) {
|
|
171 | + if ( size == capacity )
|
|
172 | + {
|
|
113 | 173 | capacity += capacity / 2;
|
114 | - if ( FT_RENEW_ARRAY((*map)->entries, size, capacity) ) {
|
|
174 | + if ( FT_RENEW_ARRAY((*map)->entries, size, capacity) )
|
|
175 | + {
|
|
115 | 176 | goto Exit;
|
116 | 177 | }
|
117 | 178 | }
|
118 | 179 | size++;
|
119 | - (*map)->entries[i].glyph_index = glyph;
|
|
120 | - (*map)->entries[i].codepoint = codepoint;
|
|
180 | + ( *map )->entries[i].glyph_index = glyph;
|
|
181 | + ( *map )->entries[i].codepoint = codepoint;
|
|
121 | 182 | }
|
122 | - (*map)->length = size;
|
|
183 | + ( *map )->length = size;
|
|
123 | 184 | |
124 | 185 | Exit:
|
125 | - if ( error ) {
|
|
126 | - if ( *map ) {
|
|
186 | + if ( error )
|
|
187 | + {
|
|
188 | + FT_TRACE4(( " error while building reverse character map. Using blank map.\n" ));
|
|
189 | + if ( *map )
|
|
190 | + {
|
|
127 | 191 | FT_FREE( ( *map )->entries );
|
128 | 192 | }
|
129 | 193 | FT_FREE( *map );
|
130 | 194 | return error;
|
131 | 195 | }
|
132 | - |
|
196 | +#ifdef FT_DEBUG_LEVEL_TRACE
|
|
197 | + FT_TRACE4(( " reverse character map built successfully"\
|
|
198 | + " with %d entries and %d failed lookups.\n", size, failed_lookups ));
|
|
199 | +#endif
|
|
133 | 200 | return FT_Err_Ok;
|
134 | 201 | }
|
135 | 202 | |
... | ... | @@ -137,4 +204,4 @@ FT_LOCAL_DEF( FT_Error ) |
137 | 204 | af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory ) {
|
138 | 205 | FT_FREE( map->entries );
|
139 | 206 | return FT_Err_Ok;
|
140 | -} |
|
\ No newline at end of file | ||
207 | +} |
... | ... | @@ -7,11 +7,11 @@ FT_BEGIN_HEADER |
7 | 7 | |
8 | 8 | /*The type of adjustment that should be done to prevent cases where 2 parts of a character*/
|
9 | 9 | /*stacked vertically merge, even though they should be separate*/
|
10 | -typedef enum AF_VerticalSeparationAdjustmentType_ {
|
|
11 | - AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE,
|
|
12 | - /*"One on one" means that the character is expected to be one contour on top of another, where the contours should not touch*/
|
|
13 | - /*the hinter will force the contours to have a gap of at least 1 pixel between them*/
|
|
14 | - /*by moving the top contour up */
|
|
10 | +typedef enum AF_VerticalSeparationAdjustmentType_
|
|
11 | +{
|
|
12 | + AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP,
|
|
13 | + /*This means that the hinter should find the topmost contour and push it up until its lowest point is 1 pixel*/
|
|
14 | + /*above the highest point not part of that contour.*/
|
|
15 | 15 | AF_VERTICAL_ADJUSTMENT_NONE
|
16 | 16 | |
17 | 17 | /*others will be needed, such as the case where the lower contour should be moved in the adjustment instead of the upper one*/
|
... | ... | @@ -19,10 +19,11 @@ typedef enum AF_VerticalSeparationAdjustmentType_ { |
19 | 19 | /*and a way of handling A and O, where the letter consists of 2 contours*/
|
20 | 20 | } AF_VerticalSeparationAdjustmentType;
|
21 | 21 | |
22 | -typedef struct AF_AdjustmentDatabaseEntry_ {
|
|
23 | - FT_UInt32 codepoint;
|
|
24 | - AF_VerticalSeparationAdjustmentType vertical_separation_adjustment_type;
|
|
25 | - } AF_AdjustmentDatabaseEntry;
|
|
22 | +typedef struct AF_AdjustmentDatabaseEntry_
|
|
23 | +{
|
|
24 | + FT_UInt32 codepoint;
|
|
25 | + AF_VerticalSeparationAdjustmentType vertical_separation_adjustment_type;
|
|
26 | +} AF_AdjustmentDatabaseEntry;
|
|
26 | 27 | |
27 | 28 | struct AF_ReverseCharacterMap_;
|
28 | 29 | |
... | ... | @@ -37,11 +38,11 @@ af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index |
37 | 38 | /*allocate and populate the reverse character map, using the character map within the face*/
|
38 | 39 | FT_LOCAL( FT_Error )
|
39 | 40 | af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map, FT_Memory memory );
|
40 | -
|
|
41 | + |
|
41 | 42 | /*free the reverse character map*/
|
42 | 43 | FT_LOCAL( FT_Error )
|
43 | 44 | af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory );
|
44 | 45 | |
45 | 46 | FT_END_HEADER
|
46 | 47 | |
47 | -#endif |
|
\ No newline at end of file | ||
48 | +#endif |
... | ... | @@ -1153,7 +1153,7 @@ |
1153 | 1153 | goto Exit;
|
1154 | 1154 | }
|
1155 | 1155 | af_latin_metrics_check_digits( metrics, face );
|
1156 | -
|
|
1156 | + |
|
1157 | 1157 | af_reverse_character_map_new( face, &metrics->root.reverse_charmap, face->memory );
|
1158 | 1158 | }
|
1159 | 1159 | |
... | ... | @@ -2745,13 +2745,25 @@ |
2745 | 2745 | }
|
2746 | 2746 | |
2747 | 2747 | |
2748 | -void af_glyph_hints_apply_adjustments(AF_GlyphHints hints, AF_Dimension dim, FT_Int glyph_index, AF_ReverseCharacterMap reverse_charmap) {
|
|
2749 | - if ( dim != AF_DIMENSION_VERT ) {
|
|
2748 | +#undef FT_COMPONENT
|
|
2749 | +#define FT_COMPONENT afadjust
|
|
2750 | + |
|
2751 | +void
|
|
2752 | +af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
|
|
2753 | + AF_Dimension dim,
|
|
2754 | + FT_Int glyph_index,
|
|
2755 | + AF_ReverseCharacterMap reverse_charmap )
|
|
2756 | +{
|
|
2757 | + if ( dim != AF_DIMENSION_VERT )
|
|
2758 | + {
|
|
2750 | 2759 | return;
|
2751 | 2760 | }
|
2752 | - if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) == AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE &&
|
|
2753 | - hints->num_contours == 2 ) {
|
|
2754 | -
|
|
2761 | + |
|
2762 | + if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) == AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP
|
|
2763 | + && hints->num_contours >= 2 )
|
|
2764 | + {
|
|
2765 | + FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: Applying vertical adjustment: AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP\n" ));
|
|
2766 | + |
|
2755 | 2767 | /* Figure out which contout is the higher one by finding the one */
|
2756 | 2768 | /* with the highest minimum y value */
|
2757 | 2769 | |
... | ... | @@ -2759,22 +2771,27 @@ void af_glyph_hints_apply_adjustments(AF_GlyphHints hints, AF_Dimension dim, FT_ |
2759 | 2771 | FT_Pos highest_min_y = 0;
|
2760 | 2772 | FT_Pos current_min_y = 0;
|
2761 | 2773 | |
2762 | - for ( FT_Int contour = 0; contour < hints->num_contours; contour++ ) {
|
|
2774 | + for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
|
|
2775 | + {
|
|
2763 | 2776 | AF_Point point = hints->contours[contour];
|
2764 | 2777 | AF_Point first_point = point;
|
2765 | - if ( point == NULL ) { /*TODO: is this necessary?*/
|
|
2778 | + if ( point == NULL )
|
|
2779 | + { /*TODO: is this necessary?*/
|
|
2766 | 2780 | continue;
|
2767 | 2781 | }
|
2768 | 2782 | current_min_y = point->y;
|
2769 | 2783 | |
2770 | - do {
|
|
2771 | - if ( point->y < current_min_y ) {
|
|
2784 | + do
|
|
2785 | + {
|
|
2786 | + if ( point->y < current_min_y )
|
|
2787 | + {
|
|
2772 | 2788 | current_min_y = point->y;
|
2773 | 2789 | }
|
2774 | 2790 | point = point->next;
|
2775 | 2791 | } while ( point != first_point );
|
2776 | 2792 | |
2777 | - if ( highest_contour == -1 || current_min_y > highest_min_y ) {
|
|
2793 | + if ( highest_contour == -1 || current_min_y > highest_min_y )
|
|
2794 | + {
|
|
2778 | 2795 | highest_min_y = current_min_y;
|
2779 | 2796 | highest_contour = contour;
|
2780 | 2797 | }
|
... | ... | @@ -2785,42 +2802,60 @@ void af_glyph_hints_apply_adjustments(AF_GlyphHints hints, AF_Dimension dim, FT_ |
2785 | 2802 | /* contour, bump the high contour up until the distance is one pixel */
|
2786 | 2803 | |
2787 | 2804 | FT_Int adjustment_amount = 0;
|
2788 | - for ( FT_Int contour = 0; contour < hints->num_contours; contour++ ) {
|
|
2789 | - if (contour == highest_contour) {
|
|
2805 | + for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
|
|
2806 | + {
|
|
2807 | + if ( contour == highest_contour )
|
|
2808 | + {
|
|
2790 | 2809 | continue;
|
2791 | 2810 | }
|
2792 | 2811 | AF_Point point = hints->contours[contour];
|
2793 | 2812 | AF_Point first_point = point;
|
2794 | - if ( point == NULL ) {
|
|
2813 | + if ( point == NULL )
|
|
2814 | + {
|
|
2795 | 2815 | continue;
|
2796 | 2816 | }
|
2797 | 2817 | FT_Pos max_y = point->y;
|
2798 | 2818 | |
2799 | - do {
|
|
2800 | - if ( point->y > max_y ) {
|
|
2819 | + do
|
|
2820 | + {
|
|
2821 | + if ( point->y > max_y )
|
|
2822 | + {
|
|
2801 | 2823 | max_y = point->y;
|
2802 | 2824 | }
|
2803 | 2825 | point = point->next;
|
2804 | 2826 | } while ( point != first_point );
|
2805 | 2827 | |
2806 | - if ( max_y >= highest_min_y - 64 ) {
|
|
2807 | - adjustment_amount = 64 - (highest_min_y - max_y);
|
|
2828 | + if ( max_y >= highest_min_y - 64 )
|
|
2829 | + {
|
|
2830 | + adjustment_amount = 64 - ( highest_min_y - max_y );
|
|
2808 | 2831 | }
|
2809 | 2832 | }
|
2810 | 2833 | |
2811 | - if ( adjustment_amount > 0 ) {
|
|
2834 | + FT_TRACE4(( " Pushing top contour %d units up\n", adjustment_amount ));
|
|
2835 | + if ( adjustment_amount > 0 )
|
|
2836 | + {
|
|
2812 | 2837 | AF_Point point = hints->contours[highest_contour];
|
2813 | 2838 | AF_Point first_point = point;
|
2814 | - if ( point != NULL ) {
|
|
2815 | - do {
|
|
2839 | + if ( point != NULL )
|
|
2840 | + {
|
|
2841 | + do
|
|
2842 | + {
|
|
2816 | 2843 | point->y += adjustment_amount;
|
2817 | 2844 | point = point->next;
|
2818 | 2845 | } while ( point != first_point );
|
2819 | 2846 | }
|
2820 | 2847 | }
|
2821 | 2848 | }
|
2849 | + else
|
|
2850 | + {
|
|
2851 | + FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: No vertical adjustment needed\n" ));
|
|
2852 | + }
|
|
2822 | 2853 | }
|
2823 | 2854 | |
2855 | +#undef FT_COMPONENT
|
|
2856 | +#define FT_COMPONENT aflatin
|
|
2857 | + |
|
2858 | + |
|
2824 | 2859 | |
2825 | 2860 | /* Compute the snapped width of a given stem, ignoring very thin ones. */
|
2826 | 2861 | /* There is a lot of voodoo in this function; changing the hard-coded */
|
... | ... | @@ -3689,7 +3724,7 @@ void af_glyph_hints_apply_adjustments(AF_GlyphHints hints, AF_Dimension dim, FT_ |
3689 | 3724 | af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
|
3690 | 3725 | af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
|
3691 | 3726 | af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
|
3692 | - af_glyph_hints_apply_adjustments(hints, (AF_Dimension) dim, glyph_index, metrics->root.reverse_charmap);
|
|
3727 | + af_glyph_hints_apply_vertical_separation_adjustments(hints, (AF_Dimension) dim, glyph_index, metrics->root.reverse_charmap);
|
|
3693 | 3728 | }
|
3694 | 3729 | }
|
3695 | 3730 |