diff options
Diffstat (limited to 'Source/WebCore/rendering/svg/RenderSVGImage.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/RenderSVGImage.cpp | 89 |
1 files changed, 53 insertions, 36 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.cpp b/Source/WebCore/rendering/svg/RenderSVGImage.cpp index 58dc14597..cd2386d7a 100644 --- a/Source/WebCore/rendering/svg/RenderSVGImage.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGImage.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Apple Inc. * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2007, 2008, 2009 Rob Buis <buis@kde.org> * Copyright (C) 2009 Google, Inc. @@ -24,20 +24,17 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "RenderSVGImage.h" -#include "Attr.h" #include "FloatQuad.h" #include "GraphicsContext.h" #include "LayoutRepainter.h" #include "PointerEventsHitRules.h" #include "RenderImageResource.h" #include "RenderLayer.h" +#include "RenderSVGResource.h" #include "RenderSVGResourceFilter.h" #include "SVGImageElement.h" -#include "SVGLength.h" #include "SVGRenderingContext.h" #include "SVGResources.h" #include "SVGResourcesCache.h" @@ -45,8 +42,8 @@ namespace WebCore { -RenderSVGImage::RenderSVGImage(SVGImageElement& element, PassRef<RenderStyle> style) - : RenderSVGModelObject(element, std::move(style)) +RenderSVGImage::RenderSVGImage(SVGImageElement& element, RenderStyle&& style) + : RenderSVGModelObject(element, WTFMove(style)) , m_needsBoundariesUpdate(true) , m_needsTransformUpdate(true) , m_imageResource(std::make_unique<RenderImageResource>()) @@ -56,27 +53,48 @@ RenderSVGImage::RenderSVGImage(SVGImageElement& element, PassRef<RenderStyle> st RenderSVGImage::~RenderSVGImage() { +} + +void RenderSVGImage::willBeDestroyed() +{ imageResource().shutdown(); + RenderSVGModelObject::willBeDestroyed(); } SVGImageElement& RenderSVGImage::imageElement() const { - return toSVGImageElement(RenderSVGModelObject::element()); + return downcast<SVGImageElement>(RenderSVGModelObject::element()); } bool RenderSVGImage::updateImageViewport() { FloatRect oldBoundaries = m_objectBoundingBox; + bool updatedViewport = false; SVGLengthContext lengthContext(&imageElement()); m_objectBoundingBox = FloatRect(imageElement().x().value(lengthContext), imageElement().y().value(lengthContext), imageElement().width().value(lengthContext), imageElement().height().value(lengthContext)); - if (oldBoundaries == m_objectBoundingBox) - return false; + // Images with preserveAspectRatio=none should force non-uniform scaling. This can be achieved + // by setting the image's container size to its intrinsic size. + // See: http://www.w3.org/TR/SVG/single-page.html, 7.8 The ‘preserveAspectRatio’ attribute. + if (imageElement().preserveAspectRatio().align() == SVGPreserveAspectRatioValue::SVG_PRESERVEASPECTRATIO_NONE) { + if (CachedImage* cachedImage = imageResource().cachedImage()) { + LayoutSize intrinsicSize = cachedImage->imageSizeForRenderer(0, style().effectiveZoom()); + if (intrinsicSize != imageResource().imageSize(style().effectiveZoom())) { + imageResource().setContainerSizeForRenderer(roundedIntSize(intrinsicSize)); + updatedViewport = true; + } + } + } - imageResource().setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size()); - m_needsBoundariesUpdate = true; - return true; + if (oldBoundaries != m_objectBoundingBox) { + if (!updatedViewport) + imageResource().setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size()); + updatedViewport = true; + m_needsBoundariesUpdate = true; + } + + return updatedViewport; } void RenderSVGImage::layout() @@ -117,7 +135,8 @@ void RenderSVGImage::layout() void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) { - if (paintInfo.context->paintingDisabled() || style().visibility() == HIDDEN || !imageResource().hasImage()) + if (paintInfo.context().paintingDisabled() || paintInfo.phase != PaintPhaseForeground + || style().visibility() == HIDDEN || !imageResource().hasImage()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); @@ -125,36 +144,36 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) return; PaintInfo childPaintInfo(paintInfo); - bool drawsOutline = style().outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); - if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { - GraphicsContextStateSaver stateSaver(*childPaintInfo.context); - childPaintInfo.applyTransform(m_localTransform); + GraphicsContextStateSaver stateSaver(childPaintInfo.context()); + childPaintInfo.applyTransform(m_localTransform); - if (childPaintInfo.phase == PaintPhaseForeground) { - SVGRenderingContext renderingContext(*this, childPaintInfo); + if (childPaintInfo.phase == PaintPhaseForeground) { + SVGRenderingContext renderingContext(*this, childPaintInfo); - if (renderingContext.isRenderingPrepared()) { - if (style().svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground)) - return; + if (renderingContext.isRenderingPrepared()) { + if (style().svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground)) + return; - paintForeground(childPaintInfo); - } + paintForeground(childPaintInfo); } - - if (drawsOutline) - paintOutline(childPaintInfo, IntRect(boundingBox)); } + + if (style().outlineWidth()) + paintOutline(childPaintInfo, IntRect(boundingBox)); } void RenderSVGImage::paintForeground(PaintInfo& paintInfo) { RefPtr<Image> image = imageResource().image(); + if (!image) + return; + FloatRect destRect = m_objectBoundingBox; FloatRect srcRect(0, 0, image->width(), image->height()); imageElement().preserveAspectRatio().transformRect(destRect, srcRect); - paintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect); + paintInfo.context().drawImage(*image, destRect, srcRect); } void RenderSVGImage::invalidateBufferedForeground() @@ -171,14 +190,14 @@ bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, request, style().pointerEvents()); bool isVisible = (style().visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { - FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); + FloatPoint localPoint = localToParentTransform().inverse().value_or(AffineTransform()).mapPoint(pointInParent); if (!SVGRenderSupport::pointInClippingArea(*this, localPoint)) return false; if (hitRules.canHitFill) { if (m_objectBoundingBox.contains(localPoint)) { - updateHitTestResult(result, roundedLayoutPoint(localPoint)); + updateHitTestResult(result, LayoutPoint(localPoint)); return true; } } @@ -191,7 +210,7 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*) { // The image resource defaults to nullImage until the resource arrives. // This empty image may be cached by SVG resources which must be invalidated. - if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this)) + if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this)) resources->removeClientFromCache(*this); // Eventually notify parent resources, that we've changed. @@ -207,14 +226,12 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*) repaint(); } -void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) +void RenderSVGImage::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { // this is called from paint() after the localTransform has already been applied - IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates()); + LayoutRect contentRect = LayoutRect(repaintRectInLocalCoordinates()); if (!contentRect.isEmpty()) rects.append(contentRect); } } // namespace WebCore - -#endif // ENABLE(SVG) |