Open Bug 1221146 Opened 5 years ago Updated 2 years ago

Fontconfig cannot match downloaded fonts anymore

Categories

(Core :: Graphics: Text, defect, P3)

44 Branch
x86_64
Linux
defect

Tracking

()

ASSIGNED

People

(Reporter: heftig, Assigned: jtd)

References

(Depends on 1 open bug)

Details

(Whiteboard: [gfx-noted])

Attachments

(2 files)

In release Firefox I am able to match downloaded fonts in Fontconfig (family containing `@font-face:` and no file) in order to adjust rendering parameters. In Dev Ed this is not the case anymore.

Disabling `gfx.font_rendering.fontconfig.fontlist.enabled` restores the expected behavior.
Jan, could you provide a snippet or the full text of the fontconfig conf file that you're using? That would help to try and reproduce the problem.
Blocks: 1056479
Flags: needinfo?(jan.steffens)
I used to use

 <match target="font">
  <test name="family" compare="contains">
   <string>@font-face:</string>
  </test>

 </match>

but I think this works now:

 <match target="font">
  <test name="prgname">
   <string>firefox</string>
  </test>
  <!-- no file name matches with |all| and means a downloaded font -->
  <test name="file" qual="all">
   <string>A STRING THAT IS NOT A FILENAME//</string>
  </test>

 </match>
Whiteboard: [gfx-noted]
Here's the font config file I was using, which attempts to use full hinting for most system fonts and slight hinting for downloaded TrueType fonts, as these are often handled poorly by FreeType's native, ClearType-style "subpixel" hinter.
Flags: needinfo?(jan.steffens)
I suppose for testing purposes you could use a config that disables anti-aliasing for downloaded fonts, which is highly visible:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fontconfig SYSTEM "/etc/fonts/fonts.dtd">
<fontconfig>
  <match target="font">
    <edit name="file" mode="append"><string></string></edit>
    <edit name="antialias" mode="assign"><bool>true</bool></edit>
  </match>
  <match target="font">
    <test name="family" compare="contains"><string>@font-face:</string></test>
    <test name="file" qual="all" compare="not_contains"><string>/</string></test>
    <edit name="antialias" mode="assign"><bool>false</bool></edit>
  </match>
</fontconfig>
ni to triage this
Flags: needinfo?(jdaggett)
Starting with Firefox 44, fonts can no longer be replaced with fontconfig (Fedora Linux 23). For example, my ~/.config/fontconfig/fonts.conf contains this to replace a web-font named "Droid Sans" with "Arial":

<match target="pattern">
        <test qual="any" name="family">
                <string>@font-face:Droid Sans</string>
        </test>
        <edit name="family" mode="assign" binding="strong">
                <string>Arial</string>
        </edit> 
</match>

It worked fine until Firefox 43 (official), but Firefox 44 (official) ignores this configuration.

