[webkit-reviews] review granted: [Bug 25431] Simplify how SVG containers paint (and likely fix bugs by doing so) : [Attachment 29827] Simplify how SVG containers paint

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Tue Apr 28 11:16:42 PDT 2009


Simon Fraser (smfr) <simon.fraser at apple.com> has granted Eric Seidel
<eric at webkit.org>'s request for review:
Bug 25431: Simplify how SVG containers paint (and likely fix bugs by doing so)
https://bugs.webkit.org/show_bug.cgi?id=25431

Attachment 29827: Simplify how SVG containers paint
https://bugs.webkit.org/attachment.cgi?id=29827&action=review

------- Additional Comments from Simon Fraser (smfr) <simon.fraser at apple.com>
>  bool RenderSVGContainer::selfWillPaint() const
>  {
>  #if ENABLE(SVG_FILTERS)
> @@ -121,29 +110,29 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo,
int, int)
>	// Spec: groups w/o children still may render filter content.
>      if (!firstChild() && !selfWillPaint())
>	   return;
> -    
> -    paintInfo.context->save();
> -    applyContentTransforms(paintInfo);
>  
> -    SVGResourceFilter* filter = 0;
> -    PaintInfo savedInfo(paintInfo);
> +    PaintInfo childPaintInfo(paintInfo);
>  
> -    FloatRect boundingBox = repaintRectInLocalCoordinates();
> -    if (paintInfo.phase == PaintPhaseForeground)
> -	   prepareToRenderSVGContent(this, paintInfo, boundingBox, filter); 
> +    childPaintInfo.context->save();
> +
> +    // Let the RenderSVGViewportContainer subclass clip if necessary
> +    applyViewportClip(childPaintInfo);
>  
> -    applyAdditionalTransforms(paintInfo);
> +    applyTransformToPaintInfo(childPaintInfo, localToParentTransform());
> +
> +    SVGResourceFilter* filter = 0;
> +    FloatRect boundingBox = repaintRectInLocalCoordinates();
> +    if (childPaintInfo.phase == PaintPhaseForeground)
> +	   prepareToRenderSVGContent(this, childPaintInfo, boundingBox,
filter);
>  
> -    // default implementation. Just pass paint through to the children
> -    PaintInfo childInfo(paintInfo);
> -    childInfo.paintingRoot = paintingRootForChildren(paintInfo);
> +    childPaintInfo.paintingRoot = paintingRootForChildren(childPaintInfo);
>      for (RenderObject* child = firstChild(); child; child =
child->nextSibling())
> -	   child->paint(childInfo, 0, 0);
> +	   child->paint(childPaintInfo, 0, 0);
>  
>      if (paintInfo.phase == PaintPhaseForeground)
> -	   finishRenderSVGContent(this, paintInfo, boundingBox, filter,
savedInfo.context);
> +	   finishRenderSVGContent(this, childPaintInfo, boundingBox, filter,
paintInfo.context);

Can we start to optimize painting by skipping children that are entirely
clipped out?

> +void RenderSVGImage::computeRectForRepaint(RenderBoxModelObject*
repaintContainer, IntRect& repaintRect, bool fixed)
>  {
> -    // FIXME: handle non-root repaintContainer
> -    return m_absoluteBounds;
> +    // Translate to coords in our parent renderer, and then call
computeRectForRepaint on our parent
> +    repaintRect = localToParentTransform().mapRect(repaintRect);
> +    parent()->computeRectForRepaint(repaintContainer, repaintRect, fixed);
>  }

It's a shame we can't just fall back on RenderBox::computeRectForRepaint(). If
we fixed that to be more
HTML-agnostic, could we?

>  void RenderSVGRoot::calcViewport()
> @@ -204,35 +182,59 @@ void RenderSVGRoot::calcViewport()
>      if (!selfNeedsLayout() && !svg->hasRelativeValues())
>	   return;
>  
> -    SVGLength width = svg->width();
> -    SVGLength height = svg->height();
>      if (!svg->hasSetContainerSize()) {
> -	   m_viewport = FloatRect(0, 0, width.value(svg), height.value(svg));
> -	   return;
> +	   // In the normal case of <svg> being stand-alone or in a CSSBoxModel
object we use
> +	   // RenderBox::width()/height() (which pulls data from RenderStyle)
> +	   m_viewportSize = FloatSize(width(), height());
> +    } else {
> +	   // In the SVGImage case grab the SVGLength values off of
SVGSVGElement and use
> +	   // the special relativeWidthValue accessors which respect the
specified containerSize
> +	   SVGLength width = svg->width();
> +	   SVGLength height = svg->height();
> +	   float viewportWidth = (width.unitType() == LengthTypePercentage) ?
svg->relativeWidthValue() : width.value(svg);
> +	   float viewportHeight = (height.unitType() == LengthTypePercentage) ?
svg->relativeHeightValue() : height.value(svg);
> +	   m_viewportSize = FloatSize(viewportWidth, viewportHeight);

Does this logic deserve to be wrapped in its own method?

>  TransformationMatrix RenderSVGRoot::localToParentTransform() const
>  {
> -    TransformationMatrix offsetTranslation;
> -    offsetTranslation.translate(x(), y());
> -    return localToParentTransformWithoutCSSParentOffset() *
offsetTranslation;
> +    IntSize parentToBorderBoxOffset = parentOriginToBorderBox();
> +
> +    TransformationMatrix borderBoxOriginToParentOrigin;
> +    borderBoxOriginToParentOrigin.translate(parentToBorderBoxOffset.width(),
parentToBorderBoxOffset.height());
> +
> +    return localToBorderBoxTransform() * borderBoxOriginToParentOrigin;
>  }

Some tests with <svg> inside transformed HTML would be good to see if this all
works.

> +void RenderSVGText::computeRectForRepaint(RenderBoxModelObject*
repaintContainer, IntRect& repaintRect, bool fixed)
> +{
> +    // Translate to coords in our parent renderer, and then call
computeRectForRepaint on our parent
> +    repaintRect = localToParentTransform().mapRect(repaintRect);
> +    parent()->computeRectForRepaint(repaintContainer, repaintRect, fixed);
>  }

Again, it's a shame we can't just drop into RenderBox::computeRectForRepaint()

> +    bool calculateLocalTransform();

What does the return value mean?

r=me


More information about the webkit-reviews mailing list