15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved. 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResourceGradient.h" 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGShape.h" 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderSupport.h" 29a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : RenderSVGResourceContainer(node) 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_shouldCollectGradientAttributes(true) 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidation) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_gradientMap.clear(); 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldCollectGradientAttributes = true; 43e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) markAllClientsForInvalidation(markForInvalidation ? PaintInvalidation : ParentOnlyInvalidation); 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool markForInvalidation) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(client); 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_gradientMap.remove(client); 50e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) markClientForInvalidation(client, markForInvalidation ? PaintInvalidation : ParentOnlyInvalidation); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(object); 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(style); 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(context); 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(resourceMode != ApplyToDefaultMode); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) clearInvalidationMask(); 6151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further. 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash. 668abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) SVGGradientElement* gradientElement = toSVGGradientElement(element()); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!gradientElement) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_shouldCollectGradientAttributes) { 71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) gradientElement->synchronizeAnimatedSVGAttribute(anyQName()); 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!collectGradientAttributes(gradientElement)) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldCollectGradientAttributes = false; 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified, 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // then the given effect (e.g. a gradient or a filter) will be ignored. 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect objectBoundingBox = object->objectBoundingBox(); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty()) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).storedValue->value; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!gradientData) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradientData = adoptPtr(new GradientData); 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Create gradient object 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!gradientData->gradient) { 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buildGradient(gradientData.get()); 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // We want the text bounding box applied to the gradient space transform now, so the gradient shader can use it. 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty()) { 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradientData->userspaceTransform.translate(objectBoundingBox.x(), objectBoundingBox.y()); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AffineTransform gradientTransform; 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) calculateGradientTransform(gradientTransform); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradientData->userspaceTransform *= gradientTransform; 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!gradientData->gradient) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 107197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch const SVGRenderStyle& svgStyle = style->svgStyle(); 1086f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch 1096f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch AffineTransform computedGradientSpaceTransform = computeResourceSpaceTransform(object, gradientData->userspaceTransform, svgStyle, resourceMode); 1106f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch gradientData->gradient->setGradientSpaceTransform(computedGradientSpaceTransform); 1116f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Draw gradient 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->save(); 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1156f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (resourceMode & ApplyToTextMode) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFill : TextModeStroke); 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (resourceMode & ApplyToFillMode) { 119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch context->setAlphaAsFloat(svgStyle.fillOpacity()); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->setFillGradient(gradientData->gradient); 121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch context->setFillRule(svgStyle.fillRule()); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (resourceMode & ApplyToStrokeMode) { 123197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch context->setAlphaAsFloat(svgStyle.strokeOpacity()); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->setStrokeGradient(gradientData->gradient); 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SVGRenderSupport::applyStrokeStyleToContext(context, style, object); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid RenderSVGResourceGradient::postApplyResource(RenderObject*, GraphicsContext*& context) 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(context); 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->restore(); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vector<Gradient::ColorStop>& stops) const 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(gradientData->gradient); 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const Vector<Gradient::ColorStop>::const_iterator end = stops.end(); 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (Vector<Gradient::ColorStop>::const_iterator it = stops.begin(); it != end; ++it) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradientData->gradient->addColorStop(*it); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType(SVGSpreadMethodType method) const 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (method) { 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SVGSpreadMethodUnknown: 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SVGSpreadMethodPad: 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return SpreadMethodPad; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SVGSpreadMethodReflect: 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return SpreadMethodReflect; 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SVGSpreadMethodRepeat: 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return SpreadMethodRepeat; 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return SpreadMethodPad; 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 163