Bug 36351 - [Qt] @font-face does not work with local and remote fonts
Summary: [Qt] @font-face does not work with local and remote fonts
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Qt (show other bugs)
Version: 528+ (Nightly build)
Hardware: Other Linux
: P2 Normal
Assignee: Nobody
URL:
Keywords: Qt, QtTriaged
Depends on: 55036
Blocks:
  Show dependency treegraph
 
Reported: 2010-03-19 00:52 PDT by Dominik Holland
Modified: 2014-02-03 03:16 PST (History)
17 users (show)

See Also:


Attachments
Qt Example (42.91 KB, application/x-compressed-tar)
2010-03-19 00:52 PDT, Dominik Holland
no flags Details
Patch (4.22 KB, patch)
2010-11-10 12:35 PST, Robert Hogan
no flags Details | Formatted Diff | Diff
Patch (4.88 KB, patch)
2010-11-19 12:37 PST, Robert Hogan
no flags Details | Formatted Diff | Diff
Patch to fix this problem for fontconfig based systems (3.06 KB, patch)
2010-12-08 06:16 PST, Jiang Jiang
no flags Details | Formatted Diff | Diff
Qt font check for src:local (1.08 KB, patch)
2011-11-23 02:32 PST, Florian Hänel
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dominik Holland 2010-03-19 00:52:31 PDT
Created attachment 51134 [details]
Qt Example

When calling @font-face the font will not be installed. So it can't be used in the HTML file. And a standard font is used.
Manually installing the Font (Moving to /usr/share/fonts/, or call QFontDatabase::addApplicationFont()) works properly.
And the font is displayed in the HTML file.

Changing the @font-face src Argument to relative Path, absolute Path, ResourceFile Path, does not have any effect to the problem.

The Bug occurs on Qt Versions > Qt 4.5.2

The following application should display the Text in a Fancy-Font
Comment 1 Simon Hausmann 2010-03-19 05:57:37 PDT
Ok, I can confirm that this bug exists. It is caused by the use of local() in the css:

@font-face {font-family: AgentOrange ; src: local(AgentOrange), url(AgentOrange.ttf);}


The choice of local() as a resource for the font results in WebKit trying to use a locally installed font first, and only then fall back to the remote url to download the font.

The way the font system works for the Qt port in WebKit is that we satisfy all requests for fonts, because it's Qt that tries to determine if a font exists or not. We do not verify the existance of a font in the QFontDatabase, in FontCache::createFontPlatformData.

