summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp')
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp111
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