Open Bug 1458353 Opened 7 years ago Updated 5 months ago

2d transforms on SVG elements should not create isolated groups

Categories

(Core :: SVG, enhancement, P3)

enhancement

Tracking

()

Tracking Status
firefox61 --- affected

People

(Reporter: mstange, Unassigned)

References

Details

Testcases: https://codepen.io/AmeliaBR/details/ZKPQYY/ If you have mix-blend-mode on an element, it blends within the isolated group that the element is located in. In SVG, what creates an isolated group is defined at https://drafts.fxtf.org/compositing-1/#isolatedgroups : > 3.3. Behavior specific to SVG > > By default, every element must create a non-isolated group. > > However, certain operations in SVG will create isolated groups. If one of the > following features is used, the group must become isolated: > > opacity > filters > 3D transforms (2D transforms must NOT cause isolation) > blending > masking We currently do not implement the part about "2D transforms must NOT cause isolation": Whenever an nsIFrame returns true from IsTransformed(), we enter BuildDisplayListForStackingContext to create the nsDisplayTransform, which causes us to wrap the contents of the frame into an nsDisplayBlendContainer, which creates an isolated group by forcing the ContainerLayer it creates to have an intermediate surface.
Component: Layout: Web Painting → SVG
There are a few ideas for how to fix this: - Inside BuildDisplayListForStackingContext, we could check whether the only reason that the frame is treated as a stacking context is because it has a 2d transform, and then do something special for it. - Or we could a new method, e.g. BuildDisplayListForTransformedFrame, which is a copy of BuildDisplayListForStackingContext except that it only handles transforms; and maybe BuildDisplayListForStackingContext can even call into this new method or share code with it. If we don't create an nsDisplayBlendContainer for 2d transforms, we also need to make sure that it does get created correctly somewhere further up the stack, by some ancestor element which actually is an isolated group. I think this can be achieved by not running this AutoSaveRestoreContainsBlendMode code in the 2d transform code path: > // reset blend mode so we can keep track if this stacking context needs have > // a nsDisplayBlendContainer. Set the blend mode back when the routine exits > // so we keep track if the parent stacking context needs a container too. > AutoSaveRestoreContainsBlendMode autoRestoreBlendMode(*aBuilder); > aBuilder->SetContainsBlendMode(false); Then aBuilder->ContainsBlendMode() will be picked up somewhere further up the stack. We also need to make sure that the ContainerLayer which gets created for the 2d nsDisplayTransform does not create an intermediate surface for other reasons. This is determined in ContainerLayer::DefaultComputeEffectiveTransforms and can happen in a few different cases: - Having a mask layer (which happens with border-radius + overflow:hidden, for example) - Having a rectangle clip which is not axis-aligned in the parent intermediate surface - Having a rectangle clip in the presence of a non-integer axis-aligned transform SVG itself does not provide means for rectangle clipping or border-radius clipping unless you use clip-path, which creates an isolated group, so it's possible that this is not actually a problem. If the outer <svg> itself creates the clip, then the clip is only non-axis aligned if there's a CSS transform on the <svg> or an ancestor, and then that CSS transform is a stacking context which is an isolated group, so maybe non-axis aligned clips are not a problem either. I haven't thought this case through completely, though. Non-integer axis aligned transforms and border-radius clipping of the <svg> elements might still be a problem. For WebRender, I think we can have transform that's not an isolating group by creating a WebRender reference frame but not a WebRender StackingContext. This would need more investigation.
Priority: -- → P3

Additional testcase from the duplicate bug: https://codepen.io/noleli/details/bGrbJEQ

Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.