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/RenderSVGResourceClipper.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp | 104 |
1 files changed, 48 insertions, 56 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp index 5a6af206d..5d835fe17 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp @@ -21,8 +21,6 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "RenderSVGResourceClipper.h" #include "ElementIterator.h" @@ -42,10 +40,8 @@ namespace WebCore { -RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResourceType; - -RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement& element, PassRef<RenderStyle> style) - : RenderSVGResourceContainer(element, std::move(style)) +RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement& element, RenderStyle&& style) + : RenderSVGResourceContainer(element, WTFMove(style)) { } @@ -61,7 +57,7 @@ void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidatio markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceClipper::removeClientFromCache(RenderObject& client, bool markForInvalidation) +void RenderSVGResourceClipper::removeClientFromCache(RenderElement& client, bool markForInvalidation) { m_clipper.remove(&client); @@ -73,10 +69,10 @@ bool RenderSVGResourceClipper::applyResource(RenderElement& renderer, const Rend ASSERT(context); ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); - return applyClippingToContext(renderer, renderer.objectBoundingBox(), renderer.repaintRectInLocalCoordinates(), context); + return applyClippingToContext(renderer, renderer.objectBoundingBox(), renderer.repaintRectInLocalCoordinates(), *context); } -bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox) +bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext& context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox) { // If the current clip-path gets clipped itself, we have to fallback to masking. if (!style().svgStyle().clipperResource().isEmpty()) @@ -96,9 +92,9 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const // Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts. if (renderer->isSVGText()) return false; - if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGGraphicsElement()) + if (!childNode->isSVGElement() || !downcast<SVGElement>(*childNode).isSVGGraphicsElement()) continue; - SVGGraphicsElement* styled = toSVGGraphicsElement(childNode); + SVGGraphicsElement& styled = downcast<SVGGraphicsElement>(*childNode); const RenderStyle& style = renderer->style(); if (style.display() == NONE || style.visibility() != VISIBLE) continue; @@ -108,7 +104,7 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const return false; // Fallback to masking, if there is more than one clipping path. if (clipPath.isEmpty()) { - styled->toClipPath(clipPath); + styled.toClipPath(clipPath); clipRule = svgStyle.clipRule(); } else return false; @@ -127,77 +123,68 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const // The SVG specification wants us to clip everything, if clip-path doesn't have a child. if (clipPath.isEmpty()) clipPath.addRect(FloatRect()); - context->clipPath(clipPath, clipRule); + context.clipPath(clipPath, clipRule); return true; } -bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox, - const FloatRect& repaintRect, GraphicsContext* context) +bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox, const FloatRect& repaintRect, GraphicsContext& context) { - bool missingClipperData = !m_clipper.contains(&renderer); - if (missingClipperData) - m_clipper.set(&renderer, std::make_unique<ClipperData>()); + ClipperMaskImage& clipperMaskImage = addRendererToClipper(renderer); + bool shouldCreateClipperMaskImage = !clipperMaskImage; - bool shouldCreateClipData = false; AffineTransform animatedLocalTransform = clipPathElement().animatedLocalTransform(); - ClipperData* clipperData = m_clipper.get(&renderer); - if (!clipperData->clipMaskImage) { - if (pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox)) - return true; - shouldCreateClipData = true; - } - AffineTransform absoluteTransform; - SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform); + if (shouldCreateClipperMaskImage && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox)) + return true; - if (shouldCreateClipData && !repaintRect.isEmpty()) { - if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated)) - return false; + AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer); - GraphicsContext* maskContext = clipperData->clipMaskImage->context(); - ASSERT(maskContext); + if (shouldCreateClipperMaskImage && !repaintRect.isEmpty()) { + // FIXME (149469): This image buffer should not be unconditionally unaccelerated. Making it match the context breaks nested clipping, though. + clipperMaskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceSRGB, Unaccelerated); + if (!clipperMaskImage) + return false; - maskContext->concatCTM(animatedLocalTransform); + GraphicsContext& maskContext = clipperMaskImage->context(); + maskContext.concatCTM(animatedLocalTransform); // clipPath can also be clipped by another clipPath. - SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); + auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); RenderSVGResourceClipper* clipper; bool succeeded; if (resources && (clipper = resources->clipper())) { - GraphicsContextStateSaver stateSaver(*maskContext); + GraphicsContextStateSaver stateSaver(maskContext); if (!clipper->applyClippingToContext(*this, objectBoundingBox, repaintRect, maskContext)) return false; - succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox); + succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox); // The context restore applies the clipping on non-CG platforms. } else - succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox); + succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox); if (!succeeded) - clipperData->clipMaskImage.reset(); + clipperMaskImage.reset(); } - if (!clipperData->clipMaskImage) + if (!clipperMaskImage) return false; - SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage, missingClipperData); + SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperMaskImage, shouldCreateClipperMaskImage); return true; } -bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData, const FloatRect& objectBoundingBox) +bool RenderSVGResourceClipper::drawContentIntoMaskImage(const ClipperMaskImage& clipperMaskImage, const FloatRect& objectBoundingBox) { - ASSERT(clipperData); - ASSERT(clipperData->clipMaskImage); + ASSERT(clipperMaskImage); - GraphicsContext* maskContext = clipperData->clipMaskImage->context(); - ASSERT(maskContext); + GraphicsContext& maskContext = clipperMaskImage->context(); AffineTransform maskContentTransformation; if (clipPathElement().clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y()); maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - maskContext->concatCTM(maskContentTransformation); + maskContext.concatCTM(maskContentTransformation); } // Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints: @@ -224,11 +211,11 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData WindRule newClipRule = style.svgStyle().clipRule(); bool isUseElement = child.hasTagName(SVGNames::useTag); if (isUseElement) { - SVGUseElement& useElement = toSVGUseElement(child); + SVGUseElement& useElement = downcast<SVGUseElement>(child); renderer = useElement.rendererClipChild(); if (!renderer) continue; - if (!useElement.hasAttribute(SVGNames::clip_ruleAttr)) + if (!useElement.hasAttributeWithoutSynchronization(SVGNames::clip_ruleAttr)) newClipRule = renderer->style().svgStyle().clipRule(); } @@ -236,12 +223,12 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData if (!renderer->isSVGShape() && !renderer->isSVGText()) continue; - maskContext->setFillRule(newClipRule); + maskContext.setFillRule(newClipRule); // 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. - SVGRenderingContext::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? *child.renderer() : *renderer, maskContentTransformation); + SVGRenderingContext::renderSubtreeToImageBuffer(clipperMaskImage.get(), isUseElement ? *child.renderer() : *renderer, maskContentTransformation); } view().frameView().setPaintBehavior(oldBehavior); @@ -265,6 +252,11 @@ void RenderSVGResourceClipper::calculateClipContentRepaintRect() m_clipBoundaries = clipPathElement().animatedLocalTransform().mapRect(m_clipBoundaries); } +ClipperMaskImage& RenderSVGResourceClipper::addRendererToClipper(const RenderObject& object) +{ + return m_clipper.add(&object, ClipperMaskImage()).iterator->value; +} + bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint) { FloatPoint point = nodeAtPoint; @@ -275,10 +267,10 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin AffineTransform transform; transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - point = transform.inverse().mapPoint(point); + point = transform.inverse().value_or(AffineTransform()).mapPoint(point); } - point = clipPathElement().animatedLocalTransform().inverse().mapPoint(point); + point = clipPathElement().animatedLocalTransform().inverse().value_or(AffineTransform()).mapPoint(point); for (Node* childNode = clipPathElement().firstChild(); childNode; childNode = childNode->nextSibling()) { RenderObject* renderer = childNode->renderer(); @@ -288,7 +280,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin continue; IntPoint hitPoint; HitTestResult result(hitPoint); - if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent | HitTestRequest::DisallowShadowContent), result, point, HitTestForeground)) + if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent | HitTestRequest::DisallowUserAgentShadowContent), result, point, HitTestForeground)) return true; } @@ -298,8 +290,10 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject& object) { // Resource was not layouted yet. Give back the boundingBox of the object. - if (selfNeedsLayout()) + if (selfNeedsLayout()) { + addRendererToClipper(object); return object.objectBoundingBox(); + } if (m_clipBoundaries.isEmpty()) calculateClipContentRepaintRect(); @@ -316,5 +310,3 @@ FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject& obje } } - -#endif // ENABLE(SVG) |