From: Po Lu <luangruo@yahoo.com>
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 */