Bug 87572 - [Master] Redesign SVG resources
Summary: [Master] Redesign SVG resources
Status: RESOLVED WONTFIX
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on: 86941 87573
Blocks:
  Show dependency treegraph
 
Reported: 2012-05-25 23:01 PDT by Nikolas Zimmermann
Modified: 2014-03-04 06:12 PST (History)
9 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nikolas Zimmermann 2012-05-25 23:01:56 PDT
This bug tracks the redesign of SVG resources (linear/radialGradient, mask, clipPath, filter, marker).
In worst cases we need a 2-pass layout now from RenderSVGRoot, to avoid leaving the render tree with some objects still needing layout after RenderSVGRoot::layout() ran.

The question came up why renderers are needed at all for SVG resources. Here's a list of reasons:
- CSS Transitions/Animations support currently only work with RenderObjects (bug 87373 contains a fix)
- Tracking of style changes (styleDidChange/styleWillChange) - this can be avoided nowadays using nonRendererRenderStyle (bug 86941 eliminates RenderSVGradientStop)

These two can easily be fixed. That would already remove the need for <linearGradient> / <radialGradient> / <stop> renderers.
But what about <pattern>? <pattern> has children which need to be rendered at some point (indirectly).

<svg>
  <defs>
    <pattern id="somePattern">
      <rect/>
    </pattern>
   </defs>
  <circle fill="url(#somePattern)"/>
</svg>

Once the <circle> paints, it'll look up the <pattern> fill resource, and apply it to the current rendering context. For that to work we need a renderer for the <rect> that we can paint into an ImageBuffer.
In order to create renderers for the <rect> child of the <pattern>, the <pattern> needs a renderer as well: a RenderSVGHiddenContainer, which is never painted directly, nor participates in layout.
In ToT the design is similar: RenderSVGResourcePattern inherits from both RenderSVGResource (abstract base class) and RenderSVGResourceContainer, which itself inherits from RenderSVGHiddenContainer.
(RenderSVGHiddenContainer::layout() is not a no-op right now, it actually lays out the subtree, otherwise certain assumptions wouldn't hold anymore...)
--

In an ideal world RenderSVGHiddenContainer::layout() would be a no-op. All children of the RenderSVGHiddenContainer would always remain in needsLayout=true state, until they're used.
As they're used on paint() time, once the (see example above) <circle> paints, we basically would need to layout() the RenderSVGHiddenContainer subtree, while painting.
This is dangerous in general, as the <rect> inside the pattern could for instance be used by another <use> element, like this:

<svg>
  <defs>
    <pattern id="somePattern">
      <rect id="rect"/>
    </pattern>
   </defs>
  <use xlink:href="#rect"/>
  <circle fill="url(#somePattern)"/>
</svg>

Why is that dangerous? RenderSVGRoot::layout() is invoked, which does nothing for the <defs> element and its subtree, then proceeds laying out the <use> element + cloned shadow tree.
After that the <circle> is laid out, and the whole layout() is done, while the <rect> still needs layout.
Upon painting the subtree following happens: <defs> doesn't paint anything, the <use> is painted, then the <circle>. Once the <circle> paints the <pattern> children would need to be laid out.
As a result of laying out the <rect> the <use> element would be marked as needsLayout=true again.
So after RenderSVGRoot::layout() + RenderSVGRoot::paint() we still have an element that needs to be laid out...

This example is really basic, we have lots more complex test cases in LayoutTests/svg/ that would break when designing <pattern> like this.
It's yet undecided how to fix it for real. We should collect ideas here and prototype them.
Comment 1 Dirk Schulze 2014-03-04 06:12:39 PST
Time passed by and I am not sure if we still want to follow this approach. Closing the bug now.