121939df44de1705786c545cd1bf519d47250322dBen Murdoch/* 221939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> 321939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) Research In Motion Limited 2010. All rights reserved. 421939df44de1705786c545cd1bf519d47250322dBen Murdoch * 521939df44de1705786c545cd1bf519d47250322dBen Murdoch * This library is free software; you can redistribute it and/or 621939df44de1705786c545cd1bf519d47250322dBen Murdoch * modify it under the terms of the GNU Library General Public 721939df44de1705786c545cd1bf519d47250322dBen Murdoch * License as published by the Free Software Foundation; either 821939df44de1705786c545cd1bf519d47250322dBen Murdoch * version 2 of the License, or (at your option) any later version. 921939df44de1705786c545cd1bf519d47250322dBen Murdoch * 1021939df44de1705786c545cd1bf519d47250322dBen Murdoch * This library is distributed in the hope that it will be useful, 1121939df44de1705786c545cd1bf519d47250322dBen Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 1221939df44de1705786c545cd1bf519d47250322dBen Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1321939df44de1705786c545cd1bf519d47250322dBen Murdoch * Library General Public License for more details. 1421939df44de1705786c545cd1bf519d47250322dBen Murdoch * 1521939df44de1705786c545cd1bf519d47250322dBen Murdoch * You should have received a copy of the GNU Library General Public License 1621939df44de1705786c545cd1bf519d47250322dBen Murdoch * along with this library; see the file COPYING.LIB. If not, write to 1721939df44de1705786c545cd1bf519d47250322dBen Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 1821939df44de1705786c545cd1bf519d47250322dBen Murdoch * Boston, MA 02110-1301, USA. 1921939df44de1705786c545cd1bf519d47250322dBen Murdoch */ 2021939df44de1705786c545cd1bf519d47250322dBen Murdoch 2121939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "config.h" 2221939df44de1705786c545cd1bf519d47250322dBen Murdoch 2321939df44de1705786c545cd1bf519d47250322dBen Murdoch#if ENABLE(SVG) 2421939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "RenderSVGResourcePattern.h" 2521939df44de1705786c545cd1bf519d47250322dBen Murdoch 26ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block#include "FrameView.h" 2721939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "GraphicsContext.h" 2821939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "PatternAttributes.h" 29e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "RenderSVGRoot.h" 30e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "SVGImageBufferTools.h" 3121939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "SVGRenderSupport.h" 3221939df44de1705786c545cd1bf519d47250322dBen Murdoch 3321939df44de1705786c545cd1bf519d47250322dBen Murdochnamespace WebCore { 3421939df44de1705786c545cd1bf519d47250322dBen Murdoch 3521939df44de1705786c545cd1bf519d47250322dBen MurdochRenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType; 3621939df44de1705786c545cd1bf519d47250322dBen Murdoch 3721939df44de1705786c545cd1bf519d47250322dBen MurdochRenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement* node) 3821939df44de1705786c545cd1bf519d47250322dBen Murdoch : RenderSVGResourceContainer(node) 39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_shouldCollectPatternAttributes(true) 4021939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 4121939df44de1705786c545cd1bf519d47250322dBen Murdoch} 4221939df44de1705786c545cd1bf519d47250322dBen Murdoch 4321939df44de1705786c545cd1bf519d47250322dBen MurdochRenderSVGResourcePattern::~RenderSVGResourcePattern() 4421939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 45db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (m_pattern.isEmpty()) 46db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block return; 4721939df44de1705786c545cd1bf519d47250322dBen Murdoch 4821939df44de1705786c545cd1bf519d47250322dBen Murdoch deleteAllValues(m_pattern); 4921939df44de1705786c545cd1bf519d47250322dBen Murdoch m_pattern.clear(); 5021939df44de1705786c545cd1bf519d47250322dBen Murdoch} 5121939df44de1705786c545cd1bf519d47250322dBen Murdoch 52f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation) 5321939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 54db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (!m_pattern.isEmpty()) { 55db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block deleteAllValues(m_pattern); 56db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block m_pattern.clear(); 57db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block } 5821939df44de1705786c545cd1bf519d47250322dBen Murdoch 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_shouldCollectPatternAttributes = true; 60f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); 61967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 62967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 63f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourcePattern::removeClientFromCache(RenderObject* client, bool markForInvalidation) 64967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 65db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block ASSERT(client); 66967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 67db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (m_pattern.contains(client)) 68db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block delete m_pattern.take(client); 69967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 70f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); 7121939df44de1705786c545cd1bf519d47250322dBen Murdoch} 7221939df44de1705786c545cd1bf519d47250322dBen Murdoch 7321939df44de1705786c545cd1bf519d47250322dBen Murdochbool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) 7421939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 7521939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(object); 7621939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(style); 7721939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(context); 7821939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(resourceMode != ApplyToDefaultMode); 7921939df44de1705786c545cd1bf519d47250322dBen Murdoch 8021939df44de1705786c545cd1bf519d47250322dBen Murdoch // Be sure to synchronize all SVG properties on the patternElement _before_ processing any further. 81e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Otherwhise the call to collectPatternAttributes() below, may cause the SVG DOM property 82f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our 8321939df44de1705786c545cd1bf519d47250322dBen Murdoch // PatternData object! Leaving out the line below will cause svg/dynamic-updates/SVGPatternElement-svgdom* to crash. 8421939df44de1705786c545cd1bf519d47250322dBen Murdoch SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node()); 8521939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!patternElement) 8621939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 8721939df44de1705786c545cd1bf519d47250322dBen Murdoch 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_shouldCollectPatternAttributes) { 89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch patternElement->updateAnimatedSVGAttribute(anyQName()); 90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_attributes = PatternAttributes(); 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch patternElement->collectPatternAttributes(m_attributes); 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_shouldCollectPatternAttributes = false; 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified, 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // then the given effect (e.g. a gradient or a filter) will be ignored. 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect objectBoundingBox = object->objectBoundingBox(); 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_attributes.boundingBoxMode() && objectBoundingBox.isEmpty()) 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 10121939df44de1705786c545cd1bf519d47250322dBen Murdoch 10221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!m_pattern.contains(object)) 10321939df44de1705786c545cd1bf519d47250322dBen Murdoch m_pattern.set(object, new PatternData); 10421939df44de1705786c545cd1bf519d47250322dBen Murdoch 10521939df44de1705786c545cd1bf519d47250322dBen Murdoch PatternData* patternData = m_pattern.get(object); 10621939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!patternData->pattern) { 107e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // If we couldn't determine the pattern content element root, stop here. 108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!m_attributes.patternContentElement()) 109e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block return false; 110e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 111e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Compute all necessary transformations to build the tile image & the pattern. 112e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block FloatRect tileBoundaries; 113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AffineTransform tileImageTransform; 114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!buildTileImageTransform(object, m_attributes, patternElement, tileBoundaries, tileImageTransform)) 115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 116e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 117e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block AffineTransform absoluteTransform; 118e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); 119e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 120e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block FloatRect absoluteTileBoundaries = absoluteTransform.mapRect(tileBoundaries); 121e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 122e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Build tile image. 123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch OwnPtr<ImageBuffer> tileImage = createTileImage(object, m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform); 12421939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!tileImage) 12521939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 12621939df44de1705786c545cd1bf519d47250322dBen Murdoch 127e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block RefPtr<Image> copiedImage = tileImage->copyImage(); 128e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (!copiedImage) 129e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block return false; 13021939df44de1705786c545cd1bf519d47250322dBen Murdoch 131e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Build pattern. 132e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block patternData->pattern = Pattern::create(copiedImage, true, true); 13321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!patternData->pattern) 13421939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 13521939df44de1705786c545cd1bf519d47250322dBen Murdoch 136e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Compute pattern space transformation. 137e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y()); 138e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block patternData->transform.scale(tileBoundaries.width() / absoluteTileBoundaries.width(), tileBoundaries.height() / absoluteTileBoundaries.height()); 139e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AffineTransform patternTransform = m_attributes.patternTransform(); 141e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (!patternTransform.isIdentity()) 142ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch patternData->transform = patternTransform * patternData->transform; 143e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 144545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch patternData->pattern->setPatternSpaceTransform(patternData->transform); 14521939df44de1705786c545cd1bf519d47250322dBen Murdoch } 14621939df44de1705786c545cd1bf519d47250322dBen Murdoch 14721939df44de1705786c545cd1bf519d47250322dBen Murdoch // Draw pattern 14821939df44de1705786c545cd1bf519d47250322dBen Murdoch context->save(); 14921939df44de1705786c545cd1bf519d47250322dBen Murdoch 15021939df44de1705786c545cd1bf519d47250322dBen Murdoch const SVGRenderStyle* svgStyle = style->svgStyle(); 15121939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(svgStyle); 15221939df44de1705786c545cd1bf519d47250322dBen Murdoch 15321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (resourceMode & ApplyToFillMode) { 15421939df44de1705786c545cd1bf519d47250322dBen Murdoch context->setAlpha(svgStyle->fillOpacity()); 15521939df44de1705786c545cd1bf519d47250322dBen Murdoch context->setFillPattern(patternData->pattern); 15621939df44de1705786c545cd1bf519d47250322dBen Murdoch context->setFillRule(svgStyle->fillRule()); 15721939df44de1705786c545cd1bf519d47250322dBen Murdoch } else if (resourceMode & ApplyToStrokeMode) { 158545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE) 159545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform)); 16021939df44de1705786c545cd1bf519d47250322dBen Murdoch context->setAlpha(svgStyle->strokeOpacity()); 16121939df44de1705786c545cd1bf519d47250322dBen Murdoch context->setStrokePattern(patternData->pattern); 162ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block SVGRenderSupport::applyStrokeStyleToContext(context, style, object); 16321939df44de1705786c545cd1bf519d47250322dBen Murdoch } 16421939df44de1705786c545cd1bf519d47250322dBen Murdoch 16521939df44de1705786c545cd1bf519d47250322dBen Murdoch if (resourceMode & ApplyToTextMode) { 16621939df44de1705786c545cd1bf519d47250322dBen Murdoch if (resourceMode & ApplyToFillMode) { 167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch context->setTextDrawingMode(TextModeFill); 16821939df44de1705786c545cd1bf519d47250322dBen Murdoch 1692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CG) 17021939df44de1705786c545cd1bf519d47250322dBen Murdoch context->applyFillPattern(); 17121939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 17221939df44de1705786c545cd1bf519d47250322dBen Murdoch } else if (resourceMode & ApplyToStrokeMode) { 173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch context->setTextDrawingMode(TextModeStroke); 17421939df44de1705786c545cd1bf519d47250322dBen Murdoch 1752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CG) 17621939df44de1705786c545cd1bf519d47250322dBen Murdoch context->applyStrokePattern(); 17721939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 17821939df44de1705786c545cd1bf519d47250322dBen Murdoch } 17921939df44de1705786c545cd1bf519d47250322dBen Murdoch } 18021939df44de1705786c545cd1bf519d47250322dBen Murdoch 18121939df44de1705786c545cd1bf519d47250322dBen Murdoch return true; 18221939df44de1705786c545cd1bf519d47250322dBen Murdoch} 18321939df44de1705786c545cd1bf519d47250322dBen Murdoch 184f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path) 18521939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 18621939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(context); 18721939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(resourceMode != ApplyToDefaultMode); 18821939df44de1705786c545cd1bf519d47250322dBen Murdoch 189f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (path && !(resourceMode & ApplyToTextMode)) { 19021939df44de1705786c545cd1bf519d47250322dBen Murdoch if (resourceMode & ApplyToFillMode) 191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch context->fillPath(*path); 19221939df44de1705786c545cd1bf519d47250322dBen Murdoch else if (resourceMode & ApplyToStrokeMode) 193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch context->strokePath(*path); 19421939df44de1705786c545cd1bf519d47250322dBen Murdoch } 19521939df44de1705786c545cd1bf519d47250322dBen Murdoch 19621939df44de1705786c545cd1bf519d47250322dBen Murdoch context->restore(); 19721939df44de1705786c545cd1bf519d47250322dBen Murdoch} 19821939df44de1705786c545cd1bf519d47250322dBen Murdoch 199e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic inline FloatRect calculatePatternBoundaries(const PatternAttributes& attributes, 20021939df44de1705786c545cd1bf519d47250322dBen Murdoch const FloatRect& objectBoundingBox, 20121939df44de1705786c545cd1bf519d47250322dBen Murdoch const SVGPatternElement* patternElement) 20221939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 203e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block ASSERT(patternElement); 204e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 20521939df44de1705786c545cd1bf519d47250322dBen Murdoch if (attributes.boundingBoxMode()) 206e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block return FloatRect(attributes.x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(), 207e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block attributes.y().valueAsPercentage() * objectBoundingBox.height() + objectBoundingBox.y(), 20821939df44de1705786c545cd1bf519d47250322dBen Murdoch attributes.width().valueAsPercentage() * objectBoundingBox.width(), 20921939df44de1705786c545cd1bf519d47250322dBen Murdoch attributes.height().valueAsPercentage() * objectBoundingBox.height()); 21021939df44de1705786c545cd1bf519d47250322dBen Murdoch 21121939df44de1705786c545cd1bf519d47250322dBen Murdoch return FloatRect(attributes.x().value(patternElement), 21221939df44de1705786c545cd1bf519d47250322dBen Murdoch attributes.y().value(patternElement), 21321939df44de1705786c545cd1bf519d47250322dBen Murdoch attributes.width().value(patternElement), 21421939df44de1705786c545cd1bf519d47250322dBen Murdoch attributes.height().value(patternElement)); 21521939df44de1705786c545cd1bf519d47250322dBen Murdoch} 21621939df44de1705786c545cd1bf519d47250322dBen Murdoch 217a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer, 218a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const PatternAttributes& attributes, 219a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const SVGPatternElement* patternElement, 220a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect& patternBoundaries, 221a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AffineTransform& tileImageTransform) const 22221939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 223e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block ASSERT(renderer); 224e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block ASSERT(patternElement); 22521939df44de1705786c545cd1bf519d47250322dBen Murdoch 226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect objectBoundingBox = renderer->objectBoundingBox(); 227e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); 228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (patternBoundaries.width() <= 0 || patternBoundaries.height() <= 0) 229a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 23021939df44de1705786c545cd1bf519d47250322dBen Murdoch 231ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch AffineTransform viewBoxCTM = patternElement->viewBoxToViewTransform(attributes.viewBox(), attributes.preserveAspectRatio(), patternBoundaries.width(), patternBoundaries.height()); 23221939df44de1705786c545cd1bf519d47250322dBen Murdoch 233e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Apply viewBox/objectBoundingBox transformations. 23421939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!viewBoxCTM.isIdentity()) 235e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block tileImageTransform = viewBoxCTM; 23681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch else if (attributes.boundingBoxModeContent()) 237e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block tileImageTransform.scale(objectBoundingBox.width(), objectBoundingBox.height()); 238ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return true; 240ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block} 241ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 242e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockPassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(RenderObject* object, 243e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block const PatternAttributes& attributes, 244e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block const FloatRect& tileBoundaries, 245e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block const FloatRect& absoluteTileBoundaries, 246e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block const AffineTransform& tileImageTransform) const 24721939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 248e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block ASSERT(object); 24921939df44de1705786c545cd1bf519d47250322dBen Murdoch 250e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Clamp tile image size against SVG viewport size, as last resort, to avoid allocating huge image buffers. 251e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block FloatRect contentBoxRect = SVGRenderSupport::findTreeRootObject(object)->contentBoxRect(); 25221939df44de1705786c545cd1bf519d47250322dBen Murdoch 253e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block FloatRect clampedAbsoluteTileBoundaries = absoluteTileBoundaries; 254e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (clampedAbsoluteTileBoundaries.width() > contentBoxRect.width()) 255e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block clampedAbsoluteTileBoundaries.setWidth(contentBoxRect.width()); 25621939df44de1705786c545cd1bf519d47250322dBen Murdoch 257e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (clampedAbsoluteTileBoundaries.height() > contentBoxRect.height()) 258e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block clampedAbsoluteTileBoundaries.setHeight(contentBoxRect.height()); 25921939df44de1705786c545cd1bf519d47250322dBen Murdoch 260e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block OwnPtr<ImageBuffer> tileImage; 26121939df44de1705786c545cd1bf519d47250322dBen Murdoch 262a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!SVGImageBufferTools::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB)) 263e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block return PassOwnPtr<ImageBuffer>(); 26421939df44de1705786c545cd1bf519d47250322dBen Murdoch 265e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block GraphicsContext* tileImageContext = tileImage->context(); 266e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block ASSERT(tileImageContext); 26721939df44de1705786c545cd1bf519d47250322dBen Murdoch 268e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation). 269e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block tileImageContext->scale(FloatSize(absoluteTileBoundaries.width() / tileBoundaries.width(), 270e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block absoluteTileBoundaries.height() / tileBoundaries.height())); 27121939df44de1705786c545cd1bf519d47250322dBen Murdoch 272e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Apply tile image transformations. 273e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (!tileImageTransform.isIdentity()) 274e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block tileImageContext->concatCTM(tileImageTransform); 27521939df44de1705786c545cd1bf519d47250322dBen Murdoch 276e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block AffineTransform contentTransformation; 27781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (attributes.boundingBoxModeContent()) 27881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch contentTransformation = tileImageTransform; 27921939df44de1705786c545cd1bf519d47250322dBen Murdoch 280e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Draw the content into the ImageBuffer. 28121939df44de1705786c545cd1bf519d47250322dBen Murdoch for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { 28221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer()) 28321939df44de1705786c545cd1bf519d47250322dBen Murdoch continue; 284e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block SVGImageBufferTools::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation); 28521939df44de1705786c545cd1bf519d47250322dBen Murdoch } 28621939df44de1705786c545cd1bf519d47250322dBen Murdoch 28721939df44de1705786c545cd1bf519d47250322dBen Murdoch return tileImage.release(); 28821939df44de1705786c545cd1bf519d47250322dBen Murdoch} 28921939df44de1705786c545cd1bf519d47250322dBen Murdoch 29021939df44de1705786c545cd1bf519d47250322dBen Murdoch} 29121939df44de1705786c545cd1bf519d47250322dBen Murdoch 29221939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 293