aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-08-23 09:08:03 +0800
committerPo Lu2023-08-23 09:15:16 +0800
commitd2e8985b8057173f56d081467ce6a69fc85b1dc5 (patch)
treecf07ef5c9f0c06fdc7d754079396f12b356298dd /src
parent255b7e1a046cbf9a745d58080d74983bfe205859 (diff)
downloademacs-d2e8985b8057173f56d081467ce6a69fc85b1dc5.tar.gz
emacs-d2e8985b8057173f56d081467ce6a69fc85b1dc5.zip
Fix compatibility problems with several fonts
* src/sfnt.c (sfnt_lookup_glyph_8): Perform binary search instead of combing through each group if the table is large. (sfnt_read_simple_glyph): Avoid losing if the last byte of a vector is identical to the last byte of the glyph data. (sfnt_read_gvar_table): Don't overwrite gvar table data while reading shared coordinates.
Diffstat (limited to 'src')
-rw-r--r--src/sfnt.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/src/sfnt.c b/src/sfnt.c
index e71ff9ae101..bf55e9302b0 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -1262,6 +1262,19 @@ sfnt_lookup_glyph_6 (sfnt_char character,
1262 return format6->glyph_index_array[character - format6->first_code]; 1262 return format6->glyph_index_array[character - format6->first_code];
1263} 1263}
1264 1264
1265/* Compare the sfnt_char A with B's end code. Employed to bisect
1266 through a format 8 or 12 table. */
1267
1268static int
1269sfnt_compare_char (const void *a, const void *b)
1270{
1271 struct sfnt_cmap_format_8_or_12_group *group;
1272
1273 group = (struct sfnt_cmap_format_8_or_12_group *) b;
1274
1275 return ((int) *((sfnt_char *) a)) - group->end_char_code;
1276}
1277
1265/* Look up the glyph corresponding to CHARACTER in the format 8 cmap 1278/* Look up the glyph corresponding to CHARACTER in the format 8 cmap
1266 FORMAT8. Return 0 if no glyph was found. */ 1279 FORMAT8. Return 0 if no glyph was found. */
1267 1280
@@ -1270,10 +1283,35 @@ sfnt_lookup_glyph_8 (sfnt_char character,
1270 struct sfnt_cmap_format_8 *format8) 1283 struct sfnt_cmap_format_8 *format8)
1271{ 1284{
1272 uint32_t i; 1285 uint32_t i;
1286 struct sfnt_cmap_format_8_or_12_group *group;
1273 1287
1274 if (character > 0xffffffff) 1288 if (character > 0xffffffff)
1275 return 0; 1289 return 0;
1276 1290
1291 if (format8->num_groups > 64)
1292 {
1293 /* This table is large, likely supplied by a CJK or similar
1294 font. Perform a binary search. */
1295
1296 /* Find the group whose END_CHAR_CODE is greater than or equal
1297 to CHARACTER. */
1298
1299 group = sfnt_bsearch_above (&character, format8->groups,
1300 format8->num_groups,
1301 sizeof format8->groups[0],
1302 sfnt_compare_char);
1303
1304 if (group->start_char_code > character)
1305 /* No glyph matches this group. */
1306 return 0;
1307
1308 /* Otherwise, use this group to map the character to a
1309 glyph. */
1310 return (group->start_glyph_code
1311 + character
1312 - group->start_char_code);
1313 }
1314
1277 for (i = 0; i < format8->num_groups; ++i) 1315 for (i = 0; i < format8->num_groups; ++i)
1278 { 1316 {
1279 if (format8->groups[i].start_char_code <= character 1317 if (format8->groups[i].start_char_code <= character
@@ -1286,19 +1324,6 @@ sfnt_lookup_glyph_8 (sfnt_char character,
1286 return 0; 1324 return 0;
1287} 1325}
1288 1326
1289/* Compare the sfnt_char A with B's end code. Employed to bisect
1290 through a format 12 table. */
1291
1292static int
1293sfnt_compare_char (const void *a, const void *b)
1294{
1295 struct sfnt_cmap_format_8_or_12_group *group;
1296
1297 group = (struct sfnt_cmap_format_8_or_12_group *) b;
1298
1299 return ((int) *((sfnt_char *) a)) - group->end_char_code;
1300}
1301
1302/* Look up the glyph corresponding to CHARACTER in the format 12 cmap 1327/* Look up the glyph corresponding to CHARACTER in the format 12 cmap
1303 FORMAT12. Return 0 if no glyph was found. */ 1328 FORMAT12. Return 0 if no glyph was found. */
1304 1329
@@ -2009,7 +2034,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
2009 /* The next byte is a delta to apply to the previous 2034 /* The next byte is a delta to apply to the previous
2010 value. Make sure it is in bounds. */ 2035 value. Make sure it is in bounds. */
2011 2036
2012 if (vec_start + 1 >= glyf->glyphs + glyf->size) 2037 if (vec_start + 1 > glyf->glyphs + glyf->size)
2013 { 2038 {
2014 glyph->simple = NULL; 2039 glyph->simple = NULL;
2015 xfree (simple); 2040 xfree (simple);
@@ -2026,7 +2051,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
2026 /* The next word is a delta to apply to the previous value. 2051 /* The next word is a delta to apply to the previous value.
2027 Make sure it is in bounds. */ 2052 Make sure it is in bounds. */
2028 2053
2029 if (vec_start + 2 >= glyf->glyphs + glyf->size) 2054 if (vec_start + 2 > glyf->glyphs + glyf->size)
2030 { 2055 {
2031 glyph->simple = NULL; 2056 glyph->simple = NULL;
2032 xfree (simple); 2057 xfree (simple);
@@ -2061,7 +2086,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
2061 /* The next byte is a delta to apply to the previous 2086 /* The next byte is a delta to apply to the previous
2062 value. Make sure it is in bounds. */ 2087 value. Make sure it is in bounds. */
2063 2088
2064 if (vec_start + 1 >= glyf->glyphs + glyf->size) 2089 if (vec_start + 1 > glyf->glyphs + glyf->size)
2065 { 2090 {
2066 glyph->simple = NULL; 2091 glyph->simple = NULL;
2067 xfree (simple); 2092 xfree (simple);
@@ -2078,7 +2103,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
2078 /* The next word is a delta to apply to the previous value. 2103 /* The next word is a delta to apply to the previous value.
2079 Make sure it is in bounds. */ 2104 Make sure it is in bounds. */
2080 2105
2081 if (vec_start + 2 >= glyf->glyphs + glyf->size) 2106 if (vec_start + 2 > glyf->glyphs + glyf->size)
2082 { 2107 {
2083 glyph->simple = NULL; 2108 glyph->simple = NULL;
2084 xfree (simple); 2109 xfree (simple);
@@ -13184,7 +13209,8 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
13184 13209
13185 /* Start reading shared coordinates. */ 13210 /* Start reading shared coordinates. */
13186 13211
13187 gvar->global_coords = ((sfnt_f2dot14 *) ((char *) gvar + off_size)); 13212 gvar->global_coords = ((sfnt_f2dot14 *) ((char *) (gvar + 1)
13213 + off_size));
13188 13214
13189 if (gvar->shared_coord_count) 13215 if (gvar->shared_coord_count)
13190 { 13216 {
@@ -13199,7 +13225,7 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
13199 != coordinate_size) 13225 != coordinate_size)
13200 goto bail; 13226 goto bail;
13201 13227
13202 for (i = 0; i <= coordinate_size / sizeof *gvar->global_coords; ++i) 13228 for (i = 0; i < coordinate_size / sizeof *gvar->global_coords; ++i)
13203 sfnt_swap16 (&gvar->global_coords[i]); 13229 sfnt_swap16 (&gvar->global_coords[i]);
13204 } 13230 }
13205 13231