Closed Bug 1378710 Opened 7 years ago Closed 7 years ago

SVG: mask renders incorrectly when clipped group has animated contents

Categories

(Core :: SVG, defect, P1)

53 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla56
Tracking Status
firefox-esr52 --- unaffected
firefox54 --- wontfix
firefox55 --- wontfix
firefox56 --- fixed

People

(Reporter: paul.lebeau, Assigned: u459114)

References

(Blocks 1 open bug)

Details

(Keywords: regression)

Attachments

(3 files, 1 obsolete file)

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0 Build ID: 20170628075643 Steps to reproduce: Related to bug #1378707. Also see: https://stackoverflow.com/questions/44935822/svg-text-clippath-in-firefox If a mask is applies to a group that contains only animated elements, then it does not render correctly. Actual results: See: https://jsfiddle.net/q770saez/1/ <svg viewBox="0 0 600 150"> <mask id="m"> <rect width="100%" height="100%" fill="black"/> <polygon points="0,0, 600,75, 0,150" fill="white"/> </mask> <g mask="url(#m)"> <rect width="100%" height="100%" class="anim-shape"/> </g> </svg> .anim-shape { transform: translate(-600px, 0); animation: moving-panel 4s forwards ease-out; } @keyframes moving-panel { 100% { transform: translate(0, 0); } } Expected results: But if you apply the same workaround as suggested in bug #1378707 (non-animated transparent rect in the group), the animation renders correctly. https://jsfiddle.net/q770saez/3/ <g mask="url(#m)"> <rect x="0" y="0" width="100%" height="100%" fill="transparent" /> <rect width="100%" height="100%" class="anim-shape"/> </g>
Component: Untriaged → SVG
Product: Firefox → Core
Assignee: nobody → cku
Flags: needinfo?(cku)
Has Regression Range: --- → yes
Attached image anim-mask.svg
The mask we generate in ContainerState::SetupMaskLayerForCSSMask is not correct. Attach a simpler test case
Not a new regression in 54. Mark 54 won't fix and see if we can fix it in 55.
Attachment #8885179 - Attachment is obsolete: true
Status: NEW → ASSIGNED
Priority: -- → P1
Attached file anim-mask.html
Attachment #8885577 - Flags: review?(mstange)
Comment on attachment 8885577 [details] Bug 1378710 - Disable OMTA if there is a mask applied on any ancestor of the animation target. https://reviewboard.mozilla.org/r/156428/#review161632 ::: layout/painting/nsDisplayList.cpp:7419 (Diff revision 6) > AnimationPerformanceWarning::Type::TransformFrameInactive)); > > return NoPrerender; > } > > + // We should not allow prerender if any ancestor container element carries ...if any ancestor container element has mask/clip-path effects. ::: layout/painting/nsDisplayList.cpp:7423 (Diff revision 6) > > + // We should not allow prerender if any ancestor container element carries > + // mask/clip-path effects. > + // > + // With prerender and sync transform animation, we do not need to restyle > + // animated element to respect position change, since that transform is done ...need to restyle an animated element to respect position changes, since... ::: layout/painting/nsDisplayList.cpp:7425 (Diff revision 6) > + // mask/clip-path effects. > + // > + // With prerender and sync transform animation, we do not need to restyle > + // animated element to respect position change, since that transform is done > + // by layer animation. As a result, the container element is not aware of > + // position change of that containing element and lose chance to update and loses the chance to... ::: layout/painting/nsDisplayList.cpp:7426 (Diff revision 6) > + // > + // With prerender and sync transform animation, we do not need to restyle > + // animated element to respect position change, since that transform is done > + // by layer animation. As a result, the container element is not aware of > + // position change of that containing element and lose chance to update > + // the content of mask/clip-path accordingly. the content of the mask/clip-path ::: layout/painting/nsDisplayList.cpp:7428 (Diff revision 6) > + // animated element to respect position change, since that transform is done > + // by layer animation. As a result, the container element is not aware of > + // position change of that containing element and lose chance to update > + // the content of mask/clip-path accordingly. > + // > + // But why need updating mask? This is relative to how we generate a mask Why do we need to update a mask? rather than But why need updating... ::: layout/painting/nsDisplayList.cpp:7432 (Diff revision 6) > + // > + // But why need updating mask? This is relative to how we generate a mask > + // layer in ContainerState::SetupMaskLayerForCSSMask. While creating a mask > + // layer, to reduce memory usage, we did not choose the size of the masked > + // element as mask size. Instead, we read the union of bounds of all children > + // display items by nsDisplayWrapList::GetBounds, which is smaller then or smaller than ::: layout/painting/nsDisplayList.cpp:7433 (Diff revision 6) > + // But why need updating mask? This is relative to how we generate a mask > + // layer in ContainerState::SetupMaskLayerForCSSMask. While creating a mask > + // layer, to reduce memory usage, we did not choose the size of the masked > + // element as mask size. Instead, we read the union of bounds of all children > + // display items by nsDisplayWrapList::GetBounds, which is smaller then or > + // equal to the masked element's boundary, and use it as position/size of as the position/size ::: layout/painting/nsDisplayList.cpp:7435 (Diff revision 6) > + // layer, to reduce memory usage, we did not choose the size of the masked > + // element as mask size. Instead, we read the union of bounds of all children > + // display items by nsDisplayWrapList::GetBounds, which is smaller then or > + // equal to the masked element's boundary, and use it as position/size of > + // the mask layer. That union bounds is actually effected by the geometry of > + // the animated element. To keep the content of mask up to date, forbid forbidding of prerender is required
Comment on attachment 8885577 [details] Bug 1378710 - Disable OMTA if there is a mask applied on any ancestor of the animation target. https://reviewboard.mozilla.org/r/156428/#review164930 I'm not very happy about this patch, but I don't have any better ideas. I guess this is not a regression compared to before we had layerized masks, so it's ok. ::: layout/painting/nsDisplayList.cpp:7434 (Diff revision 8) > + // mask layer in ContainerState::SetupMaskLayerForCSSMask. While creating a > + // mask layer, to reduce memory usage, we did not choose the size of the > + // masked element as mask size. Instead, we read the union of bounds of all > + // children display items by nsDisplayWrapList::GetBounds, which is smaller > + // than or equal to the masked element's boundary, and use it as the position > + ///size of the mask layer. That union bounds is actually effected by the affected ::: layout/painting/nsDisplayList.cpp:7438 (Diff revision 8) > + // than or equal to the masked element's boundary, and use it as the position > + ///size of the mask layer. That union bounds is actually effected by the > + // geometry of the animated element. To keep the content of mask up to date, > + // forbidding of prerender is required. > + for (nsIFrame* container = aFrame->GetParent(); container; > + container = container->GetParent()) { Should this be using nsLayoutUtils::GetCrossDocParentFrame? Otherwise I think you could have an OMTA animation inside a transparent iframe where the iframe has a mask.
Attachment #8885577 - Flags: review?(mstange) → review+
Comment on attachment 8885577 [details] Bug 1378710 - Disable OMTA if there is a mask applied on any ancestor of the animation target. https://reviewboard.mozilla.org/r/156428/#review164930 I don't like it either, since it's bad for rendering smoothness of animation. Base on my understanding of gecko, that what I can do so far, let me file a follow up to unblock this limitation later.
Blocks: 1382909
Pushed by cku@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/41c7ad2d0326 Disable OMTA if there is a mask applied on any ancestor of the animation target. r=mstange
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
Please request Beta approval on this when you get a chance.
Flags: needinfo?(cku)
Version: 54 Branch → 53 Branch
Comment on attachment 8885577 [details] Bug 1378710 - Disable OMTA if there is a mask applied on any ancestor of the animation target. Approval Request Comment [Feature/Bug causing the regression]: Bug 1313898 [User impact if declined]: the shape of mask may not be correct during a transform animation of a masked descedant. [Is this code covered by automated tests?]: no [Has the fix been verified in Nightly?]: [Needs manual test from QE? If yes, steps to reproduce]: 1. verify the renering result of anim-mask.svg during the animation, and compare with chrome 2. virify the renering result of https://jsfiddle.net/q770saez/1/, and compare with chrome [List of other uplifts needed for the feature/fix]: NA [Is the change risky?]: no [Why is the change risky/not risky?]: small change. [String changes made/needed]: NA I did not create a test case for this bug since reftest harness can not capture this glich. Glitch we saw on the screen is vanished while we do a snapshot in reftest.
Flags: needinfo?(cku)
Attachment #8885577 - Flags: approval-mozilla-beta?
Comment on attachment 8885577 [details] Bug 1378710 - Disable OMTA if there is a mask applied on any ancestor of the animation target. We shipped this in 54, we're almost at RC week, I'd prefer to punt on this for 55, unless somebody tells me this is really critical.
Attachment #8885577 - Flags: approval-mozilla-beta? → approval-mozilla-beta-
Pushed by cku@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/72873c109b1b (followup) Correct typo in the comment. r=me DONTBUILD
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: