Closed Bug 483533 Opened 15 years ago Closed 15 years ago

drawing glitches with inset box-shadows when there's a border-radius

Categories

(Core :: Web Painting, defect)

x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: dbaron, Assigned: ventnor.bugzilla)

References

Details

(Keywords: css3, fixed1.9.1)

Attachments

(2 files, 4 obsolete files)

Attached file testcase
This testcase (simplified from Håkon Lie's talk today at SXSW) shows drawing glitches with inset box shadows when there is a border-radius.

Steps to reproduce: load testcase

Expected results: Green and yellow shapes cleanly surround red

Actual results:  Extra blotches of red in the yellow band near the upper left and lower right corners.

I'm seeing this on my Linux debug build from a week or so ago.
The slides from which this was simplified are at http://people.opera.com/howcome/2009/talks/03-css3.html (although they require changing the projection style sheet to screen to see things in Gecko).
We should perhaps try to get a fix for this for 1.9.1
Flags: blocking1.9.1?
Zack might find this interesting also
This is probably a problem with the way we calculate/use rounded corners. We get the inner radii of the border, then inset to make the shadow, then use that radii that we got from the original frame size, which could be too big for the inset shadow. This is why following an edge of the shadow gives the exact same line as the inner border edge.

The fix would be to figure out what scenario(s) we should limit our border radii for inset shadows, and what we should limit it to.
Flags: blocking1.9.1? → wanted1.9.1+
So this is because we're using improper radii on shadowClipRect.

My suggestion to fix this was to add the spread distance to the gfxFloat[4] of borderSizes, and call nsCSSBorderRenderer::ComputeInnerRadii with the original borderRadii, but with the new border sizes. This should give back the inner radii that the shadowClipRect would use.

While this improves things slightly, it still doesn't make the problem go away completely, and I'm at a loss as to why.
Attached patch Solution? (obsolete) — Splinter Review
I can't find anything wrong with this logic, so I'm wondering whether its a bug with my computer or display driver (wouldn't be the first time). Does this patch solve the problem for anyone, especially non-Linux folk?
Attached patch Patch (obsolete) — Splinter Review
This makes this testcase a bit better but there is still a bug with the way we calculate the rounded corner path (and I don't think that's part of my code).

However, this is a general solution we really need to take as without it, inset box-shadows for rounded boxes are very broken in general. I can't make a reftest for it because I can't make pixel-perfect duplicates with any approach I can think of.
Attachment #369052 - Attachment is obsolete: true
Attachment #376523 - Flags: superreview?(roc)
Attachment #376523 - Flags: review?(roc)
Attached patch Patch 2 (obsolete) — Splinter Review
Actually, turns out we need this patch regardless, because the spec says that spread should not change the shape of the box shadow. Our box shadows are changing shape based on spread. So we need this (preferably for 1.9.1) not only to fix spread but also fix our compliance.

Reftests pass.
Attachment #376523 - Attachment is obsolete: true
Attachment #376610 - Flags: superreview?(roc)
Attachment #376610 - Flags: review?(roc)
Attachment #376523 - Flags: superreview?(roc)
Attachment #376523 - Flags: review?(roc)
Attached patch Patch 2.1 (obsolete) — Splinter Review
I was able to do this with slightly less code.
Attachment #376610 - Attachment is obsolete: true
Attachment #376611 - Flags: superreview?(roc)
Attachment #376611 - Flags: review?(roc)
Attachment #376610 - Flags: superreview?(roc)
Attachment #376610 - Flags: review?(roc)
Comment on attachment 376611 [details] [diff] [review]
Patch 2.1

+    if (hasBorderRadius) {
+      gfxCornerSizes clipRectRadii;
+      gfxFloat spreadDistance = shadowItem->mSpread * -1 / twipsPerPixel;
+      gfxFloat borderSizes[4] = {
+        spreadDistance, spreadDistance,
+        spreadDistance, spreadDistance
+      };
+      nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes,
+                                             &clipRectRadii);
+      shadowContext->RoundedRectangle(shadowRect, clipRectRadii);
+    } else
       shadowContext->Rectangle(shadowRect);

{} around the the ->Rectangle call.

+      gfxFloat spreadDistance = shadowItem->mSpread * -1 / twipsPerPixel;

Why not just -shadowItem->mSpread/twipsPerPixel?
Attachment #376611 - Flags: superreview?(roc)
Attachment #376611 - Flags: superreview+
Attachment #376611 - Flags: review?(roc)
Attachment #376611 - Flags: review+
Attached patch Patch 2.2Splinter Review
For checkin.
Attachment #376611 - Attachment is obsolete: true
Keywords: checkin-needed
http://hg.mozilla.org/mozilla-central/rev/68d219cad3a0
Assignee: nobody → ventnor.bugzilla
Status: NEW → RESOLVED
Closed: 15 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Whiteboard: [needs landing] → [needs 191 landing]
Blocks: 578134
Component: Layout: View Rendering → Layout: Web Painting
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: