Bug 152393 - REGRESSION (r172008): Icon fonts using hinting blurred at odd window widths
Summary: REGRESSION (r172008): Icon fonts using hinting blurred at odd window widths
Status: REOPENED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: WebKit Nightly Build
Hardware: All All
: P2 Major
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-17 13:00 PST by Adam Strzelecki
Modified: 2015-12-19 09:20 PST (History)
5 users (show)

See Also:


Attachments
Given octicons.html example rendering with even browser width vs odd browser width (2.08 KB, image/png)
2015-12-17 13:00 PST, Adam Strzelecki
no flags Details
GitHub page elements rendering when margin is even (15.81 KB, image/png)
2015-12-17 13:00 PST, Adam Strzelecki
no flags Details
GitHub page elements rendering when margin is odd (16.74 KB, image/png)
2015-12-17 13:01 PST, Adam Strzelecki
no flags Details
Testcase (477 bytes, text/html)
2015-12-17 13:19 PST, Simon Fraser (smfr)
no flags Details
Test reduction. (529 bytes, text/html)
2015-12-18 11:54 PST, zalan
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Adam Strzelecki 2015-12-17 13:00:22 PST
Created attachment 267575 [details]
Given octicons.html example rendering with even browser width vs odd browser width

Many modern sites use icon fonts, such as Font Awesome, Octicons, etc. This is more optimal for bandwidth conservation and HiDPI displays support than using separate images. These fonts come usually optimized for certain sizes, eg. Octicons for multiple of 16px font height. This optimization relies on font hinting that makes glyph elements to be aligned to pixel boundaries, this guarantees visual sharpness and clearness of the icons.

Some time ago this technique was giving desired effects in Safari and other WebKit based browsers. But since last year font icons started to appear blurry. After some investigation I found out that WebKit renders blurry font icons only when the rendered text position is fractional (non-integer), eg. when using margin: auto with fixed text container width and odd pixel number browser window width causing margin to be fractional. This is illustrated better with following HTML example below.

I did a bisection tests on WebKit nightly releases running on 10.9. I blame revision r172008 because it is only revision between r171989-r172326 that changed text rendering, and r171989 nightly downloaded from webkit.org does not exhibit the buggy behavior, while next available nightly r172326 exhibits buggy blurry rendering.

IMHO this bug has major severity, as causing blurry rendering on many well known sites such as GitHub (see attached screenshots). This cannot be worked around using some CSS tricks. It reduces experience and causes eye strain.

Please test the following page with even pixel browser window width and odd width to see the difference (LeftIntegerPositionRightFractionalPosition.png).
The fixed 800px width #container has automatic margin. So if browser window width is 1000px, then the left-margin is 1000px-800px/2 -> 100px, but when browser windows width is 1001px then left-margin is non-integer 100.5px causing blur since r172008.
--- octicons.html
<!DOCTYPE html>
<html>
<head>
	<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.3.0/octicons.css" media="all" rel="stylesheet">
	<head>
		<style>
			#container {
				border: 1px solid silver;
				padding: 10px;
				width: 800px;
				margin: auto;
				height: 100%;
			}
		</style>
	</head>
</head>
<body>
	<div id="container">
		<span class="octicon octicon-repo"></span>
		<span class="octicon octicon-plus"></span>
	</div>
</body>
</html>
--- /octicons.html
Comment 1 Adam Strzelecki 2015-12-17 13:00:55 PST
Created attachment 267576 [details]
GitHub page elements rendering when margin is even
Comment 2 Adam Strzelecki 2015-12-17 13:01:11 PST
Created attachment 267577 [details]
GitHub page elements rendering when margin is odd
Comment 3 Adam Strzelecki 2015-12-17 13:04:28 PST
Here is a link to related issue discussion for Octicons project:

