1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block/* 2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 368513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 468513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 568513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) Research In Motion Limited 2010. All rights reserved. 7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is free software; you can redistribute it and/or 9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * modify it under the terms of the GNU Library General Public 10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * License as published by the Free Software Foundation; either 11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * version 2 of the License, or (at your option) any later version. 12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is distributed in the hope that it will be useful, 14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * but WITHOUT ANY WARRANTY; without even the implied warranty of 15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Library General Public License for more details. 17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * You should have received a copy of the GNU Library General Public License 19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * along with this library; see the file COPYING.LIB. If not, write to 20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Boston, MA 02110-1301, USA. 22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block */ 23dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 24dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "config.h" 25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(SVG) && ENABLE(FILTERS) 27dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderSVGResourceFilter.h" 28dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "AffineTransform.h" 3054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block#include "FilterEffect.h" 31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FloatPoint.h" 32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FloatRect.h" 33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GraphicsContext.h" 34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Image.h" 35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ImageBuffer.h" 36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ImageData.h" 37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "IntRect.h" 38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderSVGResource.h" 39e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "RenderSVGResourceFilterPrimitive.h" 40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGElement.h" 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGFilter.h" 42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGFilterElement.h" 43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGFilterPrimitiveStandardAttributes.h" 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGImageBufferTools.h" 45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGNames.h" 46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGStyledElement.h" 47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGUnitTypes.h" 4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 4921939df44de1705786c545cd1bf519d47250322dBen Murdoch#include <wtf/UnusedParam.h> 5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <wtf/Vector.h> 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockusing namespace std; 53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore { 55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType; 57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 5821939df44de1705786c545cd1bf519d47250322dBen MurdochRenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node) 5921939df44de1705786c545cd1bf519d47250322dBen Murdoch : RenderSVGResourceContainer(node) 60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderSVGResourceFilter::~RenderSVGResourceFilter() 64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 65db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (m_filter.isEmpty()) 66db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block return; 67db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block 68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block deleteAllValues(m_filter); 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_filter.clear(); 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 72f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation) 73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 74db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (!m_filter.isEmpty()) { 75db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block deleteAllValues(m_filter); 76db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block m_filter.clear(); 77db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block } 78967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 79f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); 80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 82f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool markForInvalidation) 83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 84db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block ASSERT(client); 85db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block 8654cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block if (FilterData* filterData = m_filter.get(client)) { 8754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block if (filterData->savedContext) 8854cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block filterData->markedForRemoval = true; 8954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block else 9054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block delete m_filter.take(client); 9154cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block } 92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 93f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 964576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangPassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(Filter* filter) 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); 99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; 100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Add effects to the builder 1024576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(filter); 103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) { 104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!node->isSVGElement()) 105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block continue; 106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGElement* element = static_cast<SVGElement*>(node); 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!element->isFilterEffect()) 109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block continue; 110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); 1124576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); 113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!effect) { 114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block builder->clearEffects(); 115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return 0; 116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block builder->appendEffectToEffectReferences(effect, effectElement->renderer()); 118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block effectElement->setStandardAttributes(primitiveBoundingBoxMode, effect.get()); 119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block builder->add(effectElement->result(), effect); 120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return builder.release(); 122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale) 125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool matchesFilterSize = true; 127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (size.width() > kMaxFilterSize) { 128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scale.setWidth(scale.width() * kMaxFilterSize / size.width()); 129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block matchesFilterSize = false; 130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (size.height() > kMaxFilterSize) { 132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scale.setHeight(scale.height() * kMaxFilterSize / size.height()); 133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block matchesFilterSize = false; 134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return matchesFilterSize; 137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 13921939df44de1705786c545cd1bf519d47250322dBen Murdochbool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) 140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(object); 142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(context); 14321939df44de1705786c545cd1bf519d47250322dBen Murdoch#ifndef NDEBUG 14421939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(resourceMode == ApplyToDefaultMode); 14521939df44de1705786c545cd1bf519d47250322dBen Murdoch#else 14621939df44de1705786c545cd1bf519d47250322dBen Murdoch UNUSED_PARAM(resourceMode); 14721939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Returning false here, to avoid drawings onto the context. We just want to 150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // draw the stored filter output, not the unfiltered object as well. 151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_filter.contains(object)) { 152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block FilterData* filterData = m_filter.get(object); 153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (filterData->builded) 154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return false; 155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block delete m_filter.take(object); // Oops, have to rebuild, go through normal code path 157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block OwnPtr<FilterData> filterData(new FilterData); 160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect targetBoundingBox = object->objectBoundingBox(); 161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); 163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch filterData->boundaries = filterElement->filterBoundingBox(targetBoundingBox); 164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (filterData->boundaries.isEmpty()) 165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Determine absolute transformation matrix for filter. 168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AffineTransform absoluteTransform; 169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); 170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!absoluteTransform.isInvertible()) 171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile. 174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), absoluteTransform.e(), absoluteTransform.f()); 175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Determine absolute boundaries of the filter and the drawing region. 177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries); 178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect drawingRegion = object->strokeBoundingBox(); 179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch drawingRegion.intersect(filterData->boundaries); 180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion); 181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Create the SVGFilter object. 183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; 184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode); 185a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Create all relevant filter primitives. 1874576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang filterData->builder = buildPrimitives(filterData->filter.get()); 188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!filterData->builder) 189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return false; 190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Calculate the scale factor for the use of filterRes. 192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion 193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatSize scale(1, 1); 194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (filterElement->hasAttribute(SVGNames::filterResAttr)) { 195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width()); 196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height()); 197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (scale.isEmpty()) 200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return false; 201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 202a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize. 203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect tempSourceRect = absoluteDrawingRegion; 204dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block tempSourceRect.scale(scale.width(), scale.height()); 205dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block fitsInMaximumImageSize(tempSourceRect.size(), scale); 206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Set the scale level in SVGFilter. 208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block filterData->filter->setFilterResolution(scale); 209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block FilterEffect* lastEffect = filterData->builder->lastEffect(); 211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!lastEffect) 212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return false; 213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 2142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect); 215e14391e94c850b8bd03680c23b38978db68687a8John Reck FloatRect subRegion = lastEffect->maxEffectRect(); 216e14391e94c850b8bd03680c23b38978db68687a8John Reck // At least one FilterEffect has a too big image size, 217e14391e94c850b8bd03680c23b38978db68687a8John Reck // recalculate the effect sizes with new scale factors. 218e14391e94c850b8bd03680c23b38978db68687a8John Reck if (!fitsInMaximumImageSize(subRegion.size(), scale)) { 219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block filterData->filter->setFilterResolution(scale); 2202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect); 221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // If the drawingRegion is empty, we have something like <g filter=".."/>. 224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource. 225a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (drawingRegion.isEmpty()) { 226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(!m_filter.contains(object)); 227a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch filterData->savedContext = context; 228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_filter.set(object, filterData.leakPtr()); 229dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return false; 230a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 232a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch absoluteDrawingRegion.scale(scale.width(), scale.height()); 233a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 234a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch OwnPtr<ImageBuffer> sourceGraphic; 2354576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, ColorSpaceLinearRGB)) { 2364576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang ASSERT(!m_filter.contains(object)); 2374576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang filterData->savedContext = context; 2384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang m_filter.set(object, filterData.leakPtr()); 239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 2404576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang } 241a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 242dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block GraphicsContext* sourceGraphicContext = sourceGraphic->context(); 243a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(sourceGraphicContext); 244a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 245a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch sourceGraphicContext->translate(-absoluteDrawingRegion.x(), -absoluteDrawingRegion.y()); 246a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (scale.width() != 1 || scale.height() != 1) 247a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch sourceGraphicContext->scale(scale); 248a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 249a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch sourceGraphicContext->concatCTM(filterData->shearFreeAbsoluteTransform); 250a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch sourceGraphicContext->clearRect(FloatRect(FloatPoint(), absoluteDrawingRegion.size())); 251e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke filterData->sourceGraphicBuffer = sourceGraphic.release(); 2525af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke filterData->savedContext = context; 253dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 254dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block context = sourceGraphicContext; 255e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 256e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke ASSERT(!m_filter.contains(object)); 257e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke m_filter.set(object, filterData.leakPtr()); 258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return true; 260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*) 263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(object); 265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(context); 26621939df44de1705786c545cd1bf519d47250322dBen Murdoch#ifndef NDEBUG 26721939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(resourceMode == ApplyToDefaultMode); 26821939df44de1705786c545cd1bf519d47250322dBen Murdoch#else 26921939df44de1705786c545cd1bf519d47250322dBen Murdoch UNUSED_PARAM(resourceMode); 27021939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 27254cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block FilterData* filterData = m_filter.get(object); 27354cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block if (!filterData) 274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 27654cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block if (filterData->markedForRemoval) { 27754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block delete m_filter.take(object); 27854cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block return; 27954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block } 28054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block 281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!filterData->builded) { 2825af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke if (!filterData->savedContext) { 283f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick removeClientFromCache(object); 284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 2875af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke context = filterData->savedContext; 2885af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke filterData->savedContext = 0; 2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if !USE(CG) 290a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (filterData->sourceGraphicBuffer) 291a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch filterData->sourceGraphicBuffer->transformColorSpace(ColorSpaceDeviceRGB, ColorSpaceLinearRGB); 292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif 293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block FilterEffect* lastEffect = filterData->builder->lastEffect(); 296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 29768513a70bcd92384395513322f1b801e7bf9c729Steve Block if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) { 298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // This is the real filtering of the object. It just needs to be called on the 299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // initial filtering process. We just take the stored filter result on a 300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // second drawing. 3012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!filterData->builded) 3025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release()); 3032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Always true if filterData is just built (filterData->builded is false). 3052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!lastEffect->hasResult()) { 3064576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang lastEffect->apply(); 3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if !USE(CG) 308f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ImageBuffer* resultImage = lastEffect->asImageBuffer(); 3095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen if (resultImage) 310a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch resultImage->transformColorSpace(ColorSpaceLinearRGB, ColorSpaceDeviceRGB); 3115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#endif 312dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 3132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block filterData->builded = true; 314dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 315f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ImageBuffer* resultImage = lastEffect->asImageBuffer(); 316a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (resultImage) { 317a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse()); 318dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 319a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height())); 320a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch context->clip(lastEffect->maxEffectRect()); 321a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect()); 322a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch context->scale(filterData->filter->filterResolution()); 323a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 324a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch context->concatCTM(filterData->shearFreeAbsoluteTransform); 325a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 326a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 3275af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke filterData->sourceGraphicBuffer.clear(); 328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 329dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 330545e470e52f0ac6a3a072bf559c796b42c6066b6Ben MurdochFloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object) 331dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node())) 333545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return element->filterBoundingBox(object->objectBoundingBox()); 334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return FloatRect(); 336dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 337dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 3382fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, const QualifiedName& attribute) 3392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 3402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block HashMap<RenderObject*, FilterData*>::iterator it = m_filter.begin(); 3412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block HashMap<RenderObject*, FilterData*>::iterator end = m_filter.end(); 3422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node()); 3432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for (; it != end; ++it) { 3452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block FilterData* filterData = it->second; 3462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!filterData->builded) 3472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue; 3482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block SVGFilterBuilder* builder = filterData->builder.get(); 3502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block FilterEffect* effect = builder->effectByRenderer(object); 3512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!effect) 3522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue; 3532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Since all effects shares the same attribute value, all 3542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // or none of them will be changed. 3552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!primitve->setFilterEffectAttribute(effect, attribute)) 3562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return; 3572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block builder->clearResultsRecursive(effect); 3582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Repaint the image on the screen. 3602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block markClientForInvalidation(it->first, RepaintInvalidation); 3612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 3622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 3632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif 366