bugThe FreeType Project - Bugs: bug #54555, All 3 TrueType engines calculate...


You are not allowed to post comments on this tracker with your current authentication level.

bug #54555: All 3 TrueType engines calculate glyph widths incorrectly

Submitter:  Georgi Boiko <pandasauce>
Submitted:  Wed 22 Aug 2018 09:01:37 PM UTC
Severity:  3 - Normal Item Group:  Incorrect behaviour
Status:  Invalid Privacy:  Public
Assigned to:  wl Open/Closed:  Closed
Planned Release:  None

Jump to the original submission

Sun 24 Feb 2019 05:59:34 PM UTC, comment #16: 

Ok, closed.

Werner LEMBERG <wl>
Group administrator
Sun 24 Feb 2019 05:00:40 PM UTC, comment #15: 

The culprit has been identified as missing/disabled subpixel positioning, which the text layouting code has to implement, so I guess we can close this issue? Same problem in cairo and therefore all GTK applications. Qt implements it, with pleasing results.

Nikolaus Waxweiler <morksig>
Group Member
Thu 21 Feb 2019 09:42:37 PM UTC, comment #14: 

Finally had the opportunity to play around with Chrome and figure this out. They disable subpixel positioning by default for seemingly no reason. Building a patched version of Chromium with it enabled fixes the issue: https://bugs.chromium.org/p/chromium/issues/detail?id=824153#c7