https://github.com/github/octicons/issues/42
Comment 4 Simon Fraser (smfr) 2015-12-17 13:19:42 PST
Created attachment 267578 [details]
Testcase
Comment 5 Simon Fraser (smfr) 2015-12-17 13:22:35 PST
Subpixel stuff?
Comment 6 Adam Strzelecki 2015-12-17 13:27:27 PST
Sort of. It looks like before r172008 all text box offsets were rounded to device pixel boundaries, but the r172008 introduced rounding only in one direction, so when text is horizontal only Y is rounded, when vertical only X. I completely don't get the reasoning behind that. But the result can be observed on attached sshots.

https://trac.webkit.org/changeset/172008/trunk/Source/WebCore/rendering/InlineTextBox.cpp

I only hope this is THE change that caused the bug and no other changes were introduced afterwards, this is just because I did bisections using last years nightly builds, but there is a gap between r171989-r172326, so I blame r172008 just looking at the changes between these releases.
Comment 7 Keyamoon 2015-12-17 21:33:09 PST
I just wanted to point out that this is a more general issue. It happens with all fonts, not just icon fonts. I've seen it happen with Latin fonts as well. It's hard to notice if you're using a Retina display, unless you zoom on pixels (without smoothing).

To reproduce this issue with Latin fonts, try to slowly change the size of the browser window here: https://linearicons.com

In my tests, Firefox doesn't have this issue. Only Chrome and Safari on OS X seem to have this issue.
Comment 8 Keyamoon 2015-12-17 23:50:49 PST
It seems that resizing the window doesn't help reproduce the issue on Retina displays. On linearicons.com, if you zoom in on the word "PPI" or "raster", you can see that the vertical lines are blurred.

If you are using the zoom in OS X, make sure to uncheck the "smooth images" option so that you can see the actual pixels.

To me it seems that the letters start out in correct positions but then slowly get displaced as the sentence gets longer.

If you can access a non-retina Mac, you could more easily see this issue by resizing the window.
Comment 9 Adam Strzelecki 2015-12-18 02:18:38 PST
It is not reproducible with my test case on Retina because simple (math) reason - 100.5px logical pixels when windows size is 1001, are 201 physical pixels on Retina, so text box begins on physical pixel boundary -> no blur. However one can make some other example such as using divs with percent sizes where calculated with is not integer of Retina pixel, see:

--- octiretina.html
<!DOCTYPE html>
<html>
<head>
	<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.3.0/octicons.css" media="all" rel="stylesheet">
	<head>
		<style>
			#container {
				border: 1px solid silver;
				padding: 10px;
				width: 500px;
				margin: auto;
				height: 100%;
			}
			#left  { float: left;  width: 33.66667%; }
			#right { float: right; width: 33.33333%; }
			#clear { clear: both; }
		</style>
	</head>
</head>
<body>
	<div id="container">
		<div id="left">
			<span class="octicon octicon-repo"></span>
			<span class="octicon octicon-plus"></span>
		</div>
		<div id="right">
			<span class="octicon octicon-repo"></span>
			<span class="octicon octicon-plus"></span>
		</div>
		<div id="clear"></div>
	</div>
</body>
</html>
--- /octiretina.html

Blur is visible on Retina at right column. So WebKit is not obeying hinting and right font is not pixel aligned on Retina. Tested on my MBP.
Comment 10 zalan 2015-12-18 11:54:08 PST
Created attachment 267647 [details]
Test reduction.
Comment 11 Myles C. Maxfield 2015-12-18 15:22:02 PST
The cause of this bug is pretty straightforward - the font is trying to draw something exactly n pixels wide, but it starts halfway through the first pixel. Therefore, your edges which you thought appeared at discrete pixel boundaries all actually happen halfway through the pixel, leading to 50% coverage and grey pixels.

In one respect, this is working as intended. Sub-pixel placement of layout objects is a progression. Fonts, in general, benefit greatly from sub-pixel positioning, and it greatly improves readability of text.

All the major browsers which run on OS X all have the same behavior here.

For your use case of showing icons in web content, I would suggest using SVG. Fonts were never designed for this purpose.

A "solution" is simply to make sure your markup always results in these icons being drawn at integer pixel locations.

