Default style for variable fonts

22 views
Skip to first unread message

Roman Petrenko

unread,
Jul 12, 2022, 3:56:53 AMJul 12
to skia-discuss
Hi Skia experts,

In my project, I need to render fonts similarly to how web browsers do it. Apparently, when it comes to variable fonts, Skia and browsers (I checked Chrome and Firefox) render them differently by default.

Here is an example: Soulcraft font.
This is how it's rendered by Skia:
font_with_multiple_styles.png
This is how it's rendered by Chrome and Firefox:
Screen Shot 2022-07-12 at 5.45.26 pm.png
Note, no additional CSS properties were used in the HTML page.
As you can see, the browser version is much wider than the Skia version.

I can achieve the same effect by maxing out the width of character by using font arguments:

const Variation::Coordinate position[] = {
    { SkSetFourByteTag('w','d','t','h'), 100.0f },
};
SkFontArguments params;
params.setVariationDesignPosition({position, std::size(position)});
sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(soulcraft), params);


However, I don't know in advance what fonts my app will be used with. So, the question is, how do I render fonts with Skia in the same way web browsers do? Is it possible to find out what values should be used for font arguments?

bungeman

unread,
Jul 13, 2022, 8:28:44 PMJul 13
to skia-discuss
I assume you mean the variable font as downloaded from https://fontesk.com/soulcraft-typeface/ (since the link from the designer's page doesn't work)? I've opened that in Samsa https://www.axis-praxis.org/samsa/ and indeed the default of 0,0 for `wdth` and `slnt `gives what Skia does as shown at https://groups.google.com/g/skia-discuss/c/eFFDObvJyQ8/m/m33LTiT2AwAJ .

Note that `slnt` is supposed to be 0 for upright and then go negative to lean right (as a normal oblique does). In this font `slnt` goes from 0 to 100, so the axis is all messed up, but 0 does map to upright, so the the browser is probably setting things upright. `wdth` is supposed to be "percentage of normal" so 100 is supposed to be the "default" for "regular". In this font `wdth` goes from 0 to 100, so in this case the default value (of 0) and the "regular" value (of 100) are at odds but both are "in range".

Skia will always go with the default value for all axes which are not specified. Blink, however, may do something more complex, see uses of https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc;l=53;drc=53769525147583c4ed3f0f82ebea1f74d3b427f2 for example. In this case (whatever "no additional css" means, since you need som css to drag in this web font) it looks like the default for "font-stretch" is "normal" which maps to "100" which is what gets requested here in the browser.

In short, Skia will always set all axes to their defaults if not otherwise specified. Browsers may automatically attempt to set the registered axes (`ital`, `opsz`, `slnt`, `wdth`, and `wght`) based on css properties even if those css properties are at their default value.

If your project needs to render fonts how a browser would, you will need to implement close to the entire css specification. The question asked here isn't really a Skia question but a question about browser behavior. I suggest looking at the above link to font_custom_platform_data.cc in Blink to see where the values are passed to Skia. However there is a lot of code in Blink to interpret the css which feeds values into that Blink code.

Roman Petrenko

unread,
Jul 22, 2022, 1:47:05 AMJul 22
to skia-discuss
Thank you for this information, it helps a lot!

So far, it seems that in the absence of any CSS properties, browsers adjust font parameters in the following way:
`wdth` - set to 100.0, which is the default value of `font-stretch` CSS property
`wght` - set to 400.0, which is the default value of `font-weight` CSS property
`opsz` - set to match font size
Reply all
Reply to author
Forward
0 new messages