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/RenderSVGResourcePattern.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp | 111 |
1 files changed, 59 insertions, 52 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp index 4ed8e6a98..ea936a4dc 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp @@ -19,8 +19,6 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "RenderSVGResourcePattern.h" #include "ElementIterator.h" @@ -29,20 +27,20 @@ #include "RenderSVGRoot.h" #include "SVGFitToViewBox.h" #include "SVGRenderingContext.h" +#include "SVGResources.h" +#include "SVGResourcesCache.h" namespace WebCore { -RenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType; - -RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement& element, PassRef<RenderStyle> style) - : RenderSVGResourceContainer(element, std::move(style)) +RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement& element, RenderStyle&& style) + : RenderSVGResourceContainer(element, WTFMove(style)) , m_shouldCollectPatternAttributes(true) { } SVGPatternElement& RenderSVGResourcePattern::patternElement() const { - return toSVGPatternElement(RenderSVGResourceContainer::element()); + return downcast<SVGPatternElement>(RenderSVGResourceContainer::element()); } void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation) @@ -52,42 +50,48 @@ void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidatio markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourcePattern::removeClientFromCache(RenderObject& client, bool markForInvalidation) +void RenderSVGResourcePattern::removeClientFromCache(RenderElement& client, bool markForInvalidation) { m_patternMap.remove(&client); markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsigned short resourceMode) +void RenderSVGResourcePattern::collectPatternAttributes(PatternAttributes& attributes) const { - PatternData* currentData = m_patternMap.get(object); - if (currentData && currentData->pattern) - return currentData; + const RenderSVGResourcePattern* current = this; - if (m_shouldCollectPatternAttributes) { - patternElement().synchronizeAnimatedSVGAttribute(anyQName()); + while (current) { + const SVGPatternElement& pattern = current->patternElement(); + pattern.collectPatternAttributes(attributes); - m_attributes = PatternAttributes(); - patternElement().collectPatternAttributes(m_attributes); - m_shouldCollectPatternAttributes = false; + auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*current); + current = resources ? downcast<RenderSVGResourcePattern>(resources->linkedResource()) : nullptr; } +} + +PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, unsigned short resourceMode, GraphicsContext& context) +{ + ASSERT(!m_shouldCollectPatternAttributes); + + PatternData* currentData = m_patternMap.get(&renderer); + if (currentData && currentData->pattern) + return currentData; // If we couldn't determine the pattern content element root, stop here. if (!m_attributes.patternContentElement()) - return 0; + return nullptr; // An empty viewBox disables rendering. if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty()) - return 0; + return nullptr; // Compute all necessary transformations to build the tile image & the pattern. FloatRect tileBoundaries; AffineTransform tileImageTransform; - if (!buildTileImageTransform(object, m_attributes, patternElement(), tileBoundaries, tileImageTransform)) - return 0; + if (!buildTileImageTransform(renderer, m_attributes, patternElement(), tileBoundaries, tileImageTransform)) + return nullptr; - AffineTransform absoluteTransformIgnoringRotation; - SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation); + AffineTransform absoluteTransformIgnoringRotation = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer); // Ignore 2D rotation, as it doesn't affect the size of the tile. SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation); @@ -99,20 +103,22 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign static_cast<float>(m_attributes.patternTransform().yScale())); // Build tile image. - std::unique_ptr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries); + auto tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries, context.renderingMode()); if (!tileImage) - return 0; + return nullptr; - RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore); + const IntSize tileImageSize = tileImage->logicalSize(); + + RefPtr<Image> copiedImage = ImageBuffer::sinkIntoImage(WTFMove(tileImage)); if (!copiedImage) - return 0; + return nullptr; // Build pattern. - OwnPtr<PatternData> patternData = adoptPtr(new PatternData); + auto patternData = std::make_unique<PatternData>(); patternData->pattern = Pattern::create(copiedImage, true, true); // Compute pattern space transformation. - const IntSize tileImageSize = tileImage->logicalSize(); + patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y()); patternData->transform.scale(tileBoundaries.width() / tileImageSize.width(), tileBoundaries.height() / tileImageSize.height()); @@ -123,7 +129,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign // Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows. if (resourceMode & ApplyToTextMode) { AffineTransform additionalTextTransformation; - if (shouldTransformOnTextPainting(object, additionalTextTransformation)) + if (shouldTransformOnTextPainting(renderer, additionalTextTransformation)) patternData->transform *= additionalTextTransformation; } patternData->pattern->setPatternSpaceTransform(patternData->transform); @@ -131,7 +137,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign // Various calls above may trigger invalidations in some fringe cases (ImageBuffer allocation // failures in the SVG image cache for example). To avoid having our PatternData deleted by // removeAllClientsFromCache(), we only make it visible in the cache at the very end. - return m_patternMap.set(object, patternData.release()).iterator->value.get(); + return m_patternMap.set(&renderer, WTFMove(patternData)).iterator->value.get(); } bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const RenderStyle& style, GraphicsContext*& context, unsigned short resourceMode) @@ -139,13 +145,21 @@ bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const Rend ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); + if (m_shouldCollectPatternAttributes) { + patternElement().synchronizeAnimatedSVGAttribute(anyQName()); + + m_attributes = PatternAttributes(); + collectPatternAttributes(m_attributes); + m_shouldCollectPatternAttributes = false; + } + // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified, // then the given effect (e.g. a gradient or a filter) will be ignored. FloatRect objectBoundingBox = renderer.objectBoundingBox(); if (m_attributes.patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty()) return false; - PatternData* patternData = buildPattern(&renderer, resourceMode); + PatternData* patternData = buildPattern(renderer, resourceMode, *context); if (!patternData) return false; @@ -156,13 +170,13 @@ bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const Rend if (resourceMode & ApplyToFillMode) { context->setAlpha(svgStyle.fillOpacity()); - context->setFillPattern(patternData->pattern); + context->setFillPattern(*patternData->pattern); context->setFillRule(svgStyle.fillRule()); } else if (resourceMode & ApplyToStrokeMode) { if (svgStyle.vectorEffect() == VE_NON_SCALING_STROKE) patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(&renderer, patternData->transform)); context->setAlpha(svgStyle.strokeOpacity()); - context->setStrokePattern(patternData->pattern); + context->setStrokePattern(*patternData->pattern); SVGRenderSupport::applyStrokeStyleToContext(context, style, renderer); } @@ -194,13 +208,13 @@ void RenderSVGResourcePattern::postApplyResource(RenderElement&, GraphicsContext if (path) context->fillPath(*path); else if (shape) - shape->fillShape(context); + shape->fillShape(*context); } if (resourceMode & ApplyToStrokeMode) { if (path) context->strokePath(*path); else if (shape) - shape->strokeShape(context); + shape->strokeShape(*context); } context->restore(); @@ -213,15 +227,13 @@ static inline FloatRect calculatePatternBoundaries(const PatternAttributes& attr return SVGLengthContext::resolveRectangle(&patternElement, attributes.patternUnits(), objectBoundingBox, attributes.x(), attributes.y(), attributes.width(), attributes.height()); } -bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer, +bool RenderSVGResourcePattern::buildTileImageTransform(RenderElement& renderer, const PatternAttributes& attributes, const SVGPatternElement& patternElement, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const { - ASSERT(renderer); - - FloatRect objectBoundingBox = renderer->objectBoundingBox(); + FloatRect objectBoundingBox = renderer.objectBoundingBox(); patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); if (patternBoundaries.width() <= 0 || patternBoundaries.height() <= 0) return false; @@ -237,25 +249,22 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer, return true; } -std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const +std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries, RenderingMode renderingMode) const { - clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries); - - std::unique_ptr<ImageBuffer> tileImage; - - if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated)) + clampedAbsoluteTileBoundaries = ImageBuffer::clampedRect(absoluteTileBoundaries); + auto tileImage = SVGRenderingContext::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, ColorSpaceSRGB, renderingMode); + if (!tileImage) return nullptr; - GraphicsContext* tileImageContext = tileImage->context(); - ASSERT(tileImageContext); + GraphicsContext& tileImageContext = tileImage->context(); // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation). - tileImageContext->scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(), + tileImageContext.scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(), clampedAbsoluteTileBoundaries.height() / tileBoundaries.height())); // Apply tile image transformations. if (!tileImageTransform.isIdentity()) - tileImageContext->concatCTM(tileImageTransform); + tileImageContext.concatCTM(tileImageTransform); AffineTransform contentTransformation; if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) @@ -274,5 +283,3 @@ std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const Pat } } - -#endif |