Has this been changed intentionally in Firefox 44, or is this is bug?
Assignee: nobody → jd.bugzilla
Flags: needinfo?(jd.bugzilla)
This fixes the problem. I'm not adding this to src local webfonts as I think those are better considered as local fonts rather than ones downloaded for a page.
Attachment #8714677 - Flags: review?(karlt)
(In reply to Andreas M. Kirchwitz from comment #6)
> Starting with Firefox 44, fonts can no longer be replaced with fontconfig
> (Fedora Linux 23). For example, my ~/.config/fontconfig/fonts.conf contains
> this to replace a web-font named "Droid Sans" with "Arial":
> 
> <match target="pattern">
>         <test qual="any" name="family">
>                 <string>@font-face:Droid Sans</string>
>         </test>
>         <edit name="family" mode="assign" binding="strong">
>                 <string>Arial</string>
>         </edit> 
> </match>
> 
> It worked fine until Firefox 43 (official), but Firefox 44 (official)
> ignores this configuration.
> 
> Has this been changed intentionally in Firefox 44, or is this is bug?

The patch adds the '@font-face:' prefix but I don't think it's going to fix the regression you're experiencing. The new code in Firefox 44 handles font selection internally. It uses fontconfig to look up platform family names but it won't allow substitutions to webfont font families like this.

We needed to make this change to handle the complex loading behavior associated with the unicode-range descriptor of @font-face rules.
Comment on attachment 8714677 [details] [diff] [review]
patch, prepend @font-face: to the font family name for webfonts

I think it would be better to do this after FcFreeTypeQueryFace() in the
constructor.  That makes it is clear that mFontPattern is only ever used with
this family and saves recreating the family each time a gfxFont instance is
created.  There's also no need then to check mIsDataUserFont.

A comment to explain this is added to the family would be helpful.  Something
like:

// Adjust the family name so that fontconfig rules can easily distinguish
// between web fonts and platform fonts.

>+        NS_ConvertUTF16toUTF8 fam(mFamilyName);
>+        nsAutoCString patternFamily = NS_LITERAL_CSTRING("@font-face:") + fam;

I expect something like the following would save the buffer copy of fam and
convert directly into patternFamily:

  nsAutoCString patternFamily = NS_LITERAL_CSTRING("@font-face:);
  AppendUTF16toUTF8(mFamilyName, patternFamily);

>+        FcPatternDel(mFontPattern, FC_FAMILY);
>+        FcPatternAddString(mFontPattern, FC_FAMILY,
>+                           ToFcChar8Ptr(patternFamily.get()));

This is deleting all the family names found in the font and replacing them
with a single family name based on mFamilyName.  I assume mFamilyName is the
name in the @font-face rule?  That's all fine I think, as that is what
gfxFontconfigFonts does.  However, now the FC_FAMILYLANG entries from the font
don't necessarily correspond with FC_FAMILY from the @font-face family.  I
guess perhaps FC_FAMILYLANG should be given a single entry corresponding to
the single family from the @font-face rule, but the old code simply removed
the FC_FAMILYLANG entries, so doing that should be fine too.
Attachment #8714677 - Flags: review?(karlt) → review-
(In reply to Karl Tomlinson (ni?:karlt) from comment #9)
> A comment to explain this is added to the family would be helpful.

explain *why* ...
(In reply to Karl Tomlinson (ni?:karlt) from comment #9)
> Comment on attachment 8714677 [details] [diff] [review]
> patch, prepend @font-face: to the font family name for webfonts
> 
> I think it would be better to do this after FcFreeTypeQueryFace() in the
> constructor.  That makes it is clear that mFontPattern is only ever used with
> this family and saves recreating the family each time a gfxFont instance is
> created.  There's also no need then to check mIsDataUserFont.

Yeah, I think I agree with you here. It's a bigger change because the current code sets the family name in gfxUserFontEntry::LoadPlatformFont after the constructor is called. But this would make sense to change.

I'll rework the interfaces to MakePlatformFont and LookupLocalFont so that the family name is set within the constructor. Then simplify the patch here.
Depends on: 1248493
(In reply to John Daggett (:jtd) from comment #8)
> (In reply to Andreas M. Kirchwitz from comment #6)
> > Starting with Firefox 44, fonts can no longer be replaced with fontconfig
> > (Fedora Linux 23). For example, my ~/.config/fontconfig/fonts.conf contains
> > this to replace a web-font named "Droid Sans" with "Arial":
> > 
> > <match target="pattern">
> >         <test qual="any" name="family">
> >                 <string>@font-face:Droid Sans</string>
> >         </test>
> >         <edit name="family" mode="assign" binding="strong">
> >                 <string>Arial</string>
> >         </edit> 
> > </match>
> > 
> > It worked fine until Firefox 43 (official), but Firefox 44 (official)
> > ignores this configuration.
> > 
> > Has this been changed intentionally in Firefox 44, or is this is bug?
> 
> The patch adds the '@font-face:' prefix but I don't think it's going to fix
> the regression you're experiencing. The new code in Firefox 44 handles font
> selection internally. It uses fontconfig to look up platform family names
> but it won't allow substitutions to webfont font families like this.
> 
> We needed to make this change to handle the complex loading behavior
> associated with the unicode-range descriptor of @font-face rules.

After reading the discussion on this bug and the related bug 1243194, but the parent post in particular, it became clear to me that the only way to reliably keep the control that I'm supposed to have (per the original WWW vision) was to disable webfonts entirely, with gfx.downloadable_fonts.enabled=false.  The next step, after you take away _that_ setting, is browser.display.use_document_fonts=0; the next after that, give up Firefox.

So much for improving Firefox on Linux.
Modifying rendering parameters of downloaded fonts doesn't work at all for me anymore, even ignoring the "@font-face" matching issue.  An example would be something like this:

    <match target="font">
       <test name="family" compare="contains">
            <string>Neue</string>
        </test>
        <edit name="autohint">
            <bool>true</bool>
        </edit>
    </match>

The match and edit work fine (confirmed with FC_DEBUG) but Firefox seems to not honor the autohint change.  Without this, some fonts are near unreadable without the proper configuration.  I can't figure out where the configuration they're using comes from, either.  Even if I change my overall default in my fonts.conf to autohint true, the downloaded fonts in Firefox are still using autohint false (which is fontconfig's builtin default for that, I believe - maybe that's where it's coming from?)

Everything works fine after turning off "gfx.font_rendering.fontconfig.fontlist.enabled".  Are there any alternate/long-term solutions?  Besides disabling downloadable fonts.
My last comment can be disregarded.  I was able to get back control of the rendering parameters on DL'ed fonts.  The newer 44+ font behavior had an effect on some of the matches/edits I'm doing in my fonts.conf, and it was triggering some unexpected edits that were never triggered at all before.  After re-working my fonts.conf, now I'm able to get the same behavior regardless of the setting of "gfx.font_rendering.fontconfig.fontlist.enabled".
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
You need to log in before you can comment on or make changes to this bug.