Bug 49035 - SVG <path> inside a <defs> is still marked as needing layout at the end of FrameView::layout
Summary: SVG <path> inside a <defs> is still marked as needing layout at the end of Fr...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC OS X 10.5
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on: 81006
Blocks: 49019
  Show dependency treegraph
 
Reported: 2010-11-04 15:54 PDT by James Robinson
Modified: 2012-03-21 15:04 PDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description James Robinson 2010-11-04 15:54:33 PDT
The assertions in https://bugs.webkit.org/show_bug.cgi?id=49019 trigger on several SVG tests.  Here's a reduction of one of the issues that triggers on svg/custom/recursive-mask.svg:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
<defs>
    <rect id="rect" x="0" y="100" width="50" height="50" fill="white" mask="url(#mask4)"/> 
    <mask id="mask4"> 
        <use xlink:href="#rect"/> 
    </mask>
</defs>
</svg>

At the end of FrameView::layout() the render tree looks like this:


RenderView 0x3dbc2d8                   	#document	0x3e67420
  RenderSVGRoot 0x3eba5a8              	svg	0x3eb85c0
    RenderSVGHiddenContainer 0x3ebc6b8 	defs	0x3ebc460
*     RenderSVGPath 0x3ebdde8          	rect	0x3ebca40
      RenderSVGResourceMasker 0x3ec0168	mask	0x3ebfa40
        RenderSVGContainer 0x3daf418   	use	0x3ebf260
          RenderSVGContainer 0x3db05b8 	g	0x3daf4e0
            RenderSVGPath 0x3db0738    	rect	0x3dafd90


and the RenderSVGPath associated with the <rect> is still marked as m_needsLayout.
Comment 1 James Robinson 2010-11-04 19:18:24 PDT
Should children of a <defs> exist in the render tree at all?  They should never be rendered according to the SVG spec.
Comment 2 Dirk Schulze 2010-11-04 23:13:24 PDT
(In reply to comment #1)
> Should children of a <defs> exist in the render tree at all?  They should never be rendered according to the SVG spec.

They are accessible with xlink:href by <use>, <symbol> and <feImage> and need to have a renderer.
Comment 3 Nikolas Zimmermann 2010-11-05 00:57:22 PDT
(In reply to comment #2)
> (In reply to comment #1)
> > Should children of a <defs> exist in the render tree at all?  They should never be rendered according to the SVG spec.
> 
> They are accessible with xlink:href by <use>, <symbol> and <feImage> and need to have a renderer.
This is unrelated.

To answer the question. Any object within <defs> has a renderer, they're all placed in a RenderSVGHiddenContainer. This is needed, as for instance gradients and gradient stops are typically placed in a <defs> object:

<defs> <linearGradient> <stop stop-color="red"> ...
stop-color is a CSS property, and thus needs to be modifiable through CSS. That requires a renderer for the <stop> otherwhise we can't listen to "styleDidChange" events.
I could give more examples why this is needed.

Note, that a RenderSVGHiddenContainer::paint() is a no-op, the <defs> subtree will never be painted.
Comment 4 Nikolas Zimmermann 2010-11-05 01:00:42 PDT
(In reply to comment #0)
> The assertions in https://bugs.webkit.org/show_bug.cgi?id=49019 trigger on several SVG tests.  Here's a reduction of one of the issues that triggers on svg/custom/recursive-mask.svg:
> 
> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
> <defs>
>     <rect id="rect" x="0" y="100" width="50" height="50" fill="white" mask="url(#mask4)"/> 
>     <mask id="mask4"> 
>         <use xlink:href="#rect"/> 
>     </mask>
> </defs>
> </svg>
> 
> At the end of FrameView::layout() the render tree looks like this:
> 
> 
> RenderView 0x3dbc2d8                       #document    0x3e67420
>   RenderSVGRoot 0x3eba5a8                  svg    0x3eb85c0
>     RenderSVGHiddenContainer 0x3ebc6b8     defs    0x3ebc460
> *     RenderSVGPath 0x3ebdde8              rect    0x3ebca40
>       RenderSVGResourceMasker 0x3ec0168    mask    0x3ebfa40
>         RenderSVGContainer 0x3daf418       use    0x3ebf260
>           RenderSVGContainer 0x3db05b8     g    0x3daf4e0
>             RenderSVGPath 0x3db0738        rect    0x3dafd90
> 
> 
> and the RenderSVGPath associated with the <rect> is still marked as m_needsLayout.
The one marked with the star * ? Or the one cloned <rect> within the <use> subtree?

I guess that's RenderSVGHiddenContainer::layout's fault. More precisely the SVGRenderSupport::layoutChildren optimizations, we could end up with an inconsistent tree there...
Can you investigate a bit further, where it fails to go in the subtree?
Comment 5 Dirk Schulze 2010-11-05 07:15:08 PDT
(In reply to comment #3)
> (In reply to comment #2)
> > (In reply to comment #1)
> > > Should children of a <defs> exist in the render tree at all?  They should never be rendered according to the SVG spec.
> > 
> > They are accessible with xlink:href by <use>, <symbol> and <feImage> and need to have a renderer.
> This is unrelated.
I was talking about RenderSVGPath.
Comment 6 Rob Buis 2010-11-20 09:24:36 PST
The testcase can be reduced some more:


<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
    <rect id="rect" x="0" y="100" width="50" height="50" fill="white" mask="url(#mask4)"/>
     <mask id="mask4">
    </mask>
</defs>
</svg>

First look points at RenderSVGResourceContainer::layout(), where removeAllClientsFromCache can be called. For the above case this means the already layouted rect (done in SVGSupport::layoutChildren) gets
invalidated, so setNeedsLayout(true) is called on it and the assert from bug 49019 is hit. The problem seems to be only triggered when the resource is after the referencing element.
Cheers,

Rob.
Comment 7 Dirk Schulze 2010-11-20 09:28:05 PST
(In reply to comment #6)
> The testcase can be reduced some more:
> 
> 
> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
> <defs>
>     <rect id="rect" x="0" y="100" width="50" height="50" fill="white" mask="url(#mask4)"/>
>      <mask id="mask4">
>     </mask>
> </defs>
> </svg>
> 
> First look points at RenderSVGResourceContainer::layout(), where removeAllClientsFromCache can be called. For the above case this means the already layouted rect (done in SVGSupport::layoutChildren) gets
> invalidated, so setNeedsLayout(true) is called on it and the assert from bug 49019 is hit. The problem seems to be only triggered when the resource is after the referencing element.
> Cheers,
> 
> Rob.

If I reference the rect after the <defs> section by a <use> element, the test works, but if it is before this section, it asserts as well. So it might be a problem that the parsing of the document did not finished and the resources are unknown. Note, this only happens for mask and filter, not for clipper, gradient or pattern.
Comment 8 Dirk Schulze 2010-11-20 09:30:33 PST
(In reply to comment #7)
> If I reference the rect after the <defs> section by a <use> element, the test works, but if it is before this section, it asserts as well. So it might be a problem that the parsing of the document did not finished and the resources are unknown. Note, this only happens for mask and filter, not for clipper, gradient or pattern.

Never mind last comment, wrong bug.
Comment 9 Nikolas Zimmermann 2012-01-27 23:27:28 PST
Hm, I can't reproduce this anymore. James, do you want to give your patch at bug 49019 another try?
Comment 10 James Robinson 2012-01-27 23:29:15 PST
(In reply to comment #9)
> Hm, I can't reproduce this anymore. James, do you want to give your patch at bug 49019 another try?

There are 3 other open bugs blocking that one, so I'm not super optimistic. Might give it a try on monday.
Comment 11 Nikolas Zimmermann 2012-01-27 23:45:42 PST
(In reply to comment #10)
> (In reply to comment #9)
> > Hm, I can't reproduce this anymore. James, do you want to give your patch at bug 49019 another try?
> 
> There are 3 other open bugs blocking that one, so I'm not super optimistic. Might give it a try on monday.

Heh just realized, that I couldn't see any assertion w/o applying your patch. I'll do that soon, and test svg/ with it.
Comment 12 Nikolas Zimmermann 2012-02-17 04:07:48 PST
(In reply to comment #11)
> Heh just realized, that I couldn't see any assertion w/o applying your patch. I'll do that soon, and test svg/ with it.

Okay, the original testcase from James, and the one modified by Rob don't trigger layout invariant assertions anymore, but there are two other svg tests firing now:
svg/custom/layout-loop.svg (evil, will be hard to track down)
svg/custom/use-crash-pending-resource.svg (also not a simple one)
I'll see what I can do.
Comment 13 Stephen Chenney 2012-03-21 15:04:01 PDT
Fixed thanks to bug 81006, and change r111601: <http://trac.webkit.org/changeset/111601>