Windows / font / text futures ...

Michael Meeks michael.meeks at collabora.com
Thu Mar 3 13:44:36 UTC 2016


Hi guys,

	I've had the (mixed) pleasure of digging through the windows font
rendering in recent days; and I must say - I'm not thoroughly thrilled
with it =)

	Let me highlight a few of the problems. First we are using GDI for text
rendering, and this is ~obsolete. Several interesting problems  are
pointed out here:

http://blogs.msdn.com/b/text/archive/2009/04/15/introducing-the-directwrite-font-system.aspx

	Let me excerpt the rather charitable summary of what I've been falling
over:

	"For applications that need to work with fonts at a lower level,
	 GDI does have some functions that can really be thought of as
	 physical font APIs. Examples are GetFontData, GetGlyphIndices,
	 and even ExtTextOut when used with the ETO_GLYPH_INDEX flag.
	 Yet these “physical” font functions still use an HFONT to
	 specify the font. This means font mapping still occurs under
	 the hood, though since no text is specified there is no font
	 fallback and the same HFONT always maps to the same physical
	 font internally. While this model works, the lack of a true
	 physical font object in GDI can make it harder for application
	 developers that use these low-level functions to be sure of
	 what is going on."

	Something of an under-statement there =) As far as I can see the 
SimpleWinLayout - which we use sometimes (in place of the UniScribe layout)
and which has a number of fun comments in it like:

        // TODO: support surrogates in rewritten strings

	Essentially re-uses the non-obvious, not-really-physical-font
logic with built-in windows font fallback. In contrast the UniScribe
layout engine does not.

	The particular issue I'm looking at is that it appears really hard to
get genuine ABC widths (ie. underhang, black-width, and overhang
information) for those fall-back glyphs that are actually not in the
physical font - but that Windows (un)helpfully includes from elsewhere.
Asking for metrics via 'GetCharABCWidths' yields the 'default character's
metrics:

	"The ABC widths of the default character are used for characters
    	 outside the range of the currently selected font."

	Where by font, they mean physical font ignoring fallbacks it seems.

	After lots of nice drawings - thanks to Tor for his nice font rendering
foo, of this kind; notice the '$' character appears from another font,
with inaccurate ABC width - hence the overlap.

info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:540: DX:offset : 17:1 10:2 11:1 9:2 11:0 0:1
info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:266: this=0CC6A0E8 32 old: {[43..48],[182..187],[286..291],[9832..9837],[9858..9863],[55356..55361]}
info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:357: ABC widths: 0:1:14 3:3:3 1:8:1 0:16:0 1:8:2 0:22:2
info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:431: OpenSymbol: Escapement=0 Orientation=0 Ascent=23 InternalLeading=0 Size=(87,29) totWidth=82
info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:533: this=0CC6A0E8 now: {[32..37],[43..48],[182..187],[286..291],[9832..9837],[9858..9863],[55356..55361]}
info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:176: Bitmap 7705322A: 82x33:
info:vcl.gdi.opengl:4212:3344:vcl/win/gdi/winlayout.cxx:205:      |       |            |                    |            |
     |       |            |                    |            |
     |       |            |                    |            |
     |       |            |                    |            |
     |       |            |       7X29  92X7   |            |
     |  719  |  3X0880X3  |       3X5   9108   |            |    3XX19         925
     | 80X3  |  3X0880X3  |      92X7   8029   |      818   |  92199219        53
     | 7XX29 |  3X0880X3  |      9108   5X3    |      818   |  7X5  7X3       829
     | 7XX29 |  3X0880X3  |      8029   3X5    |    80XXXX7 |  3X7  8019     927
     | 7XX29 |  3X1991X5  |      5X3   9208    |   5XXXXXXX3| 91X7  8008     53
     | 80X3  |  7X2992X7  | 92XXXXXXXXXXXXXX5  |  80X58187XX|791X7  9108    829
     | 80X3  |  803  508  | 92XXXXXXXXXXXXXX5  |  5X3 818 3X|391X7  8008   927
     | 91X5  |            |     9108   5X3     |  3X5 818   |  3X7  8019   53
     | 92X7  |            |     8029   3X7     |  3X3 818   |  7X5  7X3   829
     |  3X7  |            |     5X3   9208     |  7XX5818   |  92199219  927
     |  308  |            |     3X5   8019     |   5XXXX29  |    3XX19   53
     |  519  |            |    9208   7X29     |    92XXXXX5|           829   92XX19
     |  729  |            |  3XXXXXXXXXXXXXX3  |      8160XX|5         927   92199208
     |  84   |            |  3XXXXXXXXXXXXXX3  |      818 3X|29        53    5X5  7X3
     |  95   |            |    5X3   9208      |      818 80|19       829   92X7  8019
     |       |            |    3X5   8019      | 91X7 818 80|19      927    91X7  9108
     |       |            |   92X7   7X29      | 92X3 818 5X|29      53     91X7  9108
     | 92X7  |            |   9119   5X5       |  7XX58187XX|5      829     92X7  8019
     | 7XX29 |            |   7X29   3X7       |   3XXXXXXX3|      927       5X5  7X3
     | 92X7  |            |   5X3   9108       |    80XXX08 |      53        92199208
     |       |            |                    |      818   |     719         92XX19
     |       |            |                    |      818   |
     |       |            |                    |            |
     |       |            |                    |            |
     |       |            |                    |            |
     |       |            |                    |            |
     |       |            |                    |            |
     |       |            |                    |            |
01234 0123456 012345678901 01234567890123456789 012345678901 01234567890123456789012345

	Anyhow - that's my problem #1. I'll carry on working away at it,
but it highlights the mess.

	The next issue I looked at is font anti-aliasing; and I notice we
previously use either DEFAULT_QUALITY or NONANTIALIASED_QUALITY fonts
cf. vcl/win/gdi/salfont.cxx

	The documentation:

	https://msdn.microsoft.com/en-us/library/ms901140.aspx

	suggests that DEFAULT_QUALITY can do odd and exciting things to font
metrics =) ie. "Appearance of the font does not matter." vs.
CLEARTYPE_COMPAT_QUALITY which "Enables ClearType® text for the font
using compatible widths. A compatible width produces text that has the
same spacing as non-ClearType text."

	Which is also somewhat concerning. I fear that we have perhaps encoded
more platform specific font rendering information into our text than expected.

	Anyhow - what to do ?

	Having looked at this heap; and worse - the two different heaps for
Windows text rendering, and also the big pile of strange cross-platform
issues with stacking diacritics, emojis etc. I'm pretty convinced that
we cannot do a good job of consistent text shaping and/or rendering
cross-platform while using the Windows font rendering infrastructure.

	While we could switch to DirectWrite on windows, which may solve some
of our problems; this will be in itself disruptive.

	So - I believe that we should switch to using harfbuzz and freetype
consistently everywhere. This would have the huge benefit of precise
cross-platform font rendering and metric fidelity, give us a font and
shaping stack that is fully introspectable, drop some legacy Windows API
usage, and allow all development work and fixing on all platforms to
share the same underlying code.

	There will of course also be some corner-cases where we may simply not
be able to replicate the tangled old layout behaviour - which is
(anyway) inconsistent across platforms - but - I think this is a one-off
risk that is well worth taking to get us to a fully consistent, Free
Software rendering stack. It is interesting that Microsoft also used freetype
for their Office / Mac rendering in the recent past =)

	Thoughts appreciated,

	ATB,

		Michael.

-- 
 michael.meeks at collabora.com  <><, Pseudo Engineer, itinerant idiot



More information about the LibreOffice mailing list