diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/svg/SVGRenderSupport.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGRenderSupport.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/SVGRenderSupport.cpp | 285 |
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, ¤t, current.objectBoundingBox()); + strokeBoundingBox.unite(current.repaintRectInLocalCoordinates()); } else { - updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox())); - strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates())); + updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, ¤t, 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 +} |