2 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
4 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
5 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #include "core/rendering/svg/RenderSVGResourceGradient.h"
28 RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node)
29 : RenderSVGResourcePaintServer(node)
30 , m_shouldCollectGradientAttributes(true)
34 void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidation)
36 m_gradientMap.clear();
37 m_shouldCollectGradientAttributes = true;
38 markAllClientsForInvalidation(markForInvalidation ? PaintInvalidation : ParentOnlyInvalidation);
41 void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool markForInvalidation)
44 m_gradientMap.remove(client);
45 markClientForInvalidation(client, markForInvalidation ? PaintInvalidation : ParentOnlyInvalidation);
48 SVGPaintServer RenderSVGResourceGradient::preparePaintServer(const RenderObject& object)
50 clearInvalidationMask();
52 // Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further.
53 // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property
54 // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our
55 // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash.
56 SVGGradientElement* gradientElement = toSVGGradientElement(element());
58 return SVGPaintServer::invalid();
60 if (m_shouldCollectGradientAttributes) {
61 gradientElement->synchronizeAnimatedSVGAttribute(anyQName());
62 if (!collectGradientAttributes(gradientElement))
63 return SVGPaintServer::invalid();
65 m_shouldCollectGradientAttributes = false;
68 // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
69 // then the given effect (e.g. a gradient or a filter) will be ignored.
70 FloatRect objectBoundingBox = object.objectBoundingBox();
71 if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
72 return SVGPaintServer::invalid();
74 OwnPtr<GradientData>& gradientData = m_gradientMap.add(&object, nullptr).storedValue->value;
76 gradientData = adoptPtr(new GradientData);
78 // Create gradient object
79 if (!gradientData->gradient) {
80 buildGradient(gradientData.get());
82 // We want the text bounding box applied to the gradient space transform now, so the gradient shader can use it.
83 if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty()) {
84 gradientData->userspaceTransform.translate(objectBoundingBox.x(), objectBoundingBox.y());
85 gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
88 AffineTransform gradientTransform;
89 calculateGradientTransform(gradientTransform);
91 gradientData->userspaceTransform *= gradientTransform;
94 if (!gradientData->gradient)
95 return SVGPaintServer::invalid();
97 gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
99 return SVGPaintServer(gradientData->gradient);
102 bool RenderSVGResourceGradient::isChildAllowed(RenderObject* child, RenderStyle*) const
104 if (child->isSVGGradientStop())
107 if (!child->isSVGResourceContainer())
110 return toRenderSVGResourceContainer(child)->isSVGPaintServer();
113 void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vector<Gradient::ColorStop>& stops) const
115 ASSERT(gradientData->gradient);
117 const Vector<Gradient::ColorStop>::const_iterator end = stops.end();
118 for (Vector<Gradient::ColorStop>::const_iterator it = stops.begin(); it != end; ++it)
119 gradientData->gradient->addColorStop(*it);
122 GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType(SVGSpreadMethodType method) const
125 case SVGSpreadMethodUnknown:
126 case SVGSpreadMethodPad:
127 return SpreadMethodPad;
128 case SVGSpreadMethodReflect:
129 return SpreadMethodReflect;
130 case SVGSpreadMethodRepeat:
131 return SpreadMethodRepeat;
134 ASSERT_NOT_REACHED();
135 return SpreadMethodPad;