Closed Bug 1457417 Opened 6 years ago Closed 6 years ago

Optical sizing example on MS variable fonts demo page does not render correctly

Categories

(Core :: Layout: Text and Fonts, defect, P2)

Unspecified
macOS
defect

Tracking

()

VERIFIED FIXED
mozilla62
Tracking Status
firefox62 --- verified
firefox63 --- verified

People

(Reporter: jfkthame, Assigned: jfkthame)

References

(Blocks 1 open bug)

Details

Attachments

(6 files)

This used to display correctly for me, probably when I was running macOS 10.12, but now on 10.13 I am seeing the wrong result.

On https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts/, there is an example of optical sizing using the Sitka font (search for "Sitka" on the page to locate it).

With font-optical-sizing:auto in effect, it renders fine; but the right-hand sample, with font-optical-sizing:none, renders incorrectly. It looks like we're getting the optically-sized glyphs as though 'auto' were in effect, but with the spacing of a much smaller optical size.
This seems to be specific to the macOS (Core Text) variation fonts back-end; it renders as expected on other platforms.
OS: Unspecified → Mac OS X
Priority: -- → P2
I'm pretty convinced by now that this is fundamentally a bug in Core Text. When a font has an optical size axis, Core Text will automatically apply it when instantiating a font at a particular size, unless the CGFont already has a custom 'opsz' variation applied. Most of the time, that's harmless... we set 'opsz' on the CGFont, and it all works OK.

But when font-optical-sizing:none is in effect, we refrain from setting the 'opsz' axis, expecting the font to use its default (which under Core Graphics rendering, it does). But then the CTFont that we instantiate (either directly in thebes or moz2d, or within skia or webrender...doesn't matter who is doing it) takes over and automatically applies the 'opsz' value it thinks appropriate. We then not only get the wrong variation rendered -- it's optically-sized when the author specifically asked that it shouldn't be -- but we also get bad spacing because we've measured glyph advances based on our assumption that 'opsz' was at its default value.

The "obvious" fix would be to explicitly set the 'opsz' axis *to its default value* when font-optical-sizing:none is requested, rather than omitting it from the variation settings. Unfortunately, that doesn't work: when a variation axis is set to its default value, Core Graphics sees that it is the default, and omits it, and so Core Text still messes us up.

I'm planning to file a bug with Apple (just putting together some standalone examples to demonstrate the issue), but at this point I don't think there's a good fix we can do. The one hackish workaround I can think of would be to explicitly set the 'opsz' axis to a value that is fractionally -different- from the font's default (e.g. with Sitka, where the 'opsz' axis has a default of 6.0, we'd forcibly set it to something like 6.001) when font-optical-sizing:none is in effect. The result should be imperceptibly different from the "correct" rendering, unless the font is doing something really screwy with the axis, and by perturbing the "default" value ever so slightly we should be able to slip past Core Text's quirks.

FWIW, the bug can also be demonstrated in Safari:

* Load https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts/

* Search for "FONT-OPTICAL-SIZING: NONE" to find the optical-sizing example

  - Note how the "auto" and "none" examples render the same glyphs;
    this is because Safari does not support font-optical-sizing:none

* Right-click the large "Abcdef" under the "NONE" column, and choose Inspect Element

* In the element's Style Attribute, add font-variation-settings:'opsz' 10;

  - Note how the text adjusts its rendering (thicker strokes, increased spacing);
    this is the expected result of forcing a smaller optical size

* Now gradually reduce the requested 'opsz' value... 9, 8, 7, 6.

  - Note how the rendering varies as expected when reducing from 10 to 7, but suddenly reverts at 6

That's the bug. Trying to set 'opsz' 6 on this font is doomed to failure, because it's the font's default value and therefore Core Text decides to ignore it and do its own thing. Setting it to 6.001 will show what the result should be like.
This is a painful hack, but it's the only way I can find of making things work, because otherwise Core Text refuses to play ball... see comment above for more detail.
Attachment #8975249 - Flags: review?(jwatt)
Assignee: nobody → jfkthame
Status: NEW → ASSIGNED
Comment on attachment 8975249 [details] [diff] [review]
Work around Core Text mishandling of 'opsz' axis when set to the font's default, by adjusting to a fractionally-different setting

Review of attachment 8975249 [details] [diff] [review]:
-----------------------------------------------------------------

Yuck indeed.

::: gfx/thebes/gfxMacPlatformFontList.h
@@ +79,5 @@
>      // (This is a floating-point number because of possible interpolation.)
>      float TrackingForCSSPx(float aPointSize) const;
>  
>  protected:
> +    friend class gfxMacFont;

I think best practice is to put 'friend' declarations right at the top of class declarations. (Inside the opening curly bracket.)

@@ +106,5 @@
>      bool mHasAATSmallCaps;
>      bool mHasAATSmallCapsInitialized;
>      bool mCheckedForTracking;
> +
> +    // To work around Core Text 'opsz' mishandling, we need to record whether

Can you make this "To work around Core Text mishandling of the default value for 'opsz'...". (That is, make it clear upfront that its the mishandling of the default value of this axis.)
Attachment #8975249 - Flags: review?(jwatt) → review+
Pushed by jkew@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/711990fd66aa
Work around Core Text mishandling of 'opsz' axis when set to the font's default, by adjusting to a fractionally-different setting. r=jwatt
https://hg.mozilla.org/mozilla-central/rev/711990fd66aa
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla62
Attached image nightly 61.0a1 4.26.png
Attached image nightly 62.0a1 5.17.png
Attached image chrome.png
The Nightly rendering in attachment 8976821 [details] is correct. Note that Chrome does not support font-optical-sizing:auto, so the left-hand example in Chrome does not show the intended result.

You can also compare Safari, which does support automatic optical sizing; however, it does not support font-optical-sizing:none, and so the right-hand example does not render as intended.

As of now, only MS Edge and Firefox Nightly implement both automatic optical sizing and the ability to turn it off, so only these browsers will render both parts of the Sitka example correctly.
Attached image nightly vs edge.PNG
Checked today on macOS High Sierra v.10.13.5 initially with Nightly 61.0a1 from 04/26 (attachment nightly 61.0a1 4.26.png) to see the original issue, then on the latest Nightly 62.0a1 from 5/17 (attachment nightly 62.0a1 5.17.png) to try and reproduce the issue and on Chrome also (attachment chrome.png) to compare the results. 

After Comment 10 did a comparison with Win10 Edge also and indeed the font-optical-sizing:none now seems the same on both browsers, but yet again there seems to be a difference on font-optical-sizing:auto between the two browsers. Is this how it is supposed to be?
Flags: needinfo?(jfkthame)
Status: RESOLVED → VERIFIED
(In reply to laszlo.bialis from comment #12)
> After Comment 10 did a comparison with Win10 Edge also and indeed the
> font-optical-sizing:none now seems the same on both browsers, but yet again
> there seems to be a difference on font-optical-sizing:auto between the two
> browsers. Is this how it is supposed to be?

The Edge screenshot looks like it is from a version that does not have variable-font support. What Win10 build is that? Note that Windows 10 Fall Creators Update or later is required for variation fonts to be enabled; earlier Win10 releases will not work.
Flags: needinfo?(jfkthame)
Here is how it renders in Edge on my Win10 (fully updated) system, for comparison with the Firefox Nightly result.
(In reply to Jonathan Kew (:jfkthame) from comment #13)
> (In reply to laszlo.bialis from comment #12)
> > After Comment 10 did a comparison with Win10 Edge also and indeed the
> > font-optical-sizing:none now seems the same on both browsers, but yet again
> > there seems to be a difference on font-optical-sizing:auto between the two
> > browsers. Is this how it is supposed to be?
> 
> The Edge screenshot looks like it is from a version that does not have
> variable-font support. What Win10 build is that? Note that Windows 10 Fall
> Creators Update or later is required for variation fonts to be enabled;
> earlier Win10 releases will not work.

That's strange as I have the Win10 version 1709 with the Os build 16299.431, with all available updates made.
That is strange indeed; AFAIK that version should support font variations, but it doesn't look like it in the screenshot. Do -any- variations work in Edge on that system (e.g. using the sample fonts at https://v-fonts.com/)? Do they work in Firefox Nightly?
I managed to reproduce the issue using an older version of Nightly (2018-04-27) on macOS 10.13.
I tested again using latest Nightly and beta 62.0b7 and the bug is not reproducing anymore.
Flags: qe-verify+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: