From: Po Lu Date: Mon, 21 Aug 2023 12:44:23 +0000 (+0800) Subject: Properly enumerate GX fonts of the same family with divergent styles X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=fb5e1b21fbf3475abffc3c0de31437120904f42a;p=emacs.git Properly enumerate GX fonts of the same family with divergent styles * 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. --- diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi index a85589f864c..cee5406b840 100644 --- a/doc/emacs/android.texi +++ b/doc/emacs/android.texi @@ -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 diff --git a/src/sfntfont.c b/src/sfntfont.c index c48339b6b66..e2dfdaff3b6 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -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;