summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGRenderSupport.cpp')
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.cpp285
1 files changed, 166 insertions, 119 deletions
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
index 9602927f2..0113c7015 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
@@ -23,21 +23,22 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGRenderSupport.h"
#include "NodeRenderStyle.h"
+#include "RenderChildIterator.h"
#include "RenderElement.h"
#include "RenderGeometryMap.h"
#include "RenderIterator.h"
#include "RenderLayer.h"
+#include "RenderSVGImage.h"
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMarker.h"
#include "RenderSVGResourceMasker.h"
#include "RenderSVGRoot.h"
#include "RenderSVGText.h"
+#include "RenderSVGTransformableContainer.h"
#include "RenderSVGViewportContainer.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
@@ -49,8 +50,8 @@ FloatRect SVGRenderSupport::repaintRectForRendererInLocalCoordinatesExcludingSVG
{
// FIXME: Add support for RenderSVGBlock.
- if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer())
- return toRenderSVGModelObject(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow();
+ if (is<RenderSVGModelObject>(renderer))
+ return downcast<RenderSVGModelObject>(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow();
return renderer.repaintRectInLocalCoordinates();
}
@@ -67,34 +68,43 @@ LayoutRect SVGRenderSupport::clippedOverflowRectForRepaint(const RenderElement&
const SVGRenderStyle& svgStyle = renderer.style().svgStyle();
if (const ShadowData* shadow = svgStyle.shadow())
shadow->adjustRectForShadow(repaintRect);
- renderer.computeFloatRectForRepaint(repaintContainer, repaintRect);
- return enclosingLayoutRect(repaintRect);
+ return enclosingLayoutRect(renderer.computeFloatRectForRepaint(repaintRect, repaintContainer));
}
-void SVGRenderSupport::computeFloatRectForRepaint(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed)
+FloatRect SVGRenderSupport::computeFloatRectForRepaint(const RenderElement& renderer, const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed)
{
+ FloatRect adjustedRect = repaintRect;
const SVGRenderStyle& svgStyle = renderer.style().svgStyle();
if (const ShadowData* shadow = svgStyle.shadow())
- shadow->adjustRectForShadow(repaintRect);
- repaintRect.inflate(renderer.style().outlineWidth());
+ shadow->adjustRectForShadow(adjustedRect);
+ adjustedRect.inflate(renderer.style().outlineWidth());
// Translate to coords in our parent renderer, and then call computeFloatRectForRepaint() on our parent.
- repaintRect = renderer.localToParentTransform().mapRect(repaintRect);
- renderer.parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+ adjustedRect = renderer.localToParentTransform().mapRect(adjustedRect);
+ return renderer.parent()->computeFloatRectForRepaint(adjustedRect, repaintContainer, fixed);
}
-void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
+const RenderElement& SVGRenderSupport::localToParentTransform(const RenderElement& renderer, AffineTransform &transform)
{
- transformState.applyTransform(renderer.localToParentTransform());
-
ASSERT(renderer.parent());
auto& parent = *renderer.parent();
-
- // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
+
+ // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
// to map an element from SVG viewport coordinates to CSS box coordinates.
- // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
- if (parent.isSVGRoot())
- transformState.applyTransform(toRenderSVGRoot(parent).localToBorderBoxTransform());
+ if (is<RenderSVGRoot>(parent))
+ transform = downcast<RenderSVGRoot>(parent).localToBorderBoxTransform() * renderer.localToParentTransform();
+ else
+ transform = renderer.localToParentTransform();
+
+ return parent;
+}
+
+void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
+{
+ AffineTransform transform;
+ auto& parent = localToParentTransform(renderer, transform);
+
+ transformState.applyTransform(transform);
MapCoordinatesFlags mode = UseTransforms;
parent.mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
@@ -104,19 +114,10 @@ const RenderElement* SVGRenderSupport::pushMappingToContainer(const RenderElemen
{
ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != &renderer);
- ASSERT(renderer.parent());
- auto& parent = *renderer.parent();
-
- // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
- // to map an element from SVG viewport coordinates to CSS box coordinates.
- // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
- if (parent.isSVGRoot()) {
- TransformationMatrix matrix(renderer.localToParentTransform());
- matrix.multiply(toRenderSVGRoot(parent).localToBorderBoxTransform());
- geometryMap.push(&renderer, matrix);
- } else
- geometryMap.push(&renderer, renderer.localToParentTransform());
+ AffineTransform transform;
+ auto& parent = localToParentTransform(renderer, transform);
+ geometryMap.push(&renderer, transform);
return &parent;
}
@@ -127,13 +128,13 @@ bool SVGRenderSupport::checkForSVGRepaintDuringLayout(const RenderElement& rende
// When a parent container is transformed in SVG, all children will be painted automatically
// so we are able to skip redundant repaint checks.
auto parent = renderer.parent();
- return !(parent && parent->isSVGContainer() && toRenderSVGContainer(parent)->didTransformToRootUpdate());
+ return !(is<RenderSVGContainer>(parent) && downcast<RenderSVGContainer>(*parent).didTransformToRootUpdate());
}
// Update a bounding box taking into account the validity of the other bounding box.
-static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
+static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, const RenderObject* other, FloatRect otherBoundingBox)
{
- bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
+ bool otherValid = is<RenderSVGContainer>(*other) ? downcast<RenderSVGContainer>(*other).isObjectBoundingBoxValid() : true;
if (!otherValid)
return;
@@ -155,17 +156,21 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderElement& contai
// When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes
// the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound
// the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also.
- for (RenderObject* current = container.firstChild(); current; current = current->nextSibling()) {
- if (current->isSVGHiddenContainer())
+ for (auto& current : childrenOfType<RenderObject>(container)) {
+ if (current.isSVGHiddenContainer())
+ continue;
+
+ // Don't include elements in the union that do not render.
+ if (is<RenderSVGShape>(current) && downcast<RenderSVGShape>(current).isRenderingDisabled())
continue;
- const AffineTransform& transform = current->localToParentTransform();
+ const AffineTransform& transform = current.localToParentTransform();
if (transform.isIdentity()) {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
- strokeBoundingBox.unite(current->repaintRectInLocalCoordinates());
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, &current, current.objectBoundingBox());
+ strokeBoundingBox.unite(current.repaintRectInLocalCoordinates());
} else {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
- strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, &current, transform.mapRect(current.objectBoundingBox()));
+ strokeBoundingBox.unite(transform.mapRect(current.repaintRectInLocalCoordinates()));
}
}
@@ -180,141 +185,149 @@ bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepa
return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect);
}
-const RenderSVGRoot& SVGRenderSupport::findTreeRootObject(const RenderElement& start)
+RenderSVGRoot* SVGRenderSupport::findTreeRootObject(RenderElement& start)
{
- return *lineageOfType<RenderSVGRoot>(start).first();
+ return lineageOfType<RenderSVGRoot>(start).first();
}
-static inline void invalidateResourcesOfChildren(RenderObject& start)
+const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderElement& start)
{
- ASSERT(!start.needsLayout());
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start))
- resources->removeClientFromCache(start, false);
+ return lineageOfType<RenderSVGRoot>(start).first();
+}
+
+static inline void invalidateResourcesOfChildren(RenderElement& renderer)
+{
+ ASSERT(!renderer.needsLayout());
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer))
+ resources->removeClientFromCache(renderer, false);
- for (RenderObject* child = start.firstChildSlow(); child; child = child->nextSibling())
- invalidateResourcesOfChildren(*child);
+ for (auto& child : childrenOfType<RenderElement>(renderer))
+ invalidateResourcesOfChildren(child);
}
static inline bool layoutSizeOfNearestViewportChanged(const RenderElement& renderer)
{
const RenderElement* start = &renderer;
- while (start && !start->isSVGRoot() && !start->isSVGViewportContainer())
+ while (start && !is<RenderSVGRoot>(*start) && !is<RenderSVGViewportContainer>(*start))
start = start->parent();
ASSERT(start);
- ASSERT(start->isSVGRoot() || start->isSVGViewportContainer());
- if (start->isSVGViewportContainer())
- return toRenderSVGViewportContainer(start)->isLayoutSizeChanged();
+ if (is<RenderSVGViewportContainer>(*start))
+ return downcast<RenderSVGViewportContainer>(*start).isLayoutSizeChanged();
- return toRenderSVGRoot(start)->isLayoutSizeChanged();
+ return downcast<RenderSVGRoot>(*start).isLayoutSizeChanged();
}
bool SVGRenderSupport::transformToRootChanged(RenderElement* ancestor)
{
- while (ancestor && !ancestor->isSVGRoot()) {
- if (ancestor->isSVGTransformableContainer())
- return toRenderSVGContainer(ancestor)->didTransformToRootUpdate();
- if (ancestor->isSVGViewportContainer())
- return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpdate();
+ while (ancestor && !is<RenderSVGRoot>(*ancestor)) {
+ if (is<RenderSVGTransformableContainer>(*ancestor))
+ return downcast<RenderSVGTransformableContainer>(*ancestor).didTransformToRootUpdate();
+ if (is<RenderSVGViewportContainer>(*ancestor))
+ return downcast<RenderSVGViewportContainer>(*ancestor).didTransformToRootUpdate();
ancestor = ancestor->parent();
}
return false;
}
+void SVGRenderSupport::layoutDifferentRootIfNeeded(const RenderElement& renderer)
+{
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) {
+ auto* svgRoot = SVGRenderSupport::findTreeRootObject(renderer);
+ ASSERT(svgRoot);
+ resources->layoutDifferentRootIfNeeded(svgRoot);
+ }
+}
+
void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout)
{
bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start);
bool transformChanged = transformToRootChanged(&start);
bool hasSVGShadow = rendererHasSVGShadow(start);
bool needsBoundariesUpdate = start.needsBoundariesUpdate();
- HashSet<RenderObject*> notlayoutedObjects;
+ HashSet<RenderElement*> elementsThatDidNotReceiveLayout;
- for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) {
+ for (auto& child : childrenOfType<RenderObject>(start)) {
bool needsLayout = selfNeedsLayout;
- bool childEverHadLayout = child->everHadLayout();
+ bool childEverHadLayout = child.everHadLayout();
if (needsBoundariesUpdate && hasSVGShadow) {
// If we have a shadow, our shadow is baked into our children's cached boundaries,
// so they need to update.
- child->setNeedsBoundariesUpdate();
+ child.setNeedsBoundariesUpdate();
needsLayout = true;
}
if (transformChanged) {
// If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
- if (child->isSVGText())
- toRenderSVGText(child)->setNeedsTextMetricsUpdate();
+ if (is<RenderSVGText>(child))
+ downcast<RenderSVGText>(child).setNeedsTextMetricsUpdate();
needsLayout = true;
}
- if (layoutSizeChanged) {
+ if (layoutSizeChanged && is<SVGElement>(*child.node())) {
// When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
- if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
- if (element->hasRelativeLengths()) {
- // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
- if (child->isSVGShape())
- toRenderSVGShape(child)->setNeedsShapeUpdate();
- else if (child->isSVGText()) {
- toRenderSVGText(child)->setNeedsTextMetricsUpdate();
- toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
- }
-
- needsLayout = true;
+ auto& element = downcast<SVGElement>(*child.node());
+ if (element.hasRelativeLengths()) {
+ // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
+ if (is<RenderSVGShape>(child))
+ downcast<RenderSVGShape>(child).setNeedsShapeUpdate();
+ else if (is<RenderSVGText>(child)) {
+ auto& svgText = downcast<RenderSVGText>(child);
+ svgText.setNeedsTextMetricsUpdate();
+ svgText.setNeedsPositioningValuesUpdate();
}
+
+ needsLayout = true;
}
}
if (needsLayout)
- child->setNeedsLayout(MarkOnlyThis);
+ child.setNeedsLayout(MarkOnlyThis);
- if (child->needsLayout()) {
- toRenderElement(child)->layout();
+ if (child.needsLayout()) {
+ layoutDifferentRootIfNeeded(downcast<RenderElement>(child));
+ downcast<RenderElement>(child).layout();
// Renderers are responsible for repainting themselves when changing, except
// for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds.
// We could handle this in the individual objects, but for now it's easier to have
// parent containers call repaint(). (RenderBlock::layout* has similar logic.)
if (!childEverHadLayout)
- child->repaint();
- } else if (layoutSizeChanged)
- notlayoutedObjects.add(child);
+ child.repaint();
+ } else if (layoutSizeChanged && is<RenderElement>(child))
+ elementsThatDidNotReceiveLayout.add(&downcast<RenderElement>(child));
- ASSERT(!child->needsLayout());
+ ASSERT(!child.needsLayout());
}
if (!layoutSizeChanged) {
- ASSERT(notlayoutedObjects.isEmpty());
+ ASSERT(elementsThatDidNotReceiveLayout.isEmpty());
return;
}
// If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path.
- for (auto child : notlayoutedObjects)
- invalidateResourcesOfChildren(*child);
+ for (auto* element : elementsThatDidNotReceiveLayout)
+ invalidateResourcesOfChildren(*element);
}
bool SVGRenderSupport::isOverflowHidden(const RenderElement& renderer)
{
- // SVG doesn't support independent x/y overflow
- ASSERT(renderer.style().overflowX() == renderer.style().overflowY());
-
- // OSCROLL is never set for SVG - see StyleResolver::adjustRenderStyle
- ASSERT(renderer.style().overflowX() != OSCROLL);
-
// RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size.
- ASSERT(!renderer.isRoot());
+ ASSERT(!renderer.isDocumentElementRenderer());
- return renderer.style().overflowX() == OHIDDEN;
+ return renderer.style().overflowX() == OHIDDEN || renderer.style().overflowX() == OSCROLL;
}
bool SVGRenderSupport::rendererHasSVGShadow(const RenderObject& renderer)
{
// FIXME: Add support for RenderSVGBlock.
- if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer())
- return toRenderSVGModelObject(renderer).hasSVGShadow();
+ if (is<RenderSVGModelObject>(renderer))
+ return downcast<RenderSVGModelObject>(renderer).hasSVGShadow();
- if (renderer.isSVGRoot())
- return toRenderSVGRoot(renderer).hasSVGShadow();
+ if (is<RenderSVGRoot>(renderer))
+ return downcast<RenderSVGRoot>(renderer).hasSVGShadow();
return false;
}
@@ -323,13 +336,13 @@ void SVGRenderSupport::setRendererHasSVGShadow(RenderObject& renderer, bool hasS
{
// FIXME: Add support for RenderSVGBlock.
- if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer()) {
- toRenderSVGModelObject(renderer).setHasSVGShadow(hasShadow);
+ if (is<RenderSVGModelObject>(renderer)) {
+ downcast<RenderSVGModelObject>(renderer).setHasSVGShadow(hasShadow);
return;
}
- if (renderer.isSVGRoot())
- toRenderSVGRoot(renderer).setHasSVGShadow(hasShadow);
+ if (is<RenderSVGRoot>(renderer))
+ downcast<RenderSVGRoot>(renderer).setHasSVGShadow(hasShadow);
}
void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& renderer, FloatRect& repaintRect)
@@ -357,20 +370,18 @@ void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& rend
if (localToRootTransform.isIdentity())
return;
- AffineTransform rootToLocalTransform = localToRootTransform.inverse();
+ AffineTransform rootToLocalTransform = localToRootTransform.inverse().value_or(AffineTransform());
repaintRect = rootToLocalTransform.mapRect(repaintRect);
}
void SVGRenderSupport::intersectRepaintRectWithResources(const RenderElement& renderer, FloatRect& repaintRect)
{
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources)
return;
-#if ENABLE(FILTERS)
if (RenderSVGResourceFilter* filter = resources->filter())
repaintRect = filter->resourceBoundingBox(renderer);
-#endif
if (RenderSVGResourceClipper* clipper = resources->clipper())
repaintRect.intersect(clipper->resourceBoundingBox(renderer));
@@ -386,7 +397,7 @@ bool SVGRenderSupport::filtersForceContainerLayout(const RenderElement& renderer
if (!renderer.normalChildNeedsLayout())
return false;
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources || !resources->filter())
return false;
@@ -397,7 +408,7 @@ bool SVGRenderSupport::pointInClippingArea(const RenderElement& renderer, const
{
// We just take clippers into account to determine if a point is on the node. The Specification may
// change later and we also need to check maskers.
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources)
return true;
@@ -415,23 +426,31 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const
const SVGRenderStyle& svgStyle = style.svgStyle();
- SVGLengthContext lengthContext(toSVGElement(renderer.element()));
- context->setStrokeThickness(svgStyle.strokeWidth().value(lengthContext));
- context->setLineCap(svgStyle.capStyle());
- context->setLineJoin(svgStyle.joinStyle());
- if (svgStyle.joinStyle() == MiterJoin)
+ SVGLengthContext lengthContext(downcast<SVGElement>(renderer.element()));
+ context->setStrokeThickness(lengthContext.valueForLength(style.strokeWidth()));
+ context->setLineCap(style.capStyle());
+ context->setLineJoin(style.joinStyle());
+ if (style.joinStyle() == MiterJoin)
context->setMiterLimit(svgStyle.strokeMiterLimit());
- const Vector<SVGLength>& dashes = svgStyle.strokeDashArray();
+ const Vector<SVGLengthValue>& dashes = svgStyle.strokeDashArray();
if (dashes.isEmpty())
context->setStrokeStyle(SolidStroke);
else {
DashArray dashArray;
dashArray.reserveInitialCapacity(dashes.size());
- for (unsigned i = 0, size = dashes.size(); i < size; ++i)
- dashArray.uncheckedAppend(dashes[i].value(lengthContext));
+ bool canSetLineDash = false;
- context->setLineDash(dashArray, svgStyle.strokeDashOffset().value(lengthContext));
+ for (auto& dash : dashes) {
+ dashArray.uncheckedAppend(dash.value(lengthContext));
+ if (dashArray.last() > 0)
+ canSetLineDash = true;
+ }
+
+ if (canSetLineDash)
+ context->setLineDash(dashArray, lengthContext.valueForLength(svgStyle.strokeDashOffset()));
+ else
+ context->setStrokeStyle(SolidStroke);
}
}
@@ -440,12 +459,40 @@ void SVGRenderSupport::childAdded(RenderElement& parent, RenderObject& child)
SVGRenderSupport::setRendererHasSVGShadow(child, SVGRenderSupport::rendererHasSVGShadow(parent) || SVGRenderSupport::rendererHasSVGShadow(child));
}
-void SVGRenderSupport::styleChanged(RenderElement& renderer)
+void SVGRenderSupport::styleChanged(RenderElement& renderer, const RenderStyle* oldStyle)
{
auto parent = renderer.parent();
SVGRenderSupport::setRendererHasSVGShadow(renderer, (parent && SVGRenderSupport::rendererHasSVGShadow(*parent)) || renderer.style().svgStyle().shadow());
+
+#if ENABLE(CSS_COMPOSITING)
+ if (renderer.element() && renderer.element()->isSVGElement() && (!oldStyle || renderer.style().hasBlendMode() != oldStyle->hasBlendMode()))
+ SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(renderer);
+#else
+ UNUSED_PARAM(oldStyle);
+#endif
}
+#if ENABLE(CSS_COMPOSITING)
+bool SVGRenderSupport::isolatesBlending(const RenderStyle& style)
+{
+ return style.svgStyle().isolatesBlending() || style.hasFilter() || style.hasBlendMode() || style.opacity() < 1.0f;
}
+void SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(const RenderElement& renderer)
+{
+ ASSERT(renderer.element());
+ ASSERT(renderer.element()->isSVGElement());
+
+ bool maskedAncestorShouldIsolateBlending = renderer.style().hasBlendMode();
+ for (auto* ancestor = renderer.element()->parentElement(); ancestor && ancestor->isSVGElement(); ancestor = ancestor->parentElement()) {
+ if (!downcast<SVGElement>(*ancestor).isSVGGraphicsElement() || !isolatesBlending(*ancestor->computedStyle()))
+ continue;
+
+ if (ancestor->computedStyle()->svgStyle().hasMasker())
+ downcast<SVGGraphicsElement>(*ancestor).setShouldIsolateBlending(maskedAncestorShouldIsolateBlending);
+
+ return;
+ }
+}
#endif
+}