There was also a patch proposal for Cairo at the end of last year which added subpixel positioning (https://lists.cairographics.org/archives/cairo/2018-November/028796.html), but it didn't get any traction because it broke some tests. The original dev of the patch stepped away and no one picked it up since. I might pick it up, but given that it took me half a year to carve out some time to rebuild Chromium and fixing Cairo would not be as simple as commenting out a few lines, I wouldn't bank on it. It would make for a fantastic and rather impactful GSoC project proposal.

From the parent discussion on Chromium's bug tracker (https://bugs.chromium.org/p/chromium/issues/detail?id=740385#c18), it looks like kerned glyphs get non-integer advance widths, which in turn get rounded in a way that breaks kerning and this results in the original issue I reported here. Subtracting a near-whole pixel in these cases (flooring instead of rounding) actually does make it look better, but I don't know if that would break other use cases in FreeType. If someone can point me towards files/functions to play around with, I would be happy to do so.

Georgi Boiko <pandasauce>
Fri 24 Aug 2018 09:23:57 PM UTC, comment #13: 

I just want to thank you for your patience and bearing with me. It appears that I came across issues similar to those described in Behdad Esfahbod's whitepaper https://docs.google.com/document/d/1wpzgGMqXgit6FBVaO76epnnFC_rQPdVKswrDQWyqO1M/edit

This implies that Chrome on Linux either doesn't implement subpixel positioning or it isn't enabled by default. Cairo definitely doesn't have it, which is probably why I can observe the same issue at those font sizes pretty much system-wide. Tragic as it is, I hope that at least others will come across this ticket if they run into the same problem.

Thanks again.

Georgi Boiko <pandasauce>
Fri 24 Aug 2018 07:56:32 PM UTC, comment #12: 

How many whole pixels would you like to remove in ftdiff/ftstring rendering? At what whole ppem value?

If you do not have a concrete answer, this is not a FreeType problem. Simple as that.

Alexei Podtelezhnikov <podtelez>
Group Member
Fri 24 Aug 2018 07:29:03 PM UTC, comment #11: 

Are you sure this is a Chrome issue? The screenshot where I remove 1px is from ftdiff. If every application has to implement it, does it not belong somewhere on the rendering stack instead, e.g. cairo or FreeType?

Autohinting is way too bold and fuzzy, particularly at commonly used sizes in the area of 12px, which is why I don't use it.

Georgi Boiko <pandasauce>
Fri 24 Aug 2018 06:48:04 PM UTC, comment #10: 

You do agree that removing the whole pixel between "Aud" and "iting" is too much, don't you? You what to remove like half a pixel. Right? This is called subpixel positioning. I thought that Chrome actually implements it, but I do not know how to enable it.

I am glad that you like vanilla autohinting - use it then. Again, I doubt that this is FreeType issue. Please open the bug with Chrome and continue the layout discussion there.

PS. I glanced at the Infinality patch. It is wrong at least in applying gamma correction to the coverage/alpha map. Gamma correction applies to colors. Whoever wrote it does not understand the basics of blending. Please do not use it.

Alexei Podtelezhnikov <podtelez>
Group Member
Fri 24 Aug 2018 06:32:09 PM UTC, comment #9: 

One more observation: in v40, "d" in "Auditing" is padded with vertical 1px whitespace both on the left and on the right, whereas on the autohinter there is no vertical whitespace on either side of it. See 72-zoomed-in-whitespace-1px.png - I pointed out the colour measurements there.

Georgi Boiko <pandasauce>
Fri 24 Aug 2018 06:26:37 PM UTC, comment #8: 

Not all Infinality patches were integrated: https://github.com/archfan/infinality_bundle/blob/master/01_freetype2-iu/0001-infinality-2.9.1-2018.06.21.patch

Anyway, that's not relevant to this discussion. I built clean FreeType, removed fontconfig-infinality, removed my own tweaks and rebooted to confirm the issue on a clean setup prior to reporting it. I also used that for my screenshots. This is why a retake at 72dpi had to wait - I am avoiding doing something stupid or cutting corners here.

Is v40 not already supposed to ignore x-direction hinting based on https://www.freetype.org/freetype2/docs/subpixel-hinting.html ?

I would also argue that this is less about "like" and more about "right". "Aud" and "iting" almost look like two separate words in that web page and this only occurs on the FreeType's TrueType hinting interpreter, even on Liberation fonts. Doesn't occur on the autohinter (except for a single weird case at fractional sizes), doesn't occur without hinting, doesn't occur on the Windows hinting interpreter.

72dpi retake attached.

Georgi Boiko <pandasauce>
Fri 24 Aug 2018 02:04:37 PM UTC, comment #7: 

What do you mean Infinality patches???? v38 is integrated Infinality. We actually default to v40. Please tell me that you do not have any custom patches.

You seem to like autohinted text (not hunted in x-direction at all) because it preserves spacing the best. Unfortunately, you cannot have it both ways: it is either hinting and slight distortion of spacing or the other way around.

Alexei Podtelezhnikov <podtelez>
Group Member
Thu 23 Aug 2018 09:23:31 PM UTC, comment #6: 

My original screenshots have red boxes to point out the precise letter pairs that are broken.

For example, spacing between "d" and "i" in "Auditing Binaries" looks like too much in ft-diff, like there is an extra vertical 1px line between them. I added a zoomed-in ftdiff screenshot with the extra 1px removed compared to v40 and the autohinter. Looks like v40 (and v35, and v38) indeed inserts a near-white vertical line of pixels on the rightmost end of "d", which results in this artefact.

With +0.2px letter-spacing applied in Chrome the additional perceived whitespace between these letters sticks out like a sore thumb. Other examples may be less obvious, but clearly visible in side-by-sides with the autohinter and Windows in my previous screenshots nonetheless:




Auditing Binaries
  ^^        ^^

Vulnerability Discovery
^^     ^^

Toolkit Prep

Operational Tradecraft

Switching to 72dpi puts me on fractional ppems (18.67 instead of 19) while 96dpi doesn't. I am on Infinality patches and custom set of fontconfigs as my daily driver so a 72dpi retake of demos will have to wait until the weekend when I get a moment to move the packages and configs around to their vanilla state and back again. I don't think it will make a difference though.

As a side note, since this is where I don't know what I'm talking about: if it provides much better outputs, would the Windows approach to integer ppems not make more sense? Otherwise I would be happy to follow it up with projects up the rendering stack if that is where the fix needs to be applied, as long as it solves the actual problem.

Georgi Boiko <pandasauce>
Thu 23 Aug 2018 08:27:26 PM UTC, comment #5: 

Can you try to describe the issue more precisely? Does you feel like removing or adding a pixel between letters? Specifically where?

There are layout engines that deal with this issues. As far as FreeType concerned, you seem to be hung on fractional ppem values. Even well-hinted fonts are not optimized for this case. Windows might be enforcing integer ppem size more stringently. Can you stick to default (72) dpi in ftdiff or ftstring when you demostrate the problem?

Alexei Podtelezhnikov <podtelez>
Group Member
Thu 23 Aug 2018 05:02:32 PM UTC, comment #4: 

On that page, font-size is set to 16px for the main copy and 14px for the left-hand menu.

The results vary at different sizes. 14pt/19ppem in ftdiff definitely gives me the same issue, except for the extra letter spacing that makes it more apparent on the web page, so it's less obvious.

With ftdiff I found that auto-hinter suffers from the same problem at 13.5pt (18ppem) using 96dpi, while the unhinted version always renders correctly.

With v40, 12.0pt/16ppem at 96dpi renders correctly, so does 13.0pt/17ppem and 13.5pt/18ppem, even though at this point the font suddenly becomes bold. The issue becomes visible at 14pt/19ppem, then disappears again at 20.

On the web page, playing around with font-size and letter-spacing properties makes the issue go away with letter-spacing:0px up until font-size:19px, where it re-appears again. With letter-spacing:0.2px the issue appears seemingly at any font-size value, I've tried 8px to 16px. I also tried playing with the font-family and observed similar behavior on Tahoma, Verdana, Ubuntu and even Liberation Sans (v2) font, so I think it is a general issue with the hinting engine rather than MS giving us a headache with Arial. There is no such behavior on Windows: with and without additional 0.2px letter-spacing you get two different outputs, but both render correctly.

Could it be that some small calculation or approximation error accumulates, remains invisible until 19ppem, but additional letter-spacing amplifies it enough to make it visible at all ppems?

I thought this might be a subpixel rendering problem, so I compiled FreeType without it and still ended up with the same issue. I have now tested this on the git version and there is no change in this behavior.

Georgi Boiko <pandasauce>
Thu 23 Aug 2018 04:04:42 PM UTC, comment #3: 

I agree with Werner. This is the issue with Chrome or whatever they use for layout. I suspect that they use linearHoriAdvance so that text is WYSIWYG on paper, or something. The bottom line is that hinted WYSIWYG layout is complicated and requires dumping accumulating rounding residues onto the whitespace between words.

In any case, this is not the job of and unlikely the bug in FreeType.

Alexei Podtelezhnikov <podtelez>
Group Member
Thu 23 Aug 2018 07:50:22 AM UTC, comment #2: 

First of all: For hinted TrueType fonts, the ppem value is always an integer.  In your large image, the main font size is 16ppem.

`ftview' is not the right tool to check good font layout; you should rather use `ftdiff' instead.

Attached is the left column output of

  ftdiff -w 1800 -h 600 -s 12 -r 96 -f txt arial.ttf

I've used the current git of FreeType (built with `make devel; make'.

As you can see, there isn't any issue with the font, and the result very closely resembles the Windows output in your image (except the slightly different width of the word spaces).

Please give more details and images so that we are exactly using the same environment.  Note that I've tried with a very old and quite recent version of arial.ttf; it doesn't make a visual difference for the given example, AFAICS.

Werner LEMBERG <wl>
Group administrator
Wed 22 Aug 2018 09:12:54 PM UTC, comment #1: 

Apologies, I mixed up ppems and pts of ftview settings in my original comment. 14pt at 96dpi (18.67ppem) and 19ppem at 72dpi are the correct values.

Georgi Boiko <pandasauce>
Wed 22 Aug 2018 09:01:37 PM UTC, original submission:  

As per the attached image, v35, v38 and v40 all result in broken glyph widths. The issue is not present in the autohinter or with hinting disabled, but both have even worse results (bold and blurry fonts respectively).

Latest Chrome was used in all cases. Vanilla Windows 7 Chrome rendering was used as a reference since the font is Arial (I don't have Helvetica installed). FreeType version is 2.9.1 with subpixel rendering, table validation and TT engine selection enabled. Arial TTFs were copied over from that same Windows 7 instance, so it is the exact same font file in all cases.

Fontconfig used:

<match target="font">
    <edit name="hinting" mode="assign">
    <edit name="hintstyle" mode="assign">
    <edit name="antialias" mode="assign">
    <edit name="embeddedbitmap" mode="assign">
    <edit name="autohint" mode="assign">
    <!-- Italic variants look jagged without forcing the DPI. Default DPI of FreeType is 72. Verify with `fc-match` if in doubt. -->
    <edit name="dpi" mode="assign">

Something felt weird about rendering of the standard web fonts and I finally hunted it down when I came across a GitBook page that slightly widens letter-spacing (by 0.2px), which makes it strikingly obvious what is wrong.

The same can be reproduced with ftview using Arial at 14 ppem and 96dpi. It appears that strength of the artefact varies with different DPI settings at different ppems. For example, with 72dpi issue is much more apparent at 19ppem instead of 14.

ftview -w 800 -h 600 -e unic -r 96 -m "Auditing Binaries" 14 /usr/share/fonts/windows/arial.ttf

Alternatively, just open any GitBook in Chrome with full v40 hinting enabled for Arial. One used in the example is https://trailofbits.github.io/ctf/.

Georgi Boiko <pandasauce>


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attached Files
file #44853:  72-arial-20pt20ppem.png added by pandasauce (354KiB - image/png - 72 dpi retake - part 2)
file #44854:  72-liberation-19pt19ppem.png added by pandasauce (349KiB - image/png - 72 dpi retake - part 2)
file #44855:  72-liberation-browser.png added by pandasauce (149KiB - image/png - 72 dpi retake - part 2)
file #44856:  72-zoomed-in-whitespace-1px.png added by pandasauce (25KiB - image/png - 72 dpi retake - part 2)
file #44849:  72-widths-bci.png added by pandasauce (89KiB - image/png - 72 dpi retake - part 1)
file #44850:  72-arial-14pt14ppem.png added by pandasauce (371KiB - image/png - 72 dpi retake - part 1)
file #44851:  72-arial-18_5pt19ppem.png added by pandasauce (367KiB - image/png - 72 dpi retake - part 1)
file #44852:  72-arial-19pt19ppem.png added by pandasauce (350KiB - image/png - 72 dpi retake - part 1)
file #44837:  arial-14pt19ppem.png added by pandasauce (367KiB - image/png)
file #44831:  arial-ftdiff.png added by wl (14KiB - image/png)


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by morksig (Posted a comment)
  • -email is unavailable- added by podtelez (Posted a comment)
  • -email is unavailable- added by wl (Updated the item)
  • -email is unavailable- added by pandasauce (Submitted the item)

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.


    Follow 18 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2019-02-24 wl StatusNone Invalid
        Assigned toNone wl
        Open/ClosedOpen Closed
    2018-08-24 pandasauce Attached File- Added 72-arial-20pt20ppem.png, #44853
        Attached File- Added 72-liberation-19pt19ppem.png, #44854
        Attached File- Added 72-liberation-browser.png, #44855
        Attached File- Added 72-zoomed-in-whitespace-1px.png, #44856
    2018-08-24 pandasauce Attached File- Added 72-widths-bci.png, #44849
        Attached File- Added 72-arial-14pt14ppem.png, #44850
        Attached File- Added 72-arial-18_5pt19ppem.png, #44851
        Attached File- Added 72-arial-19pt19ppem.png, #44852
    2018-08-23 pandasauce Attached File- Added zoomed-in-remove-1px.png, #44840
    2018-08-23 pandasauce Attached File- Added liberation-browser.png, #44835
        Attached File- Added liberation-14pt19ppem.png, #44836
        Attached File- Added arial-14pt19ppem.png, #44837
        Attached File- Added arial-13_5pt18ppem.png, #44838
    2018-08-23 wl Attached File- Added arial-ftdiff.png, #44831
    2018-08-22 pandasauce Attached File- Added widths-merged-boxes.png, #44828

    Back to the top

    Powered by Savane 3.13-4b48.
    Corresponding source code