]> git.eshelyaron.com Git - emacs.git/commitdiff
Properly enumerate GX fonts of the same family with divergent styles
authorPo Lu <luangruo@yahoo.com>
Mon, 21 Aug 2023 12:44:23 +0000 (20:44 +0800)
committerPo Lu <luangruo@yahoo.com>
Mon, 21 Aug 2023 12:45:34 +0000 (20:45 +0800)
* doc/emacs/android.texi (Android Fonts): Revise explanation of
GX font replacement during font enumeration.

* src/sfntfont.c (sfnt_replace_fonts_p): If PREV and DESC are of
the same family and both are GX fonts, restrict actions taken to
removing duplicate styles from PREV.  Reported by a user who
tried to install GX versions of Cascadia Mono, which are
distributed as two files providing the bold and italic variation
axes respectively.

doc/emacs/android.texi
src/sfntfont.c

index a85589f864ce7065ec60b71d73ebe0d026d30e4d..cee5406b84034e185937929c9c75d78e65511a7a 100644 (file)
@@ -692,18 +692,20 @@ always be Droid Sans Mono.
 @cindex TrueType GX fonts, android
 @cindex distortable fonts, android
 
-  Like on X systems, Emacs supports distortable fonts under Android.
+  As on X systems, Emacs supports distortable fonts under Android.
 These fonts (also termed ``TrueType GX fonts'', ``variable fonts'',
 and ``multiple master fonts'') provide multiple different styles
 (``Bold'', ``Italic'', etc) using a single font file.
 
-  When a user-installed distortable font is found, each font that a
+  When a user-installed distortable font is found, each style that a
 previously discovered font provided will no longer be used.  In
-addition, any previously specified distortable fonts with the same
-family name are also removed.  When a conventional font is found, any
-previous conventional font with the same style and family will be
-removed; distortable fonts with the same family will no longer be used
-to provide that style.
+addition, any previously installed distortable fonts with the same
+family name are also disregarded, provided that the new distortable
+font supplies a superset of the styles furnished by the previously
+installed font.  When a conventional font is found, any previous
+conventional font with the same style and family will be removed;
+distortable fonts with the same family will no longer be used to
+provide that style.
 
 @node Android Troubleshooting
 @section Troubleshooting Startup Problems on Android
index c48339b6b66ace6c33a7167ecf75c1728d283a93..e2dfdaff3b657b07b7128c5de5a64ed65590728c 100644 (file)
@@ -834,6 +834,9 @@ sfnt_grok_registry (int fd, struct sfnt_font_desc *desc,
    newer font description DESC, and should be removed from the list of
    system fonts.
 
+   If both PREV and DESC are variable fonts, remove styles within PREV
+   that overlap with DESC and return false.
+
    If PREV is a variable font, potentially adjust its list of
    instances.  */
 
@@ -841,8 +844,8 @@ static bool
 sfnt_replace_fonts_p (struct sfnt_font_desc *prev,
                      struct sfnt_font_desc *desc)
 {
-  int i, width, weight, slant, count_instance;
-  Lisp_Object tem;
+  int i, j, width, weight, slant, count_instance;
+  Lisp_Object tem, tem1;
   bool family_equal_p;
 
   family_equal_p = !NILP (Fstring_equal (prev->family,
@@ -851,7 +854,54 @@ sfnt_replace_fonts_p (struct sfnt_font_desc *prev,
   if ((!NILP (desc->instances)
        || !NILP (Fstring_equal (prev->style, desc->style)))
       && family_equal_p)
-    return true;
+    {
+      /* If both inputs are GX fonts...  */
+      if (!NILP (desc->instances) && !NILP (prev->instances))
+       {
+         /* ...iterate over each of the styles provided by PREV.  If
+            they match any styles within DESC, remove the old style
+            from PREV.  */
+
+         count_instance = 0;
+         for (i = 0; i < ASIZE (prev->instances); ++i)
+           {
+             tem = AREF (prev->instances, i);
+
+             if (NILP (tem))
+               continue;
+
+             for (j = 0; j < ASIZE (desc->instances); ++j)
+               {
+                 tem1 = AREF (desc->instances, j);
+
+                 if (NILP (tem1))
+                   continue;
+
+                 if (!NILP (Fequal (tem1, tem)))
+                   {
+                     /* tem1 is identical to tem, so opt for it over
+                        tem.  */
+                     ASET (prev->instances, i, Qnil);
+                     goto next;
+                   }
+               }
+
+             /* Increment the number of instances remaining within
+                PREV.  */
+             count_instance++;
+
+           next:
+             ;
+           }
+
+         /* Return true if no instances remain inside
+            PREV->instances, so that the now purposeless desc may be
+            removed.  */
+         return !count_instance;
+       }
+
+      return true;
+    }
 
   if (NILP (prev->instances) || !family_equal_p)
     return false;