High quality text rendering on Linux?

753 views
Skip to first unread message

Peter Verswyvelen

unread,
Feb 7, 2020, 10:55:03 AM2/7/20
to skia-discuss
I was reading the following 4 year old article:


and encountered this sentence:

The correct way of rendering a glyph image on a surface is to alpha blend it onto the surface in linear space and then apply gamma correction to translate the linear coverage map to something that is correct for our screens.1 No toolkit in the Linux ecosystem does it by default, even though Qt5 and Skia can and will do it on other platforms. Windows and Mac OS X do it natively. 

Does this mean that Skia can't blend glyphs in linear space correctly on Linux? 

I'm creating a CPU surface with pixel format kRGBA_F16_SkColorType, and a linear colorspace, so I was expecting glyphs to be blended in linear space, even if the glyph renderer isn't aware of gamma-correct blending? I'm converting to a 32-bit sRGB gamma corrected image only when saving the output.


Does anyone have tips to get the best possible glyph rendering quality on Linux, e.g. using text hints at small sizes, gamma correct alpha blending, etc?

Right now I'm getting really fuzzy text at small font sizes on Linux (Debian 10.2), compared to Windows DirectWrite. This might also be because I don't understand the SkPaint textSize property, this doesn't seem to be the font size, but the typographic line height? So I need to figure out a way to map standard font sizes to SkPaint textSize too ;-)

Thanks for any advice,
Peter




Mike Klein

unread,
Feb 7, 2020, 11:00:03 AM2/7/20
to skia-discuss
I don't really know what that article is getting at... to my knowledge font gamma blending isn't the sort of decision that we'd make per-OS.  (Though certainly different font systems and features are available on various platforms.)  If you draw into a linear surface, I would expect we blend those glyphs linearly.

For non-linear surfaces, we have some terrifying hacks to mangle the masks to get things to look kind of right with non-linear blending.  Maybe this is what that article is describing?

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/c20f1187-fb23-4e55-987a-5d2f8d332771%40googlegroups.com.

bungeman

unread,
Feb 7, 2020, 12:13:43 PM2/7/20
to skia-discuss
Four years ago I don't think Skia had linear surfaces. Note that one of the largest users of Skia on Linux, Chrome for Linux, has the text gamma correction turned way down for various reasons, which may have been the observation in that comment.

As for 'fuzzy text' you'll need to be more specific. However, there are multiple settings on SkFont which may make a difference, such a setEmbeddedBitmaps, setLinearMetrics, setSubpixel, setHinting, setEm. In addition in may make a difference which version of FreeType you are using. And of course which font is being used. In some cases the font can be very different even if it has the same name, but different data / version. For example the mscorefonts in most Linux packages are much older and quite different from the ones on Windows. The default fonts on most Linux setups will also just be completely different fonts as well (and may not have embedded bitmaps at small sizes, or be as heavily hinted, etc).

Also, which version of Skia are you using? SkPaint::setTextSize is now SkFont::setSize, though your mention of it being a property seems to indicate you may be using SkiaSharp? In any event the requested text size is the size of the font's em. Internally every font has an em size which is the design size of the font internally. The glyphs are described in em space which is then scaled down so that one em is the text size in device space. As a result, some fonts my look smaller at a given text size if the glyphs are smaller relative to the font's em size. Often the em size is more or less what one would think of as a bog standard line height, but it doesn't need to be. The actual line height comes from other metrics in the font (which are themselves described in the font in em space).

Peter Verswyvelen

unread,
Feb 11, 2020, 8:07:34 AM2/11/20
to skia-discuss
Thanks for the info!

Yes, I'm currently using SkiaSharp, but I also do some tests using the Skia fiddle online.

I'm using Roboto for testing, I will post back with more details when I tried all the options. 

So you write that SkPaint::textSize and SkFont::size are the "size of the font's em". 

Are you saying that when I set the font size to say 100, that this will cause a glyph to be rendered such that 1 unit in the font's EM coordinate space will become 100 pixels on the canvas (scaled with the device matrix if that is not the identity)?

Where 1 EM unit is number 13 in http://i.umumble.com/img/90e9dea4.gif

So the font size is actually in pixels, how large 1EM should become?

This is a bit confusing since the documentation says: Sets text size in points.

But a "point" is an absolute unit, 1/72 inch, and to convert that to pixels, a document needs to get a DPI. Unlike D2D, I don't think a Skia canvas has a DPI setting? One must manage the scaling outside of Skia (that makes sense to me)

bungeman

unread,
Feb 11, 2020, 10:56:27 AM2/11/20
to skia-discuss


On Tuesday, February 11, 2020 at 8:07:34 AM UTC-5, Peter Verswyvelen wrote:
Thanks for the info!

Yes, I'm currently using SkiaSharp, but I also do some tests using the Skia fiddle online.

I'm using Roboto for testing, I will post back with more details when I tried all the options. 

So you write that SkPaint::textSize and SkFont::size are the "size of the font's em". 

Are you saying that when I set the font size to say 100, that this will cause a glyph to be rendered such that 1 unit in the font's EM coordinate space will become 100 pixels on the canvas (scaled with the device matrix if that is not the identity)?

Where 1 EM unit is number 13 in http://i.umumble.com/img/90e9dea4.gif

Yes. Note that the diagram there is the typical case, but fonts are allowed to have outlines which extend beyond the EM. Other metrics (like underline, cap height, x height, or whatever) may also be inside or outside the unit EM. The EM is just the reference unit of measurement. Often inside the font the EM is divided up into into 1000, 1024, or 2048 to express the font units internal to the font. This is exposed in SkTypeface::getUnitsPerEm so that users can try to get outlines at that size if they want the closest thing to the ideal shape of a glyph in the font, though generally this isn't of much interest to most users. Also, note that EM isn't usually capitalized like I'm doing since it isn't short for anything, I just lose track of it when it's lowercase. It's just 'em' from the size of the (usually) square-ish slug in metal typesetting for the glyph 'M', hence the size of the 'em').
 

So the font size is actually in pixels, how large 1EM should become?

This is a bit confusing since the documentation says: Sets text size in points.

But a "point" is an absolute unit, 1/72 inch, and to convert that to pixels, a document needs to get a DPI. Unlike D2D, I don't think a Skia canvas has a DPI setting? One must manage the scaling outside of Skia (that makes sense to me)



Yeah, 'point' there isn't really right. It's in the same SkScalar 'user units' everything else on SkCanvas is in. I don't think we currently have a consistent term for 'units in user space'. It's close to meaning 'pixels' since one 'unit in user space' turns into one pixel distance when drawn through an identity matrix, at least on raster surfaces. We should probably change the documentation there.
Reply all
Reply to author
Forward
0 new messages