Closed Bug 1323743 Opened 8 years ago Closed 7 years ago

Add an API for DevTools to get the list of OpenType Font Variations

Categories

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

defect

Tracking

()

RESOLVED FIXED
mozilla60
Tracking Status
firefox60 --- fixed

People

(Reporter: pbro, Assigned: jfkthame)

References

(Depends on 2 open bugs, Blocks 1 open bug)

Details

(Keywords: DevAdvocacy, Whiteboard: [DevRel:P1][designer-tools])

Attachments

(7 files, 3 obsolete files)

3.01 KB, patch
dholbert
: review+
Details | Diff | Splinter Review
3.99 KB, patch
dholbert
: review+
bzbarsky
: review+
Details | Diff | Splinter Review
3.77 KB, patch
dholbert
: review+
Details | Diff | Splinter Review
3.65 KB, patch
dholbert
: review+
Details | Diff | Splinter Review
149.09 KB, patch
dholbert
: review+
Details | Diff | Splinter Review
9.28 KB, patch
lsalzman
: review+
Details | Diff | Splinter Review
3.98 KB, patch
lsalzman
: review+
Details | Diff | Splinter Review
Bug 1302685 implements OpenType Font Variations. This is cool and very useful. It might be even more useful if DevTools users could see the list of variations (are these called axes?) that a font supports. This way we could implement a new piece of UI in the inspector's Fonts panel to help people explore fonts. Therefore, we would like a new API to be implemented on the platform side that lists these variations for a given font. This was discussed on the dev-platform mailing list: https://groups.google.com/forum/#!topic/mozilla.dev.platform/_FacI6Aw2BQ
(In reply to Patrick Brosset <:pbro> from comment #0) > Bug 1302685 implements OpenType Font Variations. > > This is cool and very useful. It might be even more useful if DevTools users > could see the list of variations (are these called axes?) that a font > supports. Yes, they're "variation axes". Along with the list of variation axes (each of which will have a tag, name, and min/default/max values), we should also expose a list of defined instances. An "instance", in the context of OpenType Variations, is a predefined, named set of variation settings. So, for example, the Skia font has "weight" and "width" axes, which can be varied arbitrarily; but it also has a collection of predefined instances ("Light", "Bold", "Light Extended", "Light Condensed", etc.) that refer to specific settings of the two axes. I presume we can do this by extending the existing nsIDOMFontFace interface with 'variations' and 'instances' attributes for DevTools to examine.
Priority: -- → P3
To implement this, we'll need to add methods in gfx (probably on gfxFontEntry) to get the variations from a font face. For macOS, we could do this using Core Text APIs, but in due course we should have a platform-independent version based on harfbuzz, so it may not be worth moving forward until that's ready.
Keywords: DevAdvocacy
Whiteboard: [DevRel:P1]
Whiteboard: [DevRel:P1] → [DevRel:P1][designer-tools]
Jonathan and I recently discussed about the API in an email. Here's an excerpt: I'd guess maybe you'll want some additional properties exposed on the layout inspector's nsIDOMFontFace interface, to be able to determine the variations available in a given font (and their supported range of values). Does that sound like the kind of thing that would help? (Offhand, I'm picturing something like an nsIDOMFontVariation interface that has properties like axisName, minValue, defaultValue, maxValue; and nsIDOMFontFace would have a variations property that returns a sequence of this new thing).
Assignee: nobody → bwerth
Here's a possible way forward: this extends the nsIDOMFontFace interface that the layout/inspector code exposes for DevTools to have a .variationAxes attribute on each face. This will be null if it's not a variation font, but if variations are present it'll be a list of nsIDOMFontVariation objects, each of which has a tag (i.e. the 4-character OpenType tag such as 'wght', which would be used in font-variation-settings to control it), name (human-readable, e.g. 'Weight'), and min/max/default values. ISTM this should provide the info needed for the DevTools Inspector to present a set of sliders or something like that. Obviously, this is just a proposal at this point, and we can refine the API if necessary according to needs.
This adds support in the macOS font back-end so that nsIDOMFontFace.variationAxes will actually return something useful on macOS when variation font support is enabled.
And here's a basic chrome mochitest to check that it's working (on macOS only, for now).
Yay! Thank you Jonathan. This will make it possible for us to start experimenting.
I didn't realize Jonathan was able to move this forward. Taking myself off the bug for now.
Assignee: bwerth → nobody
Blocks: 1280059
The patches here need re-working since bug 1427419 recently landed (but should be significantly simpler as a result -- thanks, Cameron!)
Attachment #8932371 - Attachment is obsolete: true
Attachment #8932372 - Attachment is obsolete: true
Attachment #8932373 - Attachment is obsolete: true
Assignee: nobody → jfkthame
Status: NEW → ASSIGNED
(Note that the mochitest is expected to fail on platforms where we don't yet have a variable fonts implementation; we'll need to annotate it appropriately to skip those platforms if we start landing stuff here before all back-ends have been implemented.)
This doesn't actually change functionality, it is just to clean up the existing code a bit and make the following patch simpler.
Attachment #8943910 - Flags: review?(lsalzman)
And here's the actual implementation.
Attachment #8943911 - Flags: review?(lsalzman)
Attachment #8943910 - Flags: review?(lsalzman) → review+
Attachment #8943911 - Flags: review?(lsalzman) → review+
Blocks: 1432552
Attachment #8942535 - Flags: review?(cam) → review?(dholbert)
Attachment #8942536 - Flags: review?(cam) → review?(dholbert)
Attachment #8942537 - Flags: review?(cam) → review?(dholbert)
Attachment #8942538 - Flags: review?(cam) → review?(dholbert)
Attachment #8942539 - Flags: review?(cam) → review?(dholbert)
Comment on attachment 8942535 [details] [diff] [review] patch 1 - Add an API to gfxFontEntry to allow querying the available variation axes in a font face. (No actual implementation yet.) Review of attachment 8942535 [details] [diff] [review]: ----------------------------------------------------------------- ::: gfx/thebes/gfxFontEntry.h @@ +346,5 @@ > bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags); > > + // For variation font support, not yet implemented on all platforms > + virtual bool HasVariations() > + { Consider rephrasing with "which" to make the meaning clearer (assuming I'm interpreting correctly): // For variation font support, which isn't implemented on all platforms yet Otherwise (with the current wording) it's unclear whether this comment is saying that *just this specific method* isn't implemented on all platforms, vs. whether "variation font support" in general isn't yet implemented on all platforms. (I'm guessing you mean the latter, because it looks like this specific method gets implemented for all desktop platforms at least by the end of this patch queue.)
Attachment #8942535 - Flags: review?(dholbert) → review+
Comment on attachment 8942536 [details] [diff] [review] patch 2 - Add a getVariationAxes() method to InspectorFontFace for potential devtools use Review of attachment 8942536 [details] [diff] [review]: ----------------------------------------------------------------- r=me, but I think this also requires review from a DOM peer, since it's got a change to a .webidl file.... (I think there's a hg.m.o hook to enforce this, too.) ::: layout/inspector/InspectorFontFace.cpp @@ +201,5 @@ > + InspectorVariationAxis axis; > + axis.mMinValue.Construct(a.mMinValue); > + axis.mMaxValue.Construct(a.mMaxValue); > + axis.mDefaultValue.Construct(a.mDefaultValue); > + axis.mName.Construct(a.mAxisName); Nit: it might be better to do these assignments in the same order as the class declarations, so that it's easier to verify that we are indeed assigning each member-var? (i.e. consider setting axis.mTag first, and then axis.mName, then min/max/defaultValue) *shrug*, up to you.
Attachment #8942536 - Flags: review?(dholbert) → review+
Comment on attachment 8942536 [details] [diff] [review] patch 2 - Add a getVariationAxes() method to InspectorFontFace for potential devtools use Review of attachment 8942536 [details] [diff] [review]: ----------------------------------------------------------------- ::: layout/inspector/InspectorFontFace.cpp @@ +201,5 @@ > + InspectorVariationAxis axis; > + axis.mMinValue.Construct(a.mMinValue); > + axis.mMaxValue.Construct(a.mMaxValue); > + axis.mDefaultValue.Construct(a.mDefaultValue); > + axis.mName.Construct(a.mAxisName); One more nit -- can you rename either "mName" or "mAxisName" (in one or the other struct) so that they're consistent? All the other member-vars have the same names between the two structs, so it's confusing that just this one has an arbitrarily-different name.
Comment on attachment 8942536 [details] [diff] [review] patch 2 - Add a getVariationAxes() method to InspectorFontFace for potential devtools use Review of attachment 8942536 [details] [diff] [review]: ----------------------------------------------------------------- ::: layout/inspector/InspectorFontFace.cpp @@ +195,5 @@ > + if (!mFontEntry->HasVariations()) { > + return; > + } > + AutoTArray<gfxFontVariationAxis,4> axes; > + mFontEntry->GetVariationAxes(axes); Perhaps it'd be worth adding an assertion (or several) here to enforce that HasVariations() and GetVariationAxes() are consistent with each other? (i.e. the former returns true IFF the latter produces a nonempty array) (That might mean we can't have the early-return, since we need to call both APIs in order to compare their results. Not sure if that's unfortunate from a perf perspective -- I'd imagine this won't get called a ton, and GetVariationAxes will be pretty fast for a font that has no variations, so it probably doesn't matter?) Alternately, we could add internal-consistency assertions to every GetVariationAxes() implementation internally -- but it seems cleaner to kill all the birds with one stone at the callsite.
Comment on attachment 8942537 [details] [diff] [review] patch 3 - macOS implementation of the gfxFontEntry::GetVariationAxes method Review of attachment 8942537 [details] [diff] [review]: ----------------------------------------------------------------- r=me (I didn't bother looking up documentation on the various mac APIs that you're using here, but this LGTM assuming they do what they seem to do, and given that I know that you know this stuff)
Attachment #8942537 - Flags: review?(dholbert) → review+
Comment on attachment 8942538 [details] [diff] [review] patch 4 - Implement gfxFontEntry::GetVariationAxes for the Linux (fontconfig) backend Review of attachment 8942538 [details] [diff] [review]: ----------------------------------------------------------------- This seems fine. I reviewed this by comparing it to the similar code in gfxFT2FontBase::SetupVarCoords, basically. ::: gfx/thebes/gfxFcPlatformFontList.cpp @@ +1049,5 @@ > + axis.mAxisName.Assign(NS_ConvertUTF8toUTF16(a.name)); > + aAxes.AppendElement(axis); > + } > + free(mmVar); > +// FT_Done_MM_Var(face->glyph->library, mmVar); Does this commented-out line want to be removed?
Attachment #8942538 - Flags: review?(dholbert) → review+
Comment on attachment 8942539 [details] [diff] [review] Add simple chrome mochitest for InspectorFontFace.getVariationAxes() Review of attachment 8942539 [details] [diff] [review]: ----------------------------------------------------------------- ::: layout/inspector/tests/chrome/test_fontVariationsAPI.xul @@ +6,5 @@ > + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" > + onload="RunTest();"> > + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> > + > + <!-- test code goes here --> This ^^ line wants to be removed, I think. (IIRC it's part of the boilerplate produced by the "generate mochitest" script, and it's meant to be replaced with the actual test code. :)) @@ +31,5 @@ > + var elem, fonts, f; > + > + // We allow for some floating-point "fuzz" on the axis values > + var approx = function (a, b) { > + return (Math.abs(a - b) < 0.001); I think you can use the following: const epsilon = 0.001; [...] isfuzzy(a, b, epsilon, "message goes here"); ...instead of rolling your own API for this. See isfuzzy definition here: https://dxr.mozilla.org/mozilla-central/source/testing/mochitest/tests/SimpleTest/SimpleTest.js#315 That's nicer in practice (when there are failures), since it'll automatically print out the expected & actual values when it detects a failure. @@ +63,5 @@ > + ok(approx(v.maxValue, 200), "maximum weight"); > + ok(approx(v.defaultValue, 40), "default weight"); > + break; > + default: > + ok(false, "unexpected axis tag"); Two nits: (1) It's not the tag that's unexpected, but rather the whole axis (2) It would be convenient to actually print the unexpected tag as part of the error message here. How about: "unexpected axis, with tag: '" + v.tag + "'"); @@ +95,5 @@ > + ok(approx(v.maxValue, 1.30), "maximum width"); > + ok(approx(v.defaultValue, 1.0), "default width"); > + break; > + default: > + ok(false, "unexpected axis tag"); ditto
Attachment #8942539 - Flags: review?(dholbert) → review+
Depends on: 1433098
Comment on attachment 8942536 [details] [diff] [review] patch 2 - Add a getVariationAxes() method to InspectorFontFace for potential devtools use Review of attachment 8942536 [details] [diff] [review]: ----------------------------------------------------------------- r? to :bz for the webidl changes here. It's only extending a [ChromeOnly] interface, so hopefully not too controversial...
Attachment #8942536 - Flags: review?(bzbarsky)
(In reply to Daniel Holbert [:dholbert] from comment #29) > ::: gfx/thebes/gfxFcPlatformFontList.cpp > @@ +1049,5 @@ > > + axis.mAxisName.Assign(NS_ConvertUTF8toUTF16(a.name)); > > + aAxes.AppendElement(axis); > > + } > > + free(mmVar); > > +// FT_Done_MM_Var(face->glyph->library, mmVar); > > Does this commented-out line want to be removed? Oops -- that's been fixed locally, but I failed to upload a refreshed patch. We need to look up FT_Done_MM_Var with dlsym, and fall back to plain ol' free if it's not available (it's a very new addition to the freetype API).
(In reply to Jonathan Kew (:jfkthame) from comment #32) > Oops -- that's been fixed locally, but I failed to upload a refreshed patch. > We need to look up FT_Done_MM_Var with dlsym, and fall back to plain ol' > free if it's not available (it's a very new addition to the freetype API). We need probably want to do that in the existing (very-similar) gfxFT2FontBase::SetupVarCoords code as well then, right? (probably in a separate bug)
Flags: needinfo?(jfkthame)
(In reply to Daniel Holbert [:dholbert] from comment #33) > (In reply to Jonathan Kew (:jfkthame) from comment #32) > > Oops -- that's been fixed locally, but I failed to upload a refreshed patch. > > We need to look up FT_Done_MM_Var with dlsym, and fall back to plain ol' > > free if it's not available (it's a very new addition to the freetype API). > > We need probably want to do that in the existing (very-similar) > gfxFT2FontBase::SetupVarCoords code as well then, right? (probably in a > separate bug) Right. I have a trivial patch locally that does this; will post it shortly.
Flags: needinfo?(jfkthame)
Comment on attachment 8942536 [details] [diff] [review] patch 2 - Add a getVariationAxes() method to InspectorFontFace for potential devtools use If the dictionary will always have all the members specified, you could mark them as "required" and not have to deal with the Construct() bits. So then you would do something like: InspectorVariationAxis& axis = *aResult.AppendElement(); axis.mMinValue = a.mMinValue; etc. Just slightly nicer code, I think. r=me either way.
Attachment #8942536 - Flags: review?(bzbarsky) → review+
(In reply to Boris Zbarsky [:bz] (no decent commit message means r-) from comment #35) > If the dictionary will always have all the members specified, you could mark > them as "required" and not have to deal with the Construct() bits. So then > you would do something like: > > InspectorVariationAxis& axis = *aResult.AppendElement(); > axis.mMinValue = a.mMinValue; > > etc. Just slightly nicer code, I think. Thanks, I've gone with this suggestion. (In reply to Jonathan Kew (:jfkthame) from comment #34) > (In reply to Daniel Holbert [:dholbert] from comment #33) > > (In reply to Jonathan Kew (:jfkthame) from comment #32) > > > Oops -- that's been fixed locally, but I failed to upload a refreshed patch. > > > We need to look up FT_Done_MM_Var with dlsym, and fall back to plain ol' > > > free if it's not available (it's a very new addition to the freetype API). > > > > We need probably want to do that in the existing (very-similar) > > gfxFT2FontBase::SetupVarCoords code as well then, right? (probably in a > > separate bug) > > Right. I have a trivial patch locally that does this; will post it shortly. Just FTR, that fixup is now bug 1433402.
Note that on Win10, the test here passes for me locally (modulo the axis names being missing until bug 1433098 is fixed), but it fails on tryserver (no variation axes are found). I believe this is because we're not running the latest Win10 update, see bug 1433438; as a result, I'm annotating the test to be skipped on Windows for the time being. (Checking navigator.oscpu does not give sufficiently precise version information for the test to be able to tell whether to expect variations to work.)
Depends on: 1433438
Pushed by jkew@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/625b879e0a93 patch 1 - Add an API to gfxFontEntry to allow querying the available variation axes in a font face. (No actual implementation yet.) r=dholbert https://hg.mozilla.org/integration/mozilla-inbound/rev/4a2c3bc3eb23 patch 2 - Add a getVariationAxes() method to InspectorFontFace for potential devtools use. r=dholbert,bz https://hg.mozilla.org/integration/mozilla-inbound/rev/e7374076bd97 patch 3 - macOS implementation of the gfxFontEntry::GetVariationAxes method. r=dholbert https://hg.mozilla.org/integration/mozilla-inbound/rev/a4a0e7c496c6 patch 4 - Implement gfxFontEntry::GetVariationAxes for the Linux (fontconfig) backend. r=dholbert https://hg.mozilla.org/integration/mozilla-inbound/rev/09c06c7df0d1 patch 5.1 - Factor out a GetEnglishOrFirstName helper to simplify DirectWrite font-name code. r=lsalzman https://hg.mozilla.org/integration/mozilla-inbound/rev/fe3a9f1031a7 patch 5.2 - Implement gfxFontEntry::GetVariationAxes for the DirectWrite backend. r=lsalzman https://hg.mozilla.org/integration/mozilla-inbound/rev/49309c53740f Add simple chrome mochitest for InspectorFontFace.getVariationAxes(). r=dholbert
Hey Jonathan, I've tested this API (and getVariationInstances). It works great! I'm wondering whether we support custom axes though. The API does not seem to return axes when they are custom. I'm testing on https://www.axis-praxis.org/playground/horse/ which has a font with an axis called TIME. But I can't get to it with getVariationAxes(). Do we have support for custom axes in Firefox yet?
Flags: needinfo?(jfkthame)
Hmm, that's a bit surprising - I would have expected it to work. Will investigate. Which platform are you using, and have you tried others?
Flags: needinfo?(jfkthame) → needinfo?(pbrosset)
Patrick is on Mac -- though, to be clear, this isn't specific for this devtools API -- it seems like we maybe don't support custom axes *at all*? On chrome (I tested Linux and Mac), https://www.axis-praxis.org/playground/horse/ moves the horse, via a CSS animation on this custom axis. On Firefox (I tested Linux and Mac), the horse does not move.
That's odd. The horse moves for me (with the variation-font prefs set, obviously) on all platforms: Mac (Sierra, 10.12), Linux (Ubuntu 16.04), Win10 (Insider) and Android.
Never mind, we sorted it out in IRC - we hadn't set all the necessary prefs. Thanks!
Flags: needinfo?(pbrosset)
Blocks: 1441576
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: