New issue
Advanced search Search tips

Issue 631900 link

Starred by 3 users

Issue metadata

Status: Started
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All , Mac
Pri: 2
Type: Bug



Sign in to add a comment

fillText() gamma-encodes alpha values for font sizes <= 256px

Project Member Reported by evan....@gmail.com, Jul 27 2016

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36

Example URL:

Steps to reproduce the problem:
Open the attached file in Chrome and observe the two histograms.

What is the expected behavior?
The distribution of anti-aliased alpha values should not depend on font size.

What went wrong?
Alpha values for fillText() are incorrect when the font size is <= 256px.

Does it occur on multiple sites: Yes

Is it a problem with a plugin? No 

Did this work before? N/A 

Does this work in other browsers? Yes 

Chrome version: 52.0.2743.82  Channel: stable
OS Version: OS X 10.10.5
Flash Version: Shockwave Flash 22.0 r0
 
alpha-gamma-bug.html
3.5 KB View Download
Components: -Blink Blink>Fonts Blink>Paint
Components: -Blink>Paint Internals>Skia
I'm guessing this is a Skia painting issue for fonts. I doubt we do anything in Chrome to modify alpha values on font colors.

Comment 3 by hcm@chromium.org, Jul 28 2016

Owner: bunge...@chromium.org
Cc: bunge...@chromium.org
Components: -Blink>Fonts Blink>Paint
Owner: schenney@chromium.org
https://www.w3.org/TR/2dcontext/#refsCSSCOLOR
The specification seems to point all questions about canvas 2d colors at the CSS color specification

https://www.w3.org/TR/css3-color/#alpha
The rules for alpha compositing here point to...


https://www.w3.org/TR/2003/REC-SVG11-20030114/masking.html#SimpleAlphaBlending
Which defers the color space to 'color-interpolation' at


https://www.w3.org/TR/2003/REC-SVG11-20030114/painting.html#ColorInterpolationProperty
Which specifies the default for 'color-interpolation' is sRGB.

So it seems pretty clear that the text/everything is supposed to be in sRGB, so it seems we're doing the right thing here for font sizes <= 256px. The reason for the difference at larger sizes is that at larger sizes the glyphs are drawn from outlines and the current rasterizer does not blend correctly (this is currently in the process of being fixed).

That being said, the behavior is up to Chromium/Blink. If the SkSurface for the canvas were created with an SkImageInfo which explicitly requests a linear gamma, you would get the results one would expect if 'color-interpolation' were set to linearRGB. For most cases this looks rather ugly, but if what want to do is to extract masks for distance fields, its certainly what you're looking for.

So, Skia already has a knob for this, and the current behavior in Chromium for sizes less than 256 is probably the right one. The issue in Skia is to ensure that the larger sizes match the smaller sizes (this is being worked on). The issue in Blink/Compositor is setting the color space correctly, possibly depending on the css style of the canvas itself (the 'color-interpolation' property).

Comment 5 by evan....@gmail.com, Jul 28 2016

This doesn't make sense to me. Alpha is supposed to be a weighting factor, not a color. It represents a physical area coverage mask, especially in the case of text anti-aliasing, and must be linear to make sense.

See  issue #3  in https://www.opengl.org/registry/specs/EXT/texture_sRGB.txt for example. The question "Should the alpha component of sRGB texture formats be gamma-corrected?" is answered with "RESOLVED:  No.  Alpha is correctly understood to be a weighting factor that is best stored in a linear representation.  The alpha component should always be stored as a linear value."

Status: Assigned (was: Unconfirmed)
I agree with evan.exe@, the alpha values are opacity and should not be adjusted by any gamma correction or color space conversion. bungeman@, do we do this wrong everywhere when transforming color spaces?
Components: -Blink>Paint
Labels: OS-All
Owner: hcm@chromium.org
Status: Started (was: Assigned)
Ah, I see, the example does something slightly different from what I thought it was doing. I thought this was drawing black on white and reading off one of the color channels. Actually, the example clears a canvas to transparent black and then draws black text on top and reads off the alpha channel.

What you're seeing here is the fake-gamma alpha, and drawing black on black is going to give the worst possible results. The numbers you're seeing are being produced at https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkMaskGamma.cpp?q=SkTMaskGamma_build_correcting_lut&sq=package:chromium&l=75&dr=CSs . Essentially, the alpha values you're seeing are those which, if you drew black through them onto a white background with a linear blend, you would get the right sRGB result. You can also see https://bugs.chromium.org/p/skia/issues/detail?id=1187 for a little more background on what's going on here technically.

This will be fixed when Skia's blending is all color space correct and we no longer need to use the fake-gamma hack to get acceptable visual output for text. While this particular case has not been previously considered, fixing this case is yet another reason to move to correct blending. This is currently being worked on.

Comment 8 by hcm@chromium.org, Jul 28 2016

Cc: brianosman@chromium.org reed@google.com
+ color space implementers

We can circle back to look at Chromium changes when the Skia color support finishes
As to the original report, as a work-around you might try drawing middle gray instead of black text. The fake-gamma cope can't make any guess about what middle gray will eventually be composited against, so its masks will be linear.
Please substitute 'code' for 'cope' in the above comment (#9).

Comment 11 by hcm@chromium.org, Jun 27 2017

Cc: ccameron@chromium.org
@reed, ccameron- should this be fixed now w/ color space impl?
Unfortunately, no. Chrome's current approach to color space support won't adjust blending behavior, so this behavior will remain as-is. The solution from comment #9 should still work, though.

Sign in to add a comment