Closed Bug 1319407 Opened 8 years ago Closed 7 years ago

clip-path reference-box geometry computing should respect box-decoration-break

Categories

(Core :: Web Painting, defect, P2)

defect

Tracking

()

RESOLVED FIXED
mozilla56
Tracking Status
firefox56 --- fixed

People

(Reporter: u459114, Assigned: lochang)

References

(Depends on 3 open bugs, Blocks 1 open bug)

Details

Attachments

(3 files, 2 obsolete files)

According to CSS Fragmentation Module Level 3: https://drafts.csswg.org/css-break/#break-decoration When a break (page/column/region/line) splits a box, the box-decoration-break property controls * how the background positioning area [CSS3BG] (and mask positioning area [CSS-MASKING-1], shape reference box [CSS-SHAPES-1], etc.) is derived from or duplicated across the box fragments and how the element’s background is drawn within them. We do not actually handle box-decoration-break: slice among nsDisplayMask/ nsCSSClipPathInstance::ComputeSVGReferenceRect()/ nsCSSClipPathInstance::ComputeHTMLReferenceRect()
Status: NEW → ASSIGNED
Priority: -- → P3
No longer blocks: mask-image
Depends on: 1319406
Component: Layout → Layout: View Rendering
Blocks: basic-shape
Attached file box-decoration-break.html —
clip-path + box-decoration-break work not correctly on FF, Chrome and Edge. So I think we need to fix it, but this bug should not be a blocker of basic-shape shipping.
No longer blocks: basic-shape-ship
Assignee: cku → lochang
Attached patch WIP patch (obsolete) — — Splinter Review
A hacking patch that makes svg clip-path works correctly when using box-decoration-break: clone..
Priority: P3 → P2
Attachment #8881551 - Attachment is obsolete: true
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. Hi CJ, Could you review the patch for me? Thanks. In the patch, I make it not to merge the continuation frames when box-decoration-break is clone. So it will call nsDisplayMask::Paint for each frame. Then we can apply clip-path to each frame respectively. I think it works for both path: PaintMask and PaintAsLayer. The reftest of using PaintAsLayer is in the other attachment. However, I only test PaintMask on local with hack patch.
Attachment #8887410 - Flags: review?(cku)
Comment on attachment 8887411 [details] Bug 1319407 - Add reftest for clip-path when box-decoration-break is clone. reftest for clip-path with box-decoration-break is clone.
Attachment #8887411 - Flags: review?(cku)
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158272/#review163922 ::: layout/painting/nsDisplayList.cpp:8464 (Diff revision 1) > > + // items with StyleBoxDecorationBreak::Clone should not be merged into a > + // compositing group > + if (mFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone) > + return false; > + Put return false in curly brackets ::: layout/svg/nsSVGIntegrationUtils.cpp:222 (Diff revision 1) > + nullptr, > + nsRect(), > + false); > + collector.AddBox(aNonSVGFrame); > + r = collector.GetResult() + GetOffsetToBoundingBox(firstFrame); > + } else { Add MOZ_ASSERT(aNonSVGFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Slice); ::: layout/svg/nsSVGIntegrationUtils.cpp:225 (Diff revision 1) > + collector.AddBox(aNonSVGFrame); > + r = collector.GetResult() + GetOffsetToBoundingBox(firstFrame); > + } else { > + r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(), > - GetOffsetToBoundingBox(firstFrame), > + GetOffsetToBoundingBox(firstFrame), > - false); > + false); Can you add a new parameter "lastFrame" as the 2nd parameter of GetPreEffectsVisualOverflowUnion. Set lastFrame as firstFrame if mBoxDecorationBreak == StyleBoxDecorationBreak::Clone; otherwise, set lastFrame as nullptr. Inside GetPreEffectsVisualOverflowUnion, iterate frames from firstFrame to lastFrame, and iterate to the last coninuation one if lastFrame is nullptr. Then, the code here will look like: nsIFrame* lastFrame = aNonSVGFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone ? firstFrame : nullptr r = GetPreEffectsVisualOverflowUnion(firstFrame, lastFrame, nullptr, .....);
Attachment #8887410 - Flags: review?(cku)
Comment on attachment 8887411 [details] Bug 1319407 - Add reftest for clip-path when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158274/#review163938 ::: layout/reftests/svg/box-decoration-break.html:9 (Diff revision 1) > +--> > + > +<html> > +<head> > + <meta charset="utf-8"> > + <title>Test of box-decoration-break</title> Test of box-decoration-break with clip-path ::: layout/reftests/svg/box-decoration-break.html:15 (Diff revision 1) > + <style> > + .clone { > + -ms-box-decoration-break: clone; > + -webkit-box-decoration-break: clone; > + -o-box-decoration-break: clone; > + box-decoration-break: clone; keep only canonical one - box-decoration-break: clone; ::: layout/reftests/svg/box-decoration-break.html:19 (Diff revision 1) > + -o-box-decoration-break: clone; > + box-decoration-break: clone; > + } > + span { > + background: linear-gradient(to bottom right, yellow, green); > + box-shadow: 8px 8px 10px 0px deeppink, -5px -5px 5px 0px blue, 5px 5px 15px 0px yellow; box-shadow is not relative to this test, please remove it. and the same for border-xxx ::: layout/reftests/svg/box-decoration-break.html:34 (Diff revision 1) > + background: grey; > + } > + </style> > +</head> > +<body> > + <div> 2 space indent
Attachment #8887411 - Flags: review?(cku)
Attachment #8887411 - Attachment is obsolete: true
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158272/#review164042 ::: layout/svg/nsSVGIntegrationUtils.cpp:139 (Diff revision 2) > // Compute union of all overflow areas relative to aFirstContinuation: > - nsLayoutUtils::GetAllInFlowBoxes(aFirstContinuation, &collector); > + nsLayoutUtils::GetInFlowBoxes(aFirstContinuation, aCurrentFrame, &collector); > // Return the result in user space: > return collector.GetResult() + aFirstContinuationToUserSpace; > } > Leave GetPreEffectsVisualOverflowUnion as it is. Add a new function GetPreEffectsVisualOverflow( nsIFrame* aCurrentFrame, const nsRect& aCurrentFramePreEffectsOverflow, const nsPoint& aFirstContinuationToUserSpace, bool aInReflow) Only take geometry of aCurrentFrame into account.
Attachment #8887410 - Flags: review?(cku)
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158272/#review164460 ::: layout/base/nsLayoutUtils.cpp:3935 (Diff revision 3) > > void > +nsLayoutUtils::GetInFlowBoxes(nsIFrame* aCurrentFrame, > + BoxCallback* aCallback) > +{ > + AddBoxesForFrame(aCurrentFrame, aCallback); How about export AddBoxesForFrame from nsLayoutUtils and remove this one? ::: layout/painting/nsDisplayList.cpp:8460 (Diff revision 3) > bool nsDisplayMask::TryMerge(nsDisplayItem* aItem) > { > if (aItem->GetType() != TYPE_MASK) > return false; > > + // items with StyleBoxDecorationBreak::Clone should not be merged into a // Do not merge items with StyleBoxDecorationBreak::Clone prop value. ::: layout/svg/nsSVGIntegrationUtils.cpp:145 (Diff revision 3) > +static nsRect > +GetPreEffectsVisualOverflow(nsIFrame* aFirstContinuation, > + nsIFrame* aCurrentFrame, > + const nsRect& aCurrentFramePreEffectsOverflow, > + const nsPoint& aFirstContinuationToUserSpace, > + bool aInReflow) Remove aCurrentFramePreEffectsOverflow and aInReflow ::: layout/svg/nsSVGIntegrationUtils.cpp:150 (Diff revision 3) > + bool aInReflow) > +{ > + PreEffectsVisualOverflowCollector collector(aFirstContinuation, > + nullptr, > + aCurrentFramePreEffectsOverflow, > + aInReflow); collector(aFirstContinuation, nullptr, nsRect(), false); ::: layout/svg/nsSVGIntegrationUtils.cpp:152 (Diff revision 3) > + PreEffectsVisualOverflowCollector collector(aFirstContinuation, > + nullptr, > + aCurrentFramePreEffectsOverflow, > + aInReflow); > + // Compute overflow areas of current frame relative to aFirstContinuation: > + nsLayoutUtils::GetInFlowBoxes(aCurrentFrame, &collector); nsLayoutUtils::AddBoxesForFrame(aCurrentFrame, &collector);
Attachment #8887410 - Flags: review?(cku)
Comment on attachment 8887876 [details] Bug 1319407 - Add reftest for box-decoration-break with clip-path. https://reviewboard.mozilla.org/r/158806/#review164468 LGTM
Attachment #8887876 - Flags: review?(cku) → review+
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158272/#review164490 I think, Bug 1319406 should also be fixed by this patch. Please make sure it is. r+ after I get the answer and try result is green ::: layout/base/nsLayoutUtils.cpp:3908 (Diff revision 4) > return false; > } > > -static void > -AddBoxesForFrame(nsIFrame* aFrame, > +void > +nsLayoutUtils::AddBoxesForFrame(nsIFrame* aFrame, > nsLayoutUtils::BoxCallback* aCallback) indent is not correct ::: layout/svg/nsSVGIntegrationUtils.cpp:232 (Diff revision 4) > nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame); > // 'r' is in "user space": > - nsRect r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(), > + nsRect r; > + if (aNonSVGFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone) { > + r = GetPreEffectsVisualOverflow( > + firstFrame, aNonSVGFrame, GetOffsetToBoundingBox(firstFrame)); indent is not correct. put firstFrame and aNonSVGFrame right after GetPreEffectsVisualOverflow, and put GetOffsetToBoundingBox(firstFrame) in the next line.
Attachment #8887410 - Flags: review?(cku)
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158272/#review164534
Attachment #8887410 - Flags: review?(cku) → review+
Attachment #8887410 - Flags: review?(cam)
Comment on attachment 8887410 [details] Bug 1319407 - Apply clip-path to each frame when box-decoration-break is clone. https://reviewboard.mozilla.org/r/158272/#review165558 ::: layout/base/nsLayoutUtils.h:1141 (Diff revision 5) > public: > BoxCallback() : mIncludeCaptionBoxForTable(true) {} > virtual void AddBox(nsIFrame* aFrame) = 0; > bool mIncludeCaptionBoxForTable; > }; > + static void AddBoxesForFrame(nsIFrame* aFrame, BoxCallback* aCallback); Maybe add a comment here saying what AddBoxesForFrame does, now that it's a public method? ::: layout/painting/nsDisplayList.cpp:8465 (Diff revision 5) > bool nsDisplayMask::TryMerge(nsDisplayItem* aItem) > { > if (aItem->GetType() != TYPE_MASK) > return false; > > + // Do not merge items with StyleBoxDecorationBreak::Clone prop value Nit: The comment as it's written basically says the same thing as the code, so I think it's not too useful. Maybe something like this, instead, which says why we don't do this? // Do not merge items for box-decoration-break:clone elements, // since each box should have its own mask in that case.
Attachment #8887410 - Flags: review?(cam) → review+
Keywords: checkin-needed
Keywords: checkin-needed
Pushed by cku@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/e89eb57f2e97 Apply clip-path to each frame when box-decoration-break is clone. r=cjku,heycam https://hg.mozilla.org/integration/autoland/rev/8b127b0d655a Add reftest for box-decoration-break with clip-path. r=cjku
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
Depends on: 1385745
Depends on: 1388622
Depends on: 1388985
Depends on: 1391143
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

Creator:
Created:
Updated:
Size: