Index: Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp |
=================================================================== |
--- Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp (revision 106008) |
+++ Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp (working copy) |
@@ -54,7 +54,6 @@ |
RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node) |
: RenderSVGResourceContainer(node) |
- , m_invalidationBlocked(false) |
{ |
} |
@@ -69,9 +68,6 @@ |
void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidation) |
{ |
- if (m_invalidationBlocked) |
- return; |
- |
m_clipBoundaries = FloatRect(); |
if (!m_clipper.isEmpty()) { |
deleteAllValues(m_clipper); |
@@ -84,9 +80,6 @@ |
void RenderSVGResourceClipper::removeClientFromCache(RenderObject* client, bool markForInvalidation) |
{ |
ASSERT(client); |
- if (m_invalidationBlocked) |
- return; |
- |
if (m_clipper.contains(client)) |
delete m_clipper.take(client); |
@@ -199,7 +192,10 @@ |
} |
} |
- drawContentIntoMaskImage(clipperData, objectBoundingBox); |
+ if (!drawContentIntoMaskImage(clipperData, objectBoundingBox)) { |
+ stateSaver.restore(); |
+ clipperData->clipMaskImage.clear(); |
+ } |
} |
if (!clipperData->clipMaskImage) |
@@ -211,6 +207,7 @@ |
bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData, const FloatRect& objectBoundingBox) |
{ |
+ ASSERT(frame()); |
ASSERT(clipperData); |
ASSERT(clipperData->clipMaskImage); |
@@ -225,11 +222,23 @@ |
maskContext->concatCTM(maskContentTransformation); |
} |
+ // Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints: |
+ // - fill-opacity/stroke-opacity/opacity set to 1 |
+ // - masker/filter not applied when rendering the children |
+ // - fill is set to the initial fill paint server (solid, black) |
+ // - stroke is set to the initial stroke paint server (none) |
+ PaintBehavior oldBehavior = frame()->view()->paintBehavior(); |
+ frame()->view()->setPaintBehavior(oldBehavior | PaintBehaviorRenderingSVGMask); |
+ |
// Draw all clipPath children into a global mask. |
for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { |
RenderObject* renderer = childNode->renderer(); |
if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) |
continue; |
+ if (renderer->needsLayout()) { |
+ frame()->view()->setPaintBehavior(oldBehavior); |
+ return false; |
+ } |
RenderStyle* style = renderer->style(); |
if (!style || style->display() == NONE || style->visibility() != VISIBLE) |
continue; |
@@ -249,35 +258,15 @@ |
if (!renderer->isSVGShape() && !renderer->isSVGText()) |
continue; |
- // Save the old RenderStyle of the current object for restoring after drawing |
- // it to the MaskImage. The new intermediate RenderStyle needs to inherit from |
- // the old one. |
- RefPtr<RenderStyle> oldRenderStyle = renderer->style(); |
- RefPtr<RenderStyle> newRenderStyle = RenderStyle::clone(oldRenderStyle.get()); |
- SVGRenderStyle* svgStyle = newRenderStyle.get()->accessSVGStyle(); |
- svgStyle->setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRenderStyle::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri()); |
- svgStyle->setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRenderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri()); |
- svgStyle->setFillRule(newClipRule); |
- newRenderStyle.get()->setOpacity(1); |
- svgStyle->setFillOpacity(1); |
- svgStyle->setStrokeOpacity(1); |
- svgStyle->setFilterResource(String()); |
- svgStyle->setMaskerResource(String()); |
+ maskContext->setFillRule(newClipRule); |
- // The setStyle() call results in a styleDidChange() call, which in turn invalidations the resources. |
- // As we're mutating the resource on purpose, block updates until we've resetted the style again. |
- m_invalidationBlocked = true; |
- renderer->setStyle(newRenderStyle.release()); |
- |
// In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule. |
// We have to pass the <use> renderer itself to renderSubtreeToImageBuffer() to apply it's x/y/transform/etc. values when rendering. |
// So if isUseElement is true, refetch the childNode->renderer(), as renderer got overriden above. |
SVGImageBufferTools::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransformation); |
- |
- renderer->setStyle(oldRenderStyle.release()); |
- m_invalidationBlocked = false; |
} |
+ frame()->view()->setPaintBehavior(oldBehavior); |
return true; |
} |