Another idea for a solution is to allow something like a "round()" function which can be used inside the "calc()" CSS function. Presumably something like this would suit your needs?
Comment 12 Keyamoon 2015-12-18 23:32:53 PST
This notion that fonts were never intended to be used for icons is wrong. There are clear definitions for icons in the Unicode. The Private Use Area in the Unicode was designed so that it can be used for custom glyphs. Emojis are often implemented using fonts.

I don't see how fonts benefit from sub-pixel positioning. With the current behavior, the font would look different based on its position. As a font designer, I would like my glyphs to look as I designed them.

Try resizing the browser window on a non-retina display here: https://linearicons.com. The Latin font would switch between looking blurred and crisp. How is the blurred version easier to read that the crisp one?
Comment 13 Adam Strzelecki 2015-12-19 02:28:38 PST
> In one respect, this is working as intended. Sub-pixel placement of layout objects is a progression. Fonts, in general, benefit greatly from sub-pixel positioning, and it greatly improves readability of text.

You call progression something that causes blurriness and degrades readability. This does not sound convincing at all, actually it sounds even worse because "it greatly improves readability of text" is exactly contradicting screen-shots attached to this issue.


> The cause of this bug is pretty straightforward - the font is trying to draw something exactly n pixels wide, but it starts halfway through the first pixel. Therefore, your edges which you thought appeared at discrete pixel boundaries all actually happen halfway through the pixel, leading to 50% coverage and grey pixels.

This is what I have already explained above. I know the reason, yet I am telling that such behavior causes blurry rendering.


> All the major browsers which run on OS X all have the same behavior here.

If you are talking about Chromium and WebKit, then yes, they have regressed in same moment ~Jul 2014 sharing the same set of patches introducing text rendering at fractional offsets.

If we speak about Firefox, then Firefox never respected font hinting until ver. 25 where it started to work when the offsets were integer.


> For your use case of showing icons in web content, I would suggest using SVG. Fonts were never designed for this purpose.

I am sorry but this argument is completely untrue and fanciful. Computer fonts were always meant to be drawn on computer screen and optimized for underlying pixel grid. That's why we had bitmap fonts, and then we moved to vector representation in same time introducing font hinting (I stated explicitly in the subject that's the regression makes browsers not obey font hinting at fractional offsets). That's why computer fonts are always designed keeping in mind pixel grid (eg. San Francisco font presentation at WWDC 2015).

Moreover if fonts were not meant to carry icons, what the heck do all the icons and web-dings in Unicode standard v7, what do all Emojis in Unicode standard!? Unicode committee don't know well the purpose of fonts too? Sorry but you are stating something completely opposite to reality.


> A "solution" is simply to make sure your markup always results in these icons being drawn at integer pixel locations.

I said in the issue "This cannot be worked around using some CSS tricks." I've seen ppl trying but so far I don't see a real solution to ensure that some inline text box is aligned to pixel boundary. Only working solutions I have seen so far are JavaScript, but honestly using JavaScript to fix such regression is a real pity.

> Another idea for a solution is to allow something like a "round()" function which can be used inside the "calc()" CSS function. Presumably something like this would suit your needs?

Presumably. Any solution that brings us to sharp rendering as it was in May 2014 would be good. Best if it was working without extra tweaking. If it needs some extra but not enormous CSS then it is good to. But so far I've seen no such solution.


Altogether I disagree with your points, I disagree to close this issue especially when:

1. The issue shows rendering degradation and affects all users

2. No workaround was given


Therefore I humbly request to reopen it until a solution other than "it is working as intended" is given.
Comment 14 Myles C. Maxfield 2015-12-19 09:09:21 PST
hober: what do you think about adding rounding functions to the calc() CSS syntax?
Comment 15 Myles C. Maxfield 2015-12-19 09:10:38 PST
Reopening because of apparent regression
Comment 16 Keyamoon 2015-12-19 09:20:05 PST
What are the drawbacks of always rounding? If a font glyph was designed on a pixel grid, rounding would make it look as expected. If it wasn't designed on a pixel grid, it wouldn't matter either way.