If you remove the local() from the testcase, then the font is loaded.
Comment 2 Jocelyn Turcotte 2010-09-27 07:56:22 PDT
Related: Bug #36351
Comment 3 Jocelyn Turcotte 2010-09-27 07:57:15 PDT
(In reply to comment #2)
> Related: Bug #36351
Err... I mean Bug #29433
Comment 4 Peter Lai 2010-10-30 02:45:57 PDT
This bug is preventing font-face from working on most pages that use custom fonts.

Since Paul Irish introduced the 'Bulletproof @font-face syntax' (http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/), it seems most people have adopted it.

Some notable examples:
http://www.fontsquirrel.com/
http://font-face.com/
Comment 5 Robert Hogan 2010-11-09 15:15:10 PST
(In reply to comment #1)
> Ok, I can confirm that this bug exists. It is caused by the use of local() in the css:
> 
> @font-face {font-family: AgentOrange ; src: local(AgentOrange), url(AgentOrange.ttf);}
> 
> 
> The choice of local() as a resource for the font results in WebKit trying to use a locally installed font first, and only then fall back to the remote url to download the font.
> 
> The way the font system works for the Qt port in WebKit is that we satisfy all requests for fonts, because it's Qt that tries to determine if a font exists or not. We do not verify the existance of a font in the QFontDatabase, in FontCache::createFontPlatformData.

Couldn't we just query QFontDatabase::families() and styles() in FontCache::createFontPlatformData to see if we have the font local() wants?
Comment 6 Robert Hogan 2010-11-10 12:35:34 PST
Created attachment 73526 [details]
Patch
Comment 7 Robert Hogan 2010-11-10 12:39:12 PST
(In reply to comment #6)
> Created an attachment (id=73526) [details]
> Patch

Apart from fixing the issue this patch has a very interesting side-effect on my system - it allows my layout test render tree results to match almost exactly those given for mac! (Usually they are quite wide of the mark.)

I can even see the effect in QtTestBrowser - the rendering of results is much cleaner.

This may be just local to my system - there could be some fonts missing on my Kubuntu installation. But I would be very grateful if someone else could try it out and see.
Comment 8 Robert Hogan 2010-11-10 12:58:57 PST
This also fixes: font-face-multiple-faces.html.
(Specifically the rendering of the courier fonts there.)

Unfortunately the patch also breaks a lot of our platform-specific render tree expected results. Ouch. I'm hoping this can be fixed in the DRT.
Comment 9 Robert Hogan 2010-11-17 13:37:24 PST
(In reply to comment #8)
> This also fixes: font-face-multiple-faces.html.
> (Specifically the rendering of the courier fonts there.)
> 
> Unfortunately the patch also breaks a lot of our platform-specific render tree expected results. Ouch. I'm hoping this can be fixed in the DRT.

The layout test breakage is because my patch is querying the fonts by the 'proper' name supplied by WebCore, e.g. 'Times', 'Helvetica' - but the DRT adds look-alikes from the test fonts folder under the 'Nimbus' family. It is correct to attempt to match on family name, it is what other ports do, but DRT is obviously a special case since our font-alikes are designed to match on metrics when called with QFont(familyName) or similar.

The rather unlovely solution to this is to map the names of fonts used in the layout tests to our look-alikes when we know it's a DRT run and query those. That will allow us to fix this bug without breaking layout tests and also pass a couple we're currently skipping.
Comment 10 Robert Hogan 2010-11-19 12:37:42 PST
Created attachment 74414 [details]
Patch
Comment 11 Robert Hogan 2010-11-19 12:42:45 PST
(In reply to comment #10)
> Created an attachment (id=74414) [details]
> Patch

Benjamin, could you ask Jiang to take a look at this? I'm pretty sure I'm guilty of API abuse here but I cannot find any other way of establishing the system-default font fontconfig chooses when a non-existent font is requested.

So for example, if I do:

fc-cache nonexistentfont

I always get 'Deja Sans', likewise if I inspect QFontInfo::family() in QFont("nonexistentfont"). 

But QFont::defaultFamily() and QFont::lastResortFamily() give me another font entirely - usually the Nimbus Sans L loaded by DumpRenderTreeQt. I must be missing a trick.
Comment 12 Robert Hogan 2010-11-19 12:43:53 PST
(In reply to comment #10)
> Created an attachment (id=74414) [details]
> Patch

Also, tested this patch against Ossy's QT-Bat VM and it causes no regressions.
Comment 13 Robert Hogan 2010-11-24 02:22:03 PST
I asked Jiang about this and he said:

"I'm afraid there is no reliable way in Qt now to verify if a font family exists. Can you please create a bug report in http://bugreports.qt.nokia.com/ ? The workaround has to be platform specific."

See http://bugreports.qt.nokia.com/browse/QTBUG-15575

Should we fix it for now in QtWebKit using the attached patch?
Comment 14 Jiang Jiang 2010-11-24 03:17:47 PST
(In reply to comment #13)
> I asked Jiang about this and he said:
> 
> "I'm afraid there is no reliable way in Qt now to verify if a font family exists. Can you please create a bug report in http://bugreports.qt.nokia.com/ ? The workaround has to be platform specific."
> 
> See http://bugreports.qt.nokia.com/browse/QTBUG-15575
> 
> Should we fix it for now in QtWebKit using the attached patch?

Hi Robert, could you please try either QFont(family).exactMatch() or QFontInfo(family).exactMatch()? I didn't realize that's the API you need in my first reply.
Comment 15 Robert Hogan 2010-11-24 04:38:55 PST
(In reply to comment #14)
> 
> Hi Robert, could you please try either QFont(family).exactMatch() or QFontInfo(family).exactMatch()? I didn't realize that's the API you need in my first reply.

Unfortunately these don't do the job either. This is because they don't cater for cases where fontconfig has been been given a matching target for a font family. In the case of the DRT for example, 'Times' is mapped to 'Nimbus Roman No 9' by the testfonts package loaded to fontconfig at runtime. exactMatch() will always return false where such targets are configured, which is correct for exactMatch() I think but QtWebKit needs to know if a match was found that isn't the system default rather than a font with exactly the same name.
Comment 16 Jiang Jiang 2010-11-24 04:48:30 PST
(In reply to comment #15)
> (In reply to comment #14)
> > 
> > Hi Robert, could you please try either QFont(family).exactMatch() or QFontInfo(family).exactMatch()? I didn't realize that's the API you need in my first reply.
> 
> Unfortunately these don't do the job either. This is because they don't cater for cases where fontconfig has been been given a matching target for a font family. In the case of the DRT for example, 'Times' is mapped to 'Nimbus Roman No 9' by the testfonts package loaded to fontconfig at runtime. exactMatch() will always return false where such targets are configured, which is correct for exactMatch() I think but QtWebKit needs to know if a match was found that isn't the system default rather than a font with exactly the same name.

I see, it has to be done after the substitution.
Comment 17 Robert Hogan 2010-11-29 13:45:36 PST
(In reply to comment #16)
> > Unfortunately these don't do the job either. This is because they don't cater for cases where fontconfig has been been given a matching target for a font family. In the case of the DRT for example, 'Times' is mapped to 'Nimbus Roman No 9' by the testfonts package loaded to fontconfig at runtime. exactMatch() will always return false where such targets are configured, which is correct for exactMatch() I think but QtWebKit needs to know if a match was found that isn't the system default rather than a font with exactly the same name.
> 
> I see, it has to be done after the substitution.

So, can someone say yay or nay to this patch?
Comment 18 Jiang Jiang 2010-11-29 13:56:59 PST
(In reply to comment #17)
> (In reply to comment #16)
> > > Unfortunately these don't do the job either. This is because they don't cater for cases where fontconfig has been been given a matching target for a font family. In the case of the DRT for example, 'Times' is mapped to 'Nimbus Roman No 9' by the testfonts package loaded to fontconfig at runtime. exactMatch() will always return false where such targets are configured, which is correct for exactMatch() I think but QtWebKit needs to know if a match was found that isn't the system default rather than a font with exactly the same name.
> > 
> > I see, it has to be done after the substitution.
> 
> So, can someone say yay or nay to this patch?

Hi Robert, I appreciate your efforts, however I don't think it's a good solution, because matching for non-existent font usually takes too much time and it's still unable to tell the difference between requesting a default fallback font and getting that font because of fallback.

One possible approach, in my opinion, will be fixing QFont::exactMatch() so that font names after substitution will still be considered as an exact match. The implementation with fontconfig should be straightforward, but I haven't investigated how it should be done in other platforms like Windows, Mac OS X and Symbian yet.

Sorry for the late reply, I am working on another project right now, hopefully I can focus on improving web fonts support in Qt for the upcoming weeks.
Comment 19 Robert Hogan 2010-11-30 11:50:43 PST
(In reply to comment #18)
> 
> One possible approach, in my opinion, will be fixing QFont::exactMatch() so that font names after substitution will still be considered as an exact match. The implementation with fontconfig should be straightforward, but I haven't investigated how it should be done in other platforms like Windows, Mac OS X and Symbian yet.

Cool - that does sound like the right fix.
Comment 20 Jiang Jiang 2010-12-02 08:17:43 PST
(In reply to comment #15)
> (In reply to comment #14)
> > 
> > Hi Robert, could you please try either QFont(family).exactMatch() or QFontInfo(family).exactMatch()? I didn't realize that's the API you need in my first reply.
> 
> Unfortunately these don't do the job either. This is because they don't cater for cases where fontconfig has been been given a matching target for a font family. In the case of the DRT for example, 'Times' is mapped to 'Nimbus Roman No 9' by the testfonts package loaded to fontconfig at runtime. exactMatch() will always return false where such targets are configured, which is correct for exactMatch() I think but QtWebKit needs to know if a match was found that isn't the system default rather than a font with exactly the same name.

The problem appears to be more intricate than I thought. Times -> Nimbus Roman No 9 mapping is actually done after FcFontMatch rather than FcConfigSubstitute, so other WebKit ports will still reject Times if only Nimbus Roman No 9 has been installed. (In FontCache::createFontPlatformData() from FontCacheFreeType.cpp, it requires familyNameAfterConfiguration and familyNameAfterMatching to be the same).

However, Qt does need to handle substitutions for sans, serif, monospace, etc. and consider them as a match. These substitutions are done in FcConfigSubstitute().

The difference is because "Nimbus Roman No 9" is appended to "Times" in the pattern after FcConfigSubstitute, but family name like "DejaVu Sans" is prepend to "sans".
Comment 21 Jiang Jiang 2010-12-08 06:16:02 PST
Created attachment 75895 [details]
Patch to fix this problem for fontconfig based systems

Attached a patch to try out for fixing this problem in X11. Similar procedure has to be done for Windows too, but I don't have a Windows box to work on it (yet).

BTW, for QtWebKit, resolution for generic names like "-webkit-monospace" is missing too.
Comment 22 Benjamin Poulain 2011-01-11 08:11:30 PST
(In reply to comment #21)
> Created an attachment (id=75895) [details]
> Patch to fix this problem for fontconfig based systems
> 
> Attached a patch to try out for fixing this problem in X11. Similar procedure has to be done for Windows too, but I don't have a Windows box to work on it (yet).

Great.

We are a bit overloaded, I am affraid no one have time to implement the WebKit part at the moment. :(

By any chance, would you be interested in developing the WebKit part of the patch? :)
Comment 23 Florian Hänel 2011-11-22 05:47:12 PST
I stumbled over this bug after finding the persian bbc site uses the "bulletproof solution" and we display our rather unique platform default font instead of their supplied font.

I suggest we match the font name we get from Qt directly against what local() tells us to find, to make sure the site gets exactly what it wants. For any kind of fuzzy matching, family based lokoups should do the trick.

http://www.w3.org/TR/css3-fonts/

> Just as a @font-face rule specifies the characteristics of a single font within a family, the unique name used with local() specifies a single font, not an entire font family."
Comment 24 Florian Hänel 2011-11-23 02:32:25 PST
Created attachment 116333 [details]
Qt font check for src:local

Here is my suggestion for QtWebKit. Ideally we would want an exactMatch property in SimpleFontData I guess to cover all cases, although chromium at least does not have this problem, maybe because skia on Desktop does not alias font names as much as Qt does. Android 3.1 and iOS 5.0.1 don't seem to download any fonts at all.

This especially fixes a possible issue where a site owner would explicitly want to use Helvetica and not any free Helvetica lookalike or Arial.
Comment 25 Florian Hänel 2011-11-23 02:34:06 PST
correction: Android 3.1 looks fine.
Comment 26 Jocelyn Turcotte 2014-02-03 03:16:18 PST
=== Bulk closing of Qt bugs ===

If you believe that this bug report is still relevant for a non-Qt port of webkit.org, please re-open it and remove [Qt] from the summary.

If you believe that this is still an important QtWebKit bug, please fill a new report at https://bugreports.qt-project.org and add a link to this issue. See http://qt-project.org/wiki/ReportingBugsInQt for additional guidelines.