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.
This commit is contained in:
Po Lu 2023-10-22 09:06:28 +08:00
parent 8c15515b62
commit 6f87ee0e3a
3 changed files with 116 additions and 17 deletions

View file

@ -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;

View file

@ -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

View file

@ -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 */