From: Po Lu Date: Sun, 22 Oct 2023 01:06:28 +0000 (+0800) Subject: Enumerate default UVS glyphs X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6f87ee0e3a0727e16079778a4264e6e35cd7f3a8;p=emacs.git Enumerate default UVS glyphs * src/sfnt.c (sfnt_compare_unicode_value_range) (sfnt_is_character_default): New functions. (sfnt_test_uvs): Print and verify the default UVS table. * src/sfnt.h: Update prototypes. * src/sfntfont.c (sfntfont_get_variation_glyphs): Index the cmap with the default glyph, and insert it within VARIATIONS if character is present within a selector record's default UVS table. --- diff --git a/src/sfnt.c b/src/sfnt.c index 348cff604af..01d061be79c 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -12717,6 +12717,26 @@ sfnt_compare_uvs_mapping (const void *k, const void *v) return 1; } +/* Compare *(sfnt_char *) K to the Unicode value range V. */ + +static int +sfnt_compare_unicode_value_range (const void *k, const void *v) +{ + const sfnt_char *key; + const struct sfnt_unicode_value_range *value; + + key = k; + value = v; + + if (*key < value->start_unicode_value) + return -1; + else if ((*key - value->start_unicode_value + <= value->additional_count)) + return 0; + + return 1; +} + /* Return the ID of a variation glyph for the character C in the nondefault UVS mapping table UVS. @@ -12736,6 +12756,21 @@ sfnt_variation_glyph_for_char (struct sfnt_nondefault_uvs_table *uvs, return mapping ? mapping->base_character_value : 0; } +/* Return whether the character C is present in the default UVS + mapping table UVS. */ + +TEST_STATIC bool +sfnt_is_character_default (struct sfnt_default_uvs_table *uvs, + sfnt_char c) +{ + /* UVS->ranges comprises ranges of characters sorted in increasing + order; these ranges cannot overlap. */ + + return (bsearch (&c, uvs->ranges, uvs->num_unicode_value_ranges, + sizeof *uvs->ranges, + sfnt_compare_unicode_value_range) != NULL); +} + #if defined HAVE_MMAP && !defined TEST @@ -19191,10 +19226,11 @@ static void sfnt_test_uvs (int fd, struct sfnt_cmap_format_14 *format14) { struct sfnt_uvs_context *context; - size_t i, j; + size_t i, j, k; sfnt_glyph glyph; sfnt_char c; struct sfnt_nondefault_uvs_table *uvs; + struct sfnt_default_uvs_table *default_uvs; context = sfnt_create_uvs_context (format14, fd); @@ -19209,6 +19245,27 @@ sfnt_test_uvs (int fd, struct sfnt_cmap_format_14 *format14) for (i = 0; i < context->num_records; ++i) { + if (context->records[i].default_uvs) + { + default_uvs = context->records[i].default_uvs; + + for (j = 0; j < default_uvs->num_unicode_value_ranges; ++j) + { + fprintf (stderr, " Default UVS: %u, %u\n", + default_uvs->ranges[j].start_unicode_value, + default_uvs->ranges[j].additional_count); + + c = default_uvs->ranges[j].start_unicode_value; + k = 0; + + for (; k <= default_uvs->ranges[j].additional_count; ++k) + { + if (!sfnt_is_character_default (default_uvs, c + k)) + abort (); + } + } + } + if (!context->records[i].nondefault_uvs) continue; diff --git a/src/sfnt.h b/src/sfnt.h index 6602d240051..41c1f6f74e8 100644 --- a/src/sfnt.h +++ b/src/sfnt.h @@ -1526,6 +1526,12 @@ extern sfnt_glyph sfnt_variation_glyph_for_char (PROTOTYPE); #undef PROTOTYPE +#define PROTOTYPE struct sfnt_default_uvs_table *, sfnt_char + +extern bool sfnt_is_character_default (PROTOTYPE); + +#undef PROTOTYPE + #ifdef HAVE_MMAP diff --git a/src/sfntfont.c b/src/sfntfont.c index 2c58de31a16..35b37396ccd 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -3720,9 +3720,10 @@ sfntfont_get_variation_glyphs (struct font *font, int c, unsigned variations[256]) { struct sfnt_font_info *info; - size_t i; + size_t i, index; int n; struct sfnt_mapped_variation_selector_record *record; + sfnt_glyph default_glyph; info = (struct sfnt_font_info *) font; n = 0; @@ -3743,12 +3744,37 @@ sfntfont_get_variation_glyphs (struct font *font, int c, && info->uvs->records[i].selector < 0xfe00) ++i; + /* Get the glyph represented by C, used when C is present within a + default value table. */ + + default_glyph = sfntfont_lookup_glyph (info, c); + /* Fill in selectors 0 to 15. */ while (i < info->uvs->num_records && info->uvs->records[i].selector <= 0xfe0f) { record = &info->uvs->records[i]; + index = info->uvs->records[i].selector - 0xfe00 + 16; + + /* Handle invalid unsorted tables. */ + + if (record->selector < 0xfe00) + return 0; + + /* If there are default mappings in this record, ascertain if + this glyph matches one of them. */ + + if (record->default_uvs + && sfnt_is_character_default (record->default_uvs, c)) + { + variations[index] = default_glyph; + + if (default_glyph) + ++n; + + goto next_selector; + } /* If record has no non-default mappings, continue on to the next selector. */ @@ -3756,18 +3782,13 @@ sfntfont_get_variation_glyphs (struct font *font, int c, if (!record->nondefault_uvs) goto next_selector; - /* Handle invalid unsorted tables. */ - - if (record->selector < 0xfe00) - return 0; - /* Find the glyph ID associated with C and put it in VARIATIONS. */ - variations[info->uvs->records[i].selector - 0xfe00] + variations[index] = sfnt_variation_glyph_for_char (record->nondefault_uvs, c); - if (variations[info->uvs->records[i].selector - 0xfe00]) + if (variations[index]) ++n; next_selector: @@ -3787,6 +3808,26 @@ sfntfont_get_variation_glyphs (struct font *font, int c, && info->uvs->records[i].selector <= 0xe01ef) { record = &info->uvs->records[i]; + index = info->uvs->records[i].selector - 0xe0100 + 16; + + /* Handle invalid unsorted tables. */ + + if (record->selector < 0xe0100) + return 0; + + /* If there are default mappings in this record, ascertain if + this glyph matches one of them. */ + + if (record->default_uvs + && sfnt_is_character_default (record->default_uvs, c)) + { + variations[index] = default_glyph; + + if (default_glyph) + ++n; + + goto next_selector_1; + } /* If record has no non-default mappings, continue on to the next selector. */ @@ -3794,18 +3835,13 @@ sfntfont_get_variation_glyphs (struct font *font, int c, if (!record->nondefault_uvs) goto next_selector_1; - /* Handle invalid unsorted tables. */ - - if (record->selector < 0xe0100) - return 0; - /* Find the glyph ID associated with C and put it in VARIATIONS. */ - variations[info->uvs->records[i].selector - 0xe0100 + 16] + variations[index] = sfnt_variation_glyph_for_char (record->nondefault_uvs, c); - if (variations[info->uvs->records[i].selector - 0xe0100 + 16]) + if (variations[index]) ++n; next_selector_1: @@ -3841,7 +3877,7 @@ sfntfont_detect_sigbus (void *addr) return false; } -#endif +#endif /* HAVE_MMAP */