diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderSVGResourcePattern.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderSVGResourcePattern.cpp | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/Source/WebCore/rendering/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/RenderSVGResourcePattern.cpp deleted file mode 100644 index cd64183..0000000 --- a/Source/WebCore/rendering/RenderSVGResourcePattern.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) Research In Motion Limited 2010. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#if ENABLE(SVG) -#include "RenderSVGResourcePattern.h" - -#include "FrameView.h" -#include "GraphicsContext.h" -#include "PatternAttributes.h" -#include "RenderSVGRoot.h" -#include "SVGImageBufferTools.h" -#include "SVGRenderSupport.h" - -namespace WebCore { - -RenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType; - -RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement* node) - : RenderSVGResourceContainer(node) - , m_shouldCollectPatternAttributes(true) -{ -} - -RenderSVGResourcePattern::~RenderSVGResourcePattern() -{ - if (m_pattern.isEmpty()) - return; - - deleteAllValues(m_pattern); - m_pattern.clear(); -} - -void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation) -{ - if (!m_pattern.isEmpty()) { - deleteAllValues(m_pattern); - m_pattern.clear(); - } - - m_shouldCollectPatternAttributes = true; - markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); -} - -void RenderSVGResourcePattern::removeClientFromCache(RenderObject* client, bool markForInvalidation) -{ - ASSERT(client); - - if (m_pattern.contains(client)) - delete m_pattern.take(client); - - markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); -} - -bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) -{ - ASSERT(object); - ASSERT(style); - ASSERT(context); - ASSERT(resourceMode != ApplyToDefaultMode); - - // Be sure to synchronize all SVG properties on the patternElement _before_ processing any further. - // Otherwhise the call to collectPatternAttributes() below, may cause the SVG DOM property - // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our - // PatternData object! Leaving out the line below will cause svg/dynamic-updates/SVGPatternElement-svgdom* to crash. - SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node()); - if (!patternElement) - return false; - - if (m_shouldCollectPatternAttributes) { - patternElement->updateAnimatedSVGAttribute(anyQName()); - - m_attributes = PatternAttributes(); - patternElement->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 = object->objectBoundingBox(); - if (m_attributes.boundingBoxMode() && objectBoundingBox.isEmpty()) - return false; - - if (!m_pattern.contains(object)) - m_pattern.set(object, new PatternData); - - PatternData* patternData = m_pattern.get(object); - if (!patternData->pattern) { - // If we couldn't determine the pattern content element root, stop here. - if (!m_attributes.patternContentElement()) - return false; - - // Compute all necessary transformations to build the tile image & the pattern. - FloatRect tileBoundaries; - AffineTransform tileImageTransform; - if (!buildTileImageTransform(object, m_attributes, patternElement, tileBoundaries, tileImageTransform)) - return false; - - AffineTransform absoluteTransform; - SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); - - FloatRect absoluteTileBoundaries = absoluteTransform.mapRect(tileBoundaries); - - // Build tile image. - OwnPtr<ImageBuffer> tileImage = createTileImage(object, m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform); - if (!tileImage) - return false; - - RefPtr<Image> copiedImage = tileImage->copyImage(); - if (!copiedImage) - return false; - - // Build pattern. - patternData->pattern = Pattern::create(copiedImage, true, true); - if (!patternData->pattern) - return false; - - // Compute pattern space transformation. - patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y()); - patternData->transform.scale(tileBoundaries.width() / absoluteTileBoundaries.width(), tileBoundaries.height() / absoluteTileBoundaries.height()); - - AffineTransform patternTransform = m_attributes.patternTransform(); - if (!patternTransform.isIdentity()) - patternData->transform.multiply(patternTransform); - - patternData->pattern->setPatternSpaceTransform(patternData->transform); - } - - // Draw pattern - context->save(); - - const SVGRenderStyle* svgStyle = style->svgStyle(); - ASSERT(svgStyle); - - if (resourceMode & ApplyToFillMode) { - context->setAlpha(svgStyle->fillOpacity()); - context->setFillPattern(patternData->pattern); - context->setFillRule(svgStyle->fillRule()); - } else if (resourceMode & ApplyToStrokeMode) { - if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE) - patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform)); - context->setAlpha(svgStyle->strokeOpacity()); - context->setStrokePattern(patternData->pattern); - SVGRenderSupport::applyStrokeStyleToContext(context, style, object); - } - - if (resourceMode & ApplyToTextMode) { - if (resourceMode & ApplyToFillMode) { - context->setTextDrawingMode(TextModeFill); - -#if PLATFORM(CG) - context->applyFillPattern(); -#endif - } else if (resourceMode & ApplyToStrokeMode) { - context->setTextDrawingMode(TextModeStroke); - -#if PLATFORM(CG) - context->applyStrokePattern(); -#endif - } - } - - return true; -} - -void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path) -{ - ASSERT(context); - ASSERT(resourceMode != ApplyToDefaultMode); - - if (path && !(resourceMode & ApplyToTextMode)) { - if (resourceMode & ApplyToFillMode) - context->fillPath(*path); - else if (resourceMode & ApplyToStrokeMode) - context->strokePath(*path); - } - - context->restore(); -} - -static inline FloatRect calculatePatternBoundaries(const PatternAttributes& attributes, - const FloatRect& objectBoundingBox, - const SVGPatternElement* patternElement) -{ - ASSERT(patternElement); - - if (attributes.boundingBoxMode()) - return FloatRect(attributes.x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(), - attributes.y().valueAsPercentage() * objectBoundingBox.height() + objectBoundingBox.y(), - attributes.width().valueAsPercentage() * objectBoundingBox.width(), - attributes.height().valueAsPercentage() * objectBoundingBox.height()); - - return FloatRect(attributes.x().value(patternElement), - attributes.y().value(patternElement), - attributes.width().value(patternElement), - attributes.height().value(patternElement)); -} - -bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer, - const PatternAttributes& attributes, - const SVGPatternElement* patternElement, - FloatRect& patternBoundaries, - AffineTransform& tileImageTransform) const -{ - ASSERT(renderer); - ASSERT(patternElement); - - FloatRect objectBoundingBox = renderer->objectBoundingBox(); - patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); - if (patternBoundaries.width() <= 0 || patternBoundaries.height() <= 0) - return false; - - AffineTransform viewBoxCTM = patternElement->viewBoxToViewTransform(patternElement->viewBox(), patternElement->preserveAspectRatio(), patternBoundaries.width(), patternBoundaries.height()); - - // Apply viewBox/objectBoundingBox transformations. - if (!viewBoxCTM.isIdentity()) - tileImageTransform = viewBoxCTM; - else if (attributes.boundingBoxModeContent()) { - tileImageTransform.translate(objectBoundingBox.x(), objectBoundingBox.y()); - tileImageTransform.scale(objectBoundingBox.width(), objectBoundingBox.height()); - } - - return true; -} - -PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(RenderObject* object, - const PatternAttributes& attributes, - const FloatRect& tileBoundaries, - const FloatRect& absoluteTileBoundaries, - const AffineTransform& tileImageTransform) const -{ - ASSERT(object); - - // Clamp tile image size against SVG viewport size, as last resort, to avoid allocating huge image buffers. - FloatRect contentBoxRect = SVGRenderSupport::findTreeRootObject(object)->contentBoxRect(); - - FloatRect clampedAbsoluteTileBoundaries = absoluteTileBoundaries; - if (clampedAbsoluteTileBoundaries.width() > contentBoxRect.width()) - clampedAbsoluteTileBoundaries.setWidth(contentBoxRect.width()); - - if (clampedAbsoluteTileBoundaries.height() > contentBoxRect.height()) - clampedAbsoluteTileBoundaries.setHeight(contentBoxRect.height()); - - OwnPtr<ImageBuffer> tileImage; - - if (!SVGImageBufferTools::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB)) - return PassOwnPtr<ImageBuffer>(); - - GraphicsContext* tileImageContext = tileImage->context(); - ASSERT(tileImageContext); - - // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation). - tileImageContext->scale(FloatSize(absoluteTileBoundaries.width() / tileBoundaries.width(), - absoluteTileBoundaries.height() / tileBoundaries.height())); - - // Apply tile image transformations. - if (!tileImageTransform.isIdentity()) - tileImageContext->concatCTM(tileImageTransform); - - AffineTransform contentTransformation; - - // Draw the content into the ImageBuffer. - for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { - if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer()) - continue; - SVGImageBufferTools::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation); - } - - return tileImage.release(); -} - -} - -#endif |