]> git.eshelyaron.com Git - emacs.git/commitdiff
Enumerate default UVS glyphs
authorPo Lu <luangruo@yahoo.com>
Sun, 22 Oct 2023 01:06:28 +0000 (09:06 +0800)
committerPo Lu <luangruo@yahoo.com>
Sun, 22 Oct 2023 01:06:28 +0000 (09:06 +0800)
* 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.

src/sfnt.c
src/sfnt.h
src/sfntfont.c

index 348cff604af42d3c964e4c4cce8bb5f8e34f1fa1..01d061be79c338d1bc7d8277b3be3e79c10a3f57 100644 (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);
+}
+
 \f
 
 #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;
 
index 6602d2400517d60157a2a5a2ebb58cee691454dd..41c1f6f74e8666ac218e837d3ab6c6c76dac4479 100644 (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
+
 \f
 
 #ifdef HAVE_MMAP
index 2c58de31a163f701352aea733d2f7d6e6e85d49e..35b37396ccdddaa5f6459ae3b933d1a520fa41a2 100644 (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 */
 
 \f