RESOLVED FIXED 51869
Shadows are not drawn when filling a rect with a gradient fillStyle on Mac and Chromium-Mac
https://bugs.webkit.org/show_bug.cgi?id=51869
Summary Shadows are not drawn when filling a rect with a gradient fillStyle on Mac an...
Helder Correia
Reported 2011-01-04 02:50:05 PST
In CG, a gradient doesn't count as a fill. First, we must fill a rect with a shadow set, then draw the gradient over the fill.
Attachments
Patch (9.59 KB, patch)
2011-01-04 02:56 PST, Helder Correia
no flags
Testcase (906 bytes, text/html)
2011-01-04 13:18 PST, Simon Fraser (smfr)
no flags
Patch (13.19 KB, patch)
2011-01-05 00:53 PST, Helder Correia
no flags
Extra test step for rotation; fix Win build (hopefully) (14.08 KB, patch)
2011-01-05 17:07 PST, Helder Correia
no flags
No layer if no shadow required; update new test expected (18.29 KB, patch)
2011-01-05 19:26 PST, Helder Correia
no flags
Helder Correia
Comment 1 2011-01-04 02:56:13 PST
Helder Correia
Comment 2 2011-01-04 02:57:47 PST
This is my very first contact with CG. Please let me know if the fix is not the most correct.
Simon Fraser (smfr)
Comment 3 2011-01-04 08:34:38 PST
Does this work if some of the gradient stops have alpha?
Helder Correia
Comment 4 2011-01-04 09:16:57 PST
(In reply to comment #3) > Does this work if some of the gradient stops have alpha? Right. Apparently, the shadow is still there but remains solid, which I believe is not the right behavior (at least compared to what we do in Qt). Any pointers?
Simon Fraser (smfr)
Comment 5 2011-01-04 10:35:34 PST
(In reply to comment #4) > (In reply to comment #3) > > Does this work if some of the gradient stops have alpha? > > Right. Apparently, the shadow is still there but remains solid, which I believe is not the right behavior (at least compared to what we do in Qt). Any pointers? The canvas spec implies that the opacity of the shadow should follow the alpha of the content being drawn. In my testing, CG does this just fine. Can you attach a testcase that shows the failure?
Helder Correia
Comment 6 2011-01-04 12:05:34 PST
(In reply to comment #5) > The canvas spec implies that the opacity of the shadow should follow the alpha of the content being drawn. In my testing, CG does this just fine. Can you attach a testcase that shows the failure? Go to http://ie.microsoft.com/testdrive/Graphics/CanvasPad/ and click on shadows. Then replace all the code with: ctx.shadowOffsetX = 40; ctx.shadowOffsetY = 40; ctx.shadowBlur = 10; ctx.shadowColor = "rgba(255, 0, 0, 0.5)"; var gradient = ctx.createLinearGradient(0, 0, 250, 0); gradient.addColorStop(0, 'rgba(0, 0, 200, 0.3)'); gradient.addColorStop(1, 'rgba(200, 200, 200, 0.9)'); ctx.fillStyle = gradient; ctx.shadowColor = "rgba(255, 0, 0, 1)"; ctx.fillRect(0, 0, 340, 200); Finally click to preview. Without the patch, no shadow is shown. With the patch, the shadow does not follow the gradient's alpha. Same happens with the test included in the patch.
Simon Fraser (smfr)
Comment 7 2011-01-04 13:18:49 PST
Created attachment 77923 [details] Testcase
Simon Fraser (smfr)
Comment 8 2011-01-04 13:36:05 PST
The real issue is that GraphicsContext::fillRect(const FloatRect& rect) is clipping to the rect. So the shadow is being drawn, it's just getting clipped to the rect being filled (you can see this if you remove the shadow; the gradient looks lighter). So you may have to draw the gradient into a transparency layer (clipped), and then render that (unclipped).
Helder Correia
Comment 9 2011-01-05 00:53:44 PST
Helder Correia
Comment 10 2011-01-05 01:01:49 PST
(In reply to comment #8) > The real issue is that GraphicsContext::fillRect(const FloatRect& rect) is clipping to the rect. Indeed. Patch 77980 seems to fix that. I'm not sure if the addition of Gradient::paint(CGContextRef) is the best way to go, but ATM seems like the most convenient to me. > So you may have to draw the gradient into a transparency layer (clipped), and then render that (unclipped). I can't seem to clip the layer. If I add CGContextClipToRect(layerContext, rect) after the creation of the layer, the top box will be slightly translated in both axis. I guess I'm missing something possibly obvious.
Build Bot
Comment 11 2011-01-05 01:22:48 PST
Simon Fraser (smfr)
Comment 12 2011-01-05 08:40:46 PST
(In reply to comment #10) This patch looks close. > I can't seem to clip the layer. If I add CGContextClipToRect(layerContext, rect) after the creation of the layer, the top box will be slightly translated in both axis. I guess I'm missing something possibly obvious. I'd expect the layer to clip for you. You should also do a test here where the context has been transformed (e.g. rotated) before the drawing of the gradient.
Helder Correia
Comment 13 2011-01-05 17:07:30 PST
Created attachment 78073 [details] Extra test step for rotation; fix Win build (hopefully)
Simon Fraser (smfr)
Comment 14 2011-01-05 17:22:29 PST
Comment on attachment 78073 [details] Extra test step for rotation; fix Win build (hopefully) View in context: https://bugs.webkit.org/attachment.cgi?id=78073&action=review Does this patch alter any of the canvas/ test results? > WebCore/ChangeLog:10 > + The solution is to draw the gradient into a transparency layer, Strictly speaking, a transparency layer is something else. This is just a CGLayer. > WebCore/platform/graphics/cg/GraphicsContextCG.cpp:608 > - CGContextSaveGState(context); > - CGContextClipToRect(context, rect); > + CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0); > + CGContextRef layerContext = CGLayerGetContext(layer); > + m_state.fillGradient->paint(layerContext); > CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform()); > - m_state.fillGradient->paint(this); > - CGContextRestoreGState(context); > + CGContextDrawLayerAtPoint(context, CGPointMake(rect.left(), rect.top()), layer); > + CGLayerRelease(layer); You should only create the CGLayerRef if you know it should render with a shadow.
Helder Correia
Comment 15 2011-01-05 19:26:13 PST
Created attachment 78088 [details] No layer if no shadow required; update new test expected
Helder Correia
Comment 16 2011-01-05 19:28:53 PST
(In reply to comment #14) > Does this patch alter any of the canvas/ test results? Only the three Philip tests that it solves :) > You should only create the CGLayerRef if you know it should render with a shadow. Of course, added in patch 78088.
WebKit Commit Bot
Comment 17 2011-01-05 22:08:26 PST
The commit-queue encountered the following flaky tests while processing attachment 78088 [details]: http/tests/xmlhttprequest/cookies.html bug 51976 (authors: ap@webkit.org and eric@webkit.org) The commit-queue is continuing to process your patch.
WebKit Commit Bot
Comment 18 2011-01-05 22:11:20 PST
Comment on attachment 78088 [details] No layer if no shadow required; update new test expected Clearing flags on attachment: 78088 Committed r75139: <http://trac.webkit.org/changeset/75139>
WebKit Commit Bot
Comment 19 2011-01-05 22:11:26 PST
All reviewed patches have been landed. Closing bug.
Patrick R. Gansterer
Comment 20 2011-01-06 02:54:07 PST
Comment on attachment 78088 [details] No layer if no shadow required; update new test expected View in context: https://bugs.webkit.org/attachment.cgi?id=78088&action=review > WebCore/platform/graphics/Gradient.h:40 > +#if PLATFORM(WIN) > +#include <CoreGraphics/CoreGraphics.h> > +#endif Why is this PLATFORM(WIN) and not PLATFOMR(CG)? FYI: This broke WinCE: http://build.webkit.org/builders/WinCE%20Release%20%28Build%29/builds/169
Helder Correia
Comment 21 2011-01-06 11:58:33 PST
(In reply to comment #20) > Why is this PLATFORM(WIN) and not PLATFOMR(CG)? FYI: This broke WinCE: Sorry for that. IIUC, you've already fixed it, thank you.
Dirk Schulze
Comment 22 2011-01-16 03:01:20 PST
(In reply to comment #21) > (In reply to comment #20) > > Why is this PLATFORM(WIN) and not PLATFOMR(CG)? FYI: This broke WinCE: > > Sorry for that. IIUC, you've already fixed it, thank you. Causes a regression with SVG texts and gradients. See bug 52531.
Dirk Schulze
Comment 23 2011-01-16 03:12:55 PST
(In reply to comment #22) > (In reply to comment #21) > > (In reply to comment #20) > > > Why is this PLATFORM(WIN) and not PLATFOMR(CG)? FYI: This broke WinCE: > > > > Sorry for that. IIUC, you've already fixed it, thank you. > > Causes a regression with SVG texts and gradients. See bug 52531. It would be interesting as well, how your patch works with SVG texts, filled with gradient and CSS shadow. <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" > <defs> <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="red"/> <stop offset="100%" stop-color="blue"/> </linearGradient> </defs> <text x="200" y="200" style="font-size: 200px; text-shadow: #000 20px 20px 20px;" fill="url(#gradient)">SVG</text> </svg> Can you add a test case with pixel test please?
Helder Correia
Comment 24 2011-01-18 01:42:45 PST
(In reply to comment #23) > Can you add a test case with pixel test please? Done in bug 52509. BTW, I'd like to confirm with you: with Qt the shadow appears in black shades (following the gradient). In CG, the shadow has the same colors of the gradient. Isn't the former the correct behavior?
Note You need to log in before you can comment on or make changes to this bug.