emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d2e8985b805: Fix compatibility problems with several fonts


From: Po Lu
Subject: master d2e8985b805: Fix compatibility problems with several fonts
Date: Tue, 22 Aug 2023 21:15:28 -0400 (EDT)

branch: master
commit d2e8985b8057173f56d081467ce6a69fc85b1dc5
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 src/sfnt.c | 64 +++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file 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,
   return format6->glyph_index_array[character - format6->first_code];
 }
 
+/* Compare the sfnt_char A with B's end code.  Employed to bisect
+   through a format 8 or 12 table.  */
+
+static int
+sfnt_compare_char (const void *a, const void *b)
+{
+  struct sfnt_cmap_format_8_or_12_group *group;
+
+  group = (struct sfnt_cmap_format_8_or_12_group *) b;
+
+  return ((int) *((sfnt_char *) a)) - group->end_char_code;
+}
+
 /* Look up the glyph corresponding to CHARACTER in the format 8 cmap
    FORMAT8.  Return 0 if no glyph was found.  */
 
@@ -1270,10 +1283,35 @@ sfnt_lookup_glyph_8 (sfnt_char character,
                     struct sfnt_cmap_format_8 *format8)
 {
   uint32_t i;
+  struct sfnt_cmap_format_8_or_12_group *group;
 
   if (character > 0xffffffff)
     return 0;
 
+  if (format8->num_groups > 64)
+    {
+      /* This table is large, likely supplied by a CJK or similar
+        font.  Perform a binary search.  */
+
+      /* Find the group whose END_CHAR_CODE is greater than or equal
+        to CHARACTER.  */
+
+      group = sfnt_bsearch_above (&character, format8->groups,
+                                 format8->num_groups,
+                                 sizeof format8->groups[0],
+                                 sfnt_compare_char);
+
+      if (group->start_char_code > character)
+       /* No glyph matches this group.  */
+       return 0;
+
+      /* Otherwise, use this group to map the character to a
+        glyph.  */
+      return (group->start_glyph_code
+             + character
+             - group->start_char_code);
+    }
+
   for (i = 0; i < format8->num_groups; ++i)
     {
       if (format8->groups[i].start_char_code <= character
@@ -1286,19 +1324,6 @@ sfnt_lookup_glyph_8 (sfnt_char character,
   return 0;
 }
 
-/* Compare the sfnt_char A with B's end code.  Employed to bisect
-   through a format 12 table.  */
-
-static int
-sfnt_compare_char (const void *a, const void *b)
-{
-  struct sfnt_cmap_format_8_or_12_group *group;
-
-  group = (struct sfnt_cmap_format_8_or_12_group *) b;
-
-  return ((int) *((sfnt_char *) a)) - group->end_char_code;
-}
-
 /* Look up the glyph corresponding to CHARACTER in the format 12 cmap
    FORMAT12.  Return 0 if no glyph was found.  */
 
@@ -2009,7 +2034,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
          /* The next byte is a delta to apply to the previous
             value.  Make sure it is in bounds.  */
 
-         if (vec_start + 1 >= glyf->glyphs + glyf->size)
+         if (vec_start + 1 > glyf->glyphs + glyf->size)
            {
              glyph->simple = NULL;
              xfree (simple);
@@ -2026,7 +2051,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
          /* The next word is a delta to apply to the previous value.
             Make sure it is in bounds.  */
 
-         if (vec_start + 2 >= glyf->glyphs + glyf->size)
+         if (vec_start + 2 > glyf->glyphs + glyf->size)
            {
              glyph->simple = NULL;
              xfree (simple);
@@ -2061,7 +2086,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
          /* The next byte is a delta to apply to the previous
             value.  Make sure it is in bounds.  */
 
-         if (vec_start + 1 >= glyf->glyphs + glyf->size)
+         if (vec_start + 1 > glyf->glyphs + glyf->size)
            {
              glyph->simple = NULL;
              xfree (simple);
@@ -2078,7 +2103,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
          /* The next word is a delta to apply to the previous value.
             Make sure it is in bounds.  */
 
-         if (vec_start + 2 >= glyf->glyphs + glyf->size)
+         if (vec_start + 2 > glyf->glyphs + glyf->size)
            {
              glyph->simple = NULL;
              xfree (simple);
@@ -13184,7 +13209,8 @@ sfnt_read_gvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
 
   /* Start reading shared coordinates.  */
 
-  gvar->global_coords = ((sfnt_f2dot14 *) ((char *) gvar + off_size));
+  gvar->global_coords = ((sfnt_f2dot14 *) ((char *) (gvar + 1)
+                                          + off_size));
 
   if (gvar->shared_coord_count)
     {
@@ -13199,7 +13225,7 @@ sfnt_read_gvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
          != coordinate_size)
        goto bail;
 
-      for (i = 0; i <= coordinate_size / sizeof *gvar->global_coords; ++i)
+      for (i = 0; i < coordinate_size / sizeof *gvar->global_coords; ++i)
        sfnt_swap16 (&gvar->global_coords[i]);
     }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]