15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResourceFilter.h" 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 28197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/ElementTraversal.h" 2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/frame/Settings.h" 30e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "core/rendering/svg/RenderSVGResourceFilterPrimitive.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderingContext.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGFilterPrimitiveStandardAttributes.h" 33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/UnacceleratedImageBufferSurface.h" 3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h" 35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SourceAlpha.h" 36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SourceGraphic.h" 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)const RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType; 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : RenderSVGResourceContainer(node) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGResourceFilter::~RenderSVGResourceFilter() 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 49e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} 50e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 51e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void RenderSVGResourceFilter::destroy() 52e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){ 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_filter.clear(); 54e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) RenderSVGResourceContainer::destroy(); 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool RenderSVGResourceFilter::isChildAllowed(RenderObject* child, RenderStyle*) const 5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return child->isSVGResourceFilterPrimitive(); 6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) m_filter.clear(); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool markForInvalidation) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(client); 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_filter.remove(client); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 798abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) SVGFilterElement* filterElement = toSVGFilterElement(element()); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect targetBoundingBox = filter->targetBoundingBox(); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Add effects to the builder 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(SourceGraphic::create(filter), SourceAlpha::create(filter)); 84d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for (SVGElement* element = Traversal<SVGElement>::firstChild(*filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) { 855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!element->isFilterEffect() || !element->renderer()) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!effect) { 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder->clearEffects(); 92d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return nullptr; 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder->appendEffectToEffectReferences(effect, effectElement->renderer()); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) effectElement->setStandardAttributes(effect.get()); 96d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->currentValue()->enumValue(), targetBoundingBox)); 97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) effect->setOperatingColorSpace( 98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch effectElement->renderer()->style()->svgStyle().colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); 9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return builder.release(); 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void beginDeferredFilter(GraphicsContext* context, FilterData* filterData) 105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) context->beginRecording(filterData->boundaries); 107697ef0c10ac944be8499480c025020e4c282c980Ben Murdoch context->setShouldSmoothFonts(false); 108c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // We pass the boundaries to SkPictureImageFilter so it knows the 109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // world-space position of the filter primitives. It gets them 110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // from the DisplayList, which also applies the inverse translate 111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // to the origin. So we apply the forward translate here to avoid 112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // it being applied twice. 113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // FIXME: we should fix SkPicture to handle this offset itself, or 114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // make the translate optional on SkPictureImageFilter. 115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // See https://code.google.com/p/skia/issues/detail?id=2801 116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) context->translate(filterData->boundaries.x(), filterData->boundaries.y()); 117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 119c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void endDeferredFilter(GraphicsContext* context, FilterData* filterData) 120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // FIXME: maybe filterData should just hold onto SourceGraphic after creation? 122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SourceGraphic* sourceGraphic = static_cast<SourceGraphic*>(filterData->builder->getEffectById(SourceGraphic::effectName())); 123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(sourceGraphic); 124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) sourceGraphic->setDisplayList(context->endRecording()); 125c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void drawDeferredFilter(GraphicsContext* context, FilterData* filterData, SVGFilterElement* filterElement) 128f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{ 129f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu SkiaImageFilterBuilder builder(context); 130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SourceGraphic* sourceGraphic = static_cast<SourceGraphic*>(filterData->builder->getEffectById(SourceGraphic::effectName())); 131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(sourceGraphic); 132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) builder.setSourceGraphic(sourceGraphic); 133f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu RefPtr<ImageFilter> imageFilter = builder.build(filterData->builder->lastEffect(), ColorSpaceDeviceRGB); 1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci FloatRect boundaries = filterData->boundaries; 135f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu context->save(); 136c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) FloatSize deviceSize = context->getCTM().mapSize(boundaries.size()); 138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) float scaledArea = deviceSize.width() * deviceSize.height(); 13976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) 14076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // If area of scaled size is bigger than the upper limit, adjust the scale 141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // to fit. Note that this only really matters in the non-impl-side painting 142c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // case, since the impl-side case never allocates a full-sized backing 143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // store, only tile-sized. 144c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // FIXME: remove this once all platforms are using impl-side painting. 145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // crbug.com/169282. 14676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (scaledArea > FilterEffect::maxFilterArea()) { 14776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) float scale = sqrtf(FilterEffect::maxFilterArea() / scaledArea); 14876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) context->scale(scale, scale); 14976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 1507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Clip drawing of filtered image to the minimum required paint rect. 1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci FilterEffect* lastEffect = filterData->builder->lastEffect(); 1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci context->clipRect(lastEffect->determineAbsolutePaintRect(lastEffect->maxEffectRect())); 153f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (filterElement->hasAttribute(SVGNames::filterResAttr)) { 154f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Get boundaries in device coords. 1555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // FIXME: See crbug.com/382491. Is the use of getCTM OK here, given it does not include device 1565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // zoom or High DPI adjustments? 157f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu FloatSize size = context->getCTM().mapSize(boundaries.size()); 158f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Compute the scale amount required so that the resulting offscreen is exactly filterResX by filterResY pixels. 1595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) float filterResScaleX = filterElement->filterResX()->currentValue()->value() / size.width(); 1605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) float filterResScaleY = filterElement->filterResY()->currentValue()->value() / size.height(); 161f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Scale the CTM so the primitive is drawn to filterRes. 1625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) context->scale(filterResScaleX, filterResScaleY); 163f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Create a resize filter with the inverse scale. 164f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu AffineTransform resizeMatrix; 1655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) resizeMatrix.scale(1 / filterResScaleX, 1 / filterResScaleY); 166f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu imageFilter = builder.buildTransform(resizeMatrix, imageFilter.get()); 167f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 168f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // If the CTM contains rotation or shearing, apply the filter to 169f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // the unsheared/unrotated matrix, and do the shearing/rotation 170f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // as a final pass. 171f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu AffineTransform ctm = context->getCTM(); 172f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (ctm.b() || ctm.c()) { 173f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu AffineTransform scaleAndTranslate; 174f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu scaleAndTranslate.translate(ctm.e(), ctm.f()); 175f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu scaleAndTranslate.scale(ctm.xScale(), ctm.yScale()); 176f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ASSERT(scaleAndTranslate.isInvertible()); 177f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu AffineTransform shearAndRotate = scaleAndTranslate.inverse(); 178f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu shearAndRotate.multiply(ctm); 179f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu context->setCTM(scaleAndTranslate); 180f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get()); 181f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 182f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get()); 183f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu context->endLayer(); 184f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu context->restore(); 185f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 186f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(object); 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(context); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) clearInvalidationMask(); 19451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 195f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_filter.contains(object)) { 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterData* filterData = m_filter.get(object); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying) 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) filterData->state = FilterData::CycleDetected; 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now. 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<FilterData> filterData(adoptPtr(new FilterData)); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect targetBoundingBox = object->objectBoundingBox(); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2058abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) SVGFilterElement* filterElement = toSVGFilterElement(element()); 206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox); 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (filterData->boundaries.isEmpty()) 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) filterData->drawingRegion = object->strokeBoundingBox(); 211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) filterData->drawingRegion.intersect(filterData->boundaries); 2127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci IntRect intDrawingRegion = enclosingIntRect(filterData->drawingRegion); 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Create the SVGFilter object. 215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; 2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci filterData->filter = SVGFilter::create(intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode); 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Create all relevant filter primitives. 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) filterData->builder = buildPrimitives(filterData->filter.get()); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!filterData->builder) 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterEffect* lastEffect = filterData->builder->lastEffect(); 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!lastEffect) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 227a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion); 22809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci FilterData* data = filterData.get(); 2301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) m_filter.set(object, filterData.release()); 2317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci beginDeferredFilter(context, data); 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(object); 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(context); 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterData* filterData = m_filter.get(object); 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!filterData) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (filterData->state) { 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FilterData::CycleDetected: 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FilterData::Applying: 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We have a cycle if we are already applying the data. 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This can occur due to FeImage referencing a source that makes use of the FEImage itself. 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // will continue correctly. 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) filterData->state = FilterData::PaintingSource; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FilterData::PaintingSource: 2557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci endDeferredFilter(context, filterData); 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FilterData::Built: { } // Empty 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci drawDeferredFilter(context, filterData, toSVGFilterElement(element())); 2627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci filterData->state = FilterData::Built; 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject* object) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2678abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (SVGFilterElement* element = toSVGFilterElement(this->element())) 268d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnits()->currentValue()->enumValue(), object->objectBoundingBox()); 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return FloatRect(); 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, const QualifiedName& attribute) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) FilterMap::iterator it = m_filter.begin(); 2761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) FilterMap::iterator end = m_filter.end(); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node()); 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (; it != end; ++it) { 2801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) FilterData* filterData = it->value.get(); 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (filterData->state != FilterData::Built) 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SVGFilterBuilder* builder = filterData->builder.get(); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterEffect* effect = builder->effectByRenderer(object); 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!effect) 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Since all effects shares the same attribute value, all 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // or none of them will be changed. 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!primitve->setFilterEffectAttribute(effect, attribute)) 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder->clearResultsRecursive(effect); 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 294e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // Issue paint invalidations for the image on the screen. 295e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) markClientForInvalidation(it->key, PaintInvalidation); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markAllClientLayersForInvalidation(); 298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const 301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) FilterData* filterData = m_filter.get(object); 303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return filterData ? filterData->drawingRegion : FloatRect(); 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 307