Last Comment Bug 379786 - Text with 'opacity' gets grayscale antialiasing, inconsistent with rendering with RGBA color
: Text with 'opacity' gets grayscale antialiasing, inconsistent with rendering ...
Status: RESOLVED WONTFIX
:
Product: Core
Classification: Components
Component: Graphics (show other bugs)
: Trunk
: x86 Mac OS X
: -- normal (vote)
: ---
Assigned To: John Daggett (:jtd)
:
: Milan Sreckovic [:milan]
Mentors:
Depends on:
Blocks: 379316 398102
  Show dependency treegraph
 
Reported: 2007-05-04 15:59 PDT by Robert O'Callahan (:roc) (email my personal email if necessary)
Modified: 2016-08-30 08:58 PDT (History)
10 users (show)
vladimir: blocking1.9-
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments
testcase (188 bytes, text/html)
2007-05-04 16:01 PDT, Robert O'Callahan (:roc) (email my personal email if necessary)
no flags Details
testcase screenshot with pixie view (34.76 KB, image/png)
2007-10-02 23:56 PDT, John Daggett (:jtd)
no flags Details
Rendering smoothed text various ways (61.04 KB, image/png)
2007-10-11 23:18 PDT, John Daggett (:jtd)
no flags Details
Rendering smoothed text various ways, code (5.00 KB, text/plain)
2007-10-11 23:24 PDT, John Daggett (:jtd)
no flags Details
pixie view of 'a' drawn into a bitmap context filled white (11.62 KB, image/png)
2007-10-11 23:27 PDT, John Daggett (:jtd)
no flags Details
Comparing semantics of opacity to use of RGBA colors (1.29 KB, text/html)
2007-10-11 23:40 PDT, John Daggett (:jtd)
no flags Details
screenshot of blend test above (25.51 KB, image/png)
2007-10-11 23:41 PDT, John Daggett (:jtd)
no flags Details

Description Robert O'Callahan (:roc) (email my personal email if necessary) 2007-05-04 15:59:05 PDT
In the attached testcase, both lines of text should be the same. But if I look closely with the Pixie tool or some other tool, they're antialiased differently on my laptop. rgba(0,0,0,0.5) text is subpixel-antialiased like the rest of my text. opacity:0.5 text is antialiased using grayscale only. My guess is that  _cairo_quartz_surface_create_similar is creating a surface which doesn't have the LCD characteristics associated with it.

This breaks layout/reftests/bugs/379316-1.html on my Mac.
Comment 1 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-05-04 16:01:32 PDT
Created attachment 263797 [details]
testcase
Comment 2 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-05-04 16:02:41 PDT
I suppose that this isn't showing up on Tinderbox because those Macs are configured to not use subpixel rendering (implicitly or explicitly).
Comment 3 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-05-04 17:28:13 PDT
I'm not sure what the best thing is to do here. I don't see any API to configure the bitmap context to do subpixel AA (although I might have missed it). 10.4 has a "CGLayer" type that we could use to implement _cairo_quartz_surface_create_similar, which might do the right thing, but that's 10.4 only.
Comment 4 Jesse Ruderman 2007-07-25 17:31:40 PDT
This affects the address bar (post bug 366797 landing).  Watch the "r", the second-to-last letter in "bugzilla.mozilla.org", while moving the cursor into or out of the address bar.  It temporarily becomes grayscale and appears to shift by half a pixel.  You can see similar things happening to the other letters in the hostname if you zoom in.
Comment 5 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-07-25 17:44:05 PDT
Now that we're dropping support for 10.3 I think we can change cairo-quartz to use CGLayers (which I think, but can't be sure, will fix this).
Comment 6 Vladimir Vukicevic [:vlad] [:vladv] 2007-08-07 15:15:05 PDT
Not gonna block on this, but we should try to fix it.. I don't think we want to use CGLayers for this, though.  However, I do have a patch that does basically that (uses CGLayer instead of push_group), but I need to do a bunch of cairo work to expose push/pop group to backends.
Comment 7 Sylvain Pasche 2007-09-14 05:17:09 PDT
I'm seeing the same issue on Linux. If you have subpixel rendering active ("Subpixel smoothing" option in gnome-font-properties), the reftest on bug 379316 fails.

I guess the linux Tinderboxes have their default to non-subpixel rendering, that's why it's not failing there too.

For information, the output of "xrdb -query|grep Xft" with "Subpixel smoothing" on is:
Xft.antialias:  1
Xft.dpi:        86.000000
Xft.hinting:    1
Xft.hintstyle:  hintfull
Xft.rgba:       rgb

And with "Best shapes" (the default on most distributions)
Xft.antialias:  1
Xft.dpi:        86.000000
Xft.hinting:    1
Xft.hintstyle:  hintmedium
Xft.rgba:       none
Comment 8 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-09-30 20:26:31 PDT
(In reply to comment #6)
> Not gonna block on this, but we should try to fix it.. I don't think we want to
> use CGLayers for this, though.  However, I do have a patch that does basically
> that (uses CGLayer instead of push_group), but I need to do a bunch of cairo
> work to expose push/pop group to backends.

I don't quite understand ... ideally, wouldn't create_surface_similar create a surface that has the same subpixel rendering characteristics as the original surface? CGLayer is the only way to get that in Quartz, as far as I know.
Comment 9 Vladimir Vukicevic [:vlad] [:vladv] 2007-10-01 11:59:44 PDT
Supposedly, you have to specify a screen CGContext when creating an ATSU layout to get subpixel AA, even if you don't draw to that context.  You can't specify NULL, either, it has to be a real screen context.  I'm not sure that actually helps us though, since our final drawing is done using CG, and not using ATSU, so there's probably some magic flag we're missing for CG.
Comment 10 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-10-01 18:37:39 PDT
Maybe John's secret backchannel can help us here...
Comment 11 John Daggett (:jtd) 2007-10-02 23:56:07 PDT
Created attachment 283314 [details]
testcase screenshot with pixie view

The first line of the testcase shows grey-level rendering, the second one shows LCD screen rendering.

  <div style="opacity: 0.5">Test 17</div>
  <div style="color: rgba(0, 0, 0, 0.5)">Test 17</div>    

The first line will be first rendered to an offscreen, then blit to the screen context.  The second one will be drawn directly to the screen context.  In either case, ATSUI is not involved in the rendering, the rendering occurs via calls to CGContextShowGlyphsWithAdvances.

I could be wildly offbase but isn't this a problem of the colorspace used with the context?

http://mxr.mozilla.org/mozilla/source/gfx/cairo/cairo/src/cairo-atsui-font.c#698

Will investigate more later.
Comment 12 Robert O'Callahan (:roc) (email my personal email if necessary) 2007-10-03 01:32:19 PDT
Isn't that just for fallback? I don't think we'll touch that code during normal rendering.

Here's some info:
http://mjtsai.com/blog/2006/02/04/font-smoothing-in-pages/
http://michelf.com/weblog/2006/subpixel-antialiasing-achilles-heel/

The latter one seems to be right on the money ... the problem being there's really no way to do subpixel AA right in an RGBA surface, we want an RAGABA surface and Quartz doesn't have one.

So I guess we have to WONTFIX this bug and emasculate the tests that depend on it.
Comment 13 John Daggett (:jtd) 2007-10-03 02:06:19 PDT
Don't tag this WONTFIX just yet, let me play around with this for a bit.
Comment 14 John Daggett (:jtd) 2007-10-11 20:23:11 PDT
I don't think we can solve this problem without some extremely fancy footwork that's probably not worth it.  The root of the problem is the ever-so-subtle difference between the semantics of the opacity setting and RGBA colors in combination with the way in which Apple renders text.

Setting opacity on an element forces a two-stage process, that element is first rendered and *then* blended with the background.  With RGBA colors, elements can be blended directly into the background.  

On the Mac, text is rendered based on settings in the Appearance panel and font smoothing settings of the current context.  If the Appearance panel is set to render to a LCD display and font smoothing is enabled in the context, text is *blended* into the background in such a way that leading edges of black text appear reddish and trailing edges appear blueish.  As roc has suggested, the font scaler is essentially taking the LCD geometry into account and generating separate alpha values for each channel.  When text is rendered these separate alphas are used to blend the text color into the background.  So when black text is rendered against a white background, leading and trailing edges will be shaded differently.  But if a transparent layer is used (i.e. all background pixels have alpha = 0), the result is just black pixels with a variety of alpha values, hence the gray-scale effect when subsequently blended into a background.  In short, when transparent offscreens are used, the LCD-sensitive coverage info is lost.

We could simulate this with a mask operation.  Rendering white text into a solid black (alpha=1, color=black) background would give us a mask that would capture the separate r,g,b alpha information.  But we would need to keep this around until all subelements were rendered, then blit the final result to the main context with a custom blitter.  Might be possible to approximate this using a special packed alpha format (e.g. Ar: 2bits, Ag: 3bits, Ab: 2 bits), but this would lead to a lot of headaches.

I suggest we mark this as WONTFIX (ever so sorry...).

Note that this strictly related to Quartz font smoothing, ATSUI and CGLayer are orthogonal to the issue.

More examples to follow. 
Comment 15 John Daggett (:jtd) 2007-10-11 23:18:14 PDT
Created attachment 284583 [details]
Rendering smoothed text various ways
Comment 16 John Daggett (:jtd) 2007-10-11 23:24:07 PDT
Created attachment 284584 [details]
Rendering smoothed text various ways, code

The attached code renders text using a variety of ways.  The first just draws directly into the window context, the others render into an offscreen and then copy to the screen.  For example, with a bitmap context that has been filled white, black text shows the same sub-pixel anti-aliasing as in the direct case.  With a gradient as a background, you can see that the text drawing code is clearing blending the text with the background color.  Using a CGLayer gives the same result as using a transparent bitmap context.
Comment 17 John Daggett (:jtd) 2007-10-11 23:27:07 PDT
Created attachment 284585 [details]
pixie view of 'a' drawn into a bitmap context filled white

Note the different shading on the leading and trailing edges.
Comment 18 John Daggett (:jtd) 2007-10-11 23:40:07 PDT
Created attachment 284586 [details]
Comparing semantics of opacity to use of RGBA colors

This example shows how the semantics of using RGBA colors with A=0.5 differs from using opacity = 0.5.  With RGBA colors, the paint operation immediately blends the content into the background.  With opacity, elements are first rendered without opacity, then blended in with the background using the opacity value.  Note how the red border doesn't show in the second case, that's because the blue div occludes it *before* the blend operation occurs.

Note: for both examples, the "Using..." text should be the same.  It looks like the rgba color specified in the first case is "leaking" into the second case, that's a separate bug.
Comment 19 John Daggett (:jtd) 2007-10-11 23:41:38 PDT
Created attachment 284588 [details]
screenshot of blend test above
Comment 20 John Daggett (:jtd) 2007-10-23 06:13:57 PDT
As per comments above, changing to won't fix.
Comment 21 Sylvain Pasche 2007-10-23 06:32:44 PDT
I opened bug 400829 for the Linux version if this issue, in case it is easier to solve there.

Note You need to log in before you can comment on or make changes to this bug.