Testing feature variations with DirectWrite

I'm trying to find a variable font debugging tool for Windows that uses the DWrite shaper, because I want to answer a question about how it processes feature variations. Not finding one, I tried writing my own, first with DWriteShapePy and then with Harfbuzz. But neither of these seem to get DirectWrite to process feature variations at all.

For example, with Bahnscrift I would expect the dollar sign to be gid 696 for wght<=319 and gid 730 for wght >= 320. With the Harfbuzz OT shaper, that's what I see:

simon@DESKTOP-1I8LMGB MINGW64 ~/DWriteShapePy (main)
$ /c/bin/hb-shape.exe /c/Windows/Fonts/bahnschrift.ttf 'A$' --variations=wght=319 --shaper=ot
[gid2=0+1246|gid696=1+1181]

simon@DESKTOP-1I8LMGB MINGW64 ~/DWriteShapePy (main)
$ /c/bin/hb-shape.exe /c/Windows/Fonts/bahnschrift.ttf 'A$' --variations=wght=320 --shaper=ot
[gid2=0+1246|gid730=1+1181]

But with the DWrite shaper, the substitution is not made. (DWriteShapePy gives same result.)

simon@DESKTOP-1I8LMGB MINGW64 ~/DWriteShapePy (main)
$ /c/bin/hb-shape.exe /c/Windows/Fonts/bahnschrift.ttf 'A$' --variations=wght=319 --shaper=directwrite
[gid2=0+1246|gid730=1+1181]

simon@DESKTOP-1I8LMGB MINGW64 ~/DWriteShapePy (main)
$ /c/bin/hb-shape.exe /c/Windows/Fonts/bahnschrift.ttf 'A$' --variations=wght=320 --shaper=directwrite
[gid2=0+1246|gid730=1+1181]

So:

  • Is there a good tool for testing variable fonts on the DirectWrite shaper?
  • Why are feature variations not being processed correctly in DirectWrite?

Comments

  • I'll inquire. Things work as expected in Notepad (hence GDI), but not in Word on-screen (hence DWrite) or in WordPad (RichEdit).
  • It works in Word online (Web) in Safari, but not in Edge on the Mac—though I can't confirm that it's actually using Bahnschrift in that case (it doesn't look like Bahnschrift to me).
  • Simon Cozens
    Simon Cozens Posts: 732
    Thanks. The real question I want to answer, which sparked my need for a testing tool is: do the (various, by the sound of things) Windows shapers process feature variations even if they are not in the rvrn feature?
  • My understanding Direct Write should process feature variations applied to any feature, not only <rvrn>. It's possible however there are subtleties in how the client calls Direct Write where that behavior may not happen. That could be the reason why DWriteShapePy and the DWrite Shaper in Harfbuzz is not seeing the result. I'll look into that further. 

    Regarding Bahnschrift, the correct substitution for the $ is performed by DWrite. This can be verified as follows:

    1. Open the Settings app, and navigate to the Personalization / Fonts page.
    2. Select Bahnschrift.
    3. Scroll down to the Metadata and click the “Variable font properties” link.
    4. In the Variable font properties page, type $ under Preview text.
    5. Drag the Weight slider and the appearance of the $ changes between 319 and 320.

  • I looked into why DWriteShapePy was not showing expected behavior and found there was a bug when setting variations. HarfBuzz tags and DWrite tags are reversed. I had accounted for this in feature tags but not variation tags. I fixed it and posted update to PyPi. 
  • Thanks. The real question I want to answer, which sparked my need for a testing tool is: do the (various, by the sound of things) Windows shapers process feature variations even if they are not in the rvrn feature?
    Adding to what Paul said: within DWrite, this level of processing isn't implemented in individual shaping engines, but rather would be implemented in the lower-level OTL layer that all shaping engines call into.
  • I'll inquire. Things work as expected in Notepad (hence GDI), but not in Word on-screen (hence DWrite) or in WordPad (RichEdit).
    Addendum: the issue for Word isn't DWrite, but with Word itself. Word and RichEdit are by-passing shaping on the assumption that the text isn't a complex script that requires shaping and no discretionary features are being applied. It's an optimization that might have been valid before OpenType 1.8, but should have been revisited after the introduction of variable fonts.
  • Simon Cozens
    Simon Cozens Posts: 732
    Thanks, both, for your comments. Now I have to wonder why rvrn exists. It feels like a mistake. Doing a variation-based substitution so early on in the process means that all following rules now have multiple glyphs to track instead of just one...
  • John Hudson
    John Hudson Posts: 3,126
    edited July 2021
    I believe the thinking of rvrn is similar to that of ccmp and locl, i.e. that there might be substitutions that set up subsequent inputs, based on, respectively, variation instance, cmap output, or language system. I always thought of rvrn as an option, as a feature that would be reliably processed at an early stage, to produce output specific to the variation instance—bearing in mind that selecting an instance in a VF design space is akin to selecting a font: rvrn produces the default forms for that font. I never expected that all GSUB feature variations would belong in rvrn, any more than all GSUB substitutions belong in ccmp: you put the lookups in the features that make most sense for the project.
  • bearing in mind that selecting an instance in a VF design space is akin to selecting a font: rvrn produces the default forms for that font.

    That's a fair way to think of 'rvrn'.
    I never expected that all GSUB feature variations would belong in rvrn, any more than all GSUB substitutions belong in ccmp: you put the lookups in the features that make most sense for the project.

    Certainly not. In particular, for instance, if you had a discretionary feature like 'swsh' and the substitutions needed to be different for certain portions of the design space, you'd simply use a feature variation for the 'swsh' feature table.