15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved. 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGGradientElement.h" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XLinkNames.h" 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Attribute.h" 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGPath.h" 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResourceLinearGradient.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResourceRadialGradient.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGStopElement.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGTransformList.h" 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)template<> const SVGEnumerationStringEntries& getStaticStringEntries<SVGSpreadMethodType>() 37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 38d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) DEFINE_STATIC_LOCAL(SVGEnumerationStringEntries, entries, ()); 39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (entries.isEmpty()) { 40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) entries.append(std::make_pair(SVGSpreadMethodPad, "pad")); 41d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) entries.append(std::make_pair(SVGSpreadMethodReflect, "reflect")); 42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) entries.append(std::make_pair(SVGSpreadMethodRepeat, "repeat")); 43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return entries; 45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 4602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 478abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)SVGGradientElement::SVGGradientElement(const QualifiedName& tagName, Document& document) 48f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) : SVGElement(tagName, document) 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , SVGURIReference(this) 50d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_gradientTransform(SVGAnimatedTransformList::create(this, SVGNames::gradientTransformAttr, SVGTransformList::create())) 51d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_spreadMethod(SVGAnimatedEnumeration<SVGSpreadMethodType>::create(this, SVGNames::spreadMethodAttr, SVGSpreadMethodPad)) 52d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_gradientUnits(SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>::create(this, SVGNames::gradientUnitsAttr, SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 54d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) addToPropertyMap(m_gradientTransform); 55d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) addToPropertyMap(m_spreadMethod); 56d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) addToPropertyMap(m_gradientUnits); 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGGradientElement::isSupportedAttribute(const QualifiedName& attrName) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (supportedAttributes.isEmpty()) { 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SVGURIReference::addSupportedAttributes(supportedAttributes); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) supportedAttributes.add(SVGNames::gradientUnitsAttr); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) supportedAttributes.add(SVGNames::gradientTransformAttr); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) supportedAttributes.add(SVGNames::spreadMethodAttr); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 68591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGGradientElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!isSupportedAttribute(name)) { 74f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) SVGElement::parseAttribute(name, value); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) SVGParsingError parseError = NoError; 7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (name == SVGNames::gradientTransformAttr) 81d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_gradientTransform->setBaseValueAsString(value, parseError); 82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) else if (name == SVGNames::gradientUnitsAttr) 83d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_gradientUnits->setBaseValueAsString(value, parseError); 84d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) else if (name == SVGNames::spreadMethodAttr) 85d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_spreadMethod->setBaseValueAsString(value, parseError); 86d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) else if (SVGURIReference::parseAttribute(name, value, parseError)) { 87d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT_NOT_REACHED(); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) reportAttributeParsingError(parseError, name, value); 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGGradientElement::svgAttributeChanged(const QualifiedName& attrName) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isSupportedAttribute(attrName)) { 96f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) SVGElement::svgAttributeChanged(attrName); 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 100323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) SVGElement::InvalidationGuard invalidationGuard(this); 10102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 102f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer()); 103f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (renderer) 104f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) renderer->invalidateCacheAndMarkForLayout(); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 10602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGGradientElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 109f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (changedByParser) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (RenderObject* object = renderer()) 1155d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) object->setNeedsLayoutAndFullPaintInvalidation(); 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Vector<Gradient::ColorStop> SVGGradientElement::buildStops() 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<Gradient::ColorStop> stops; 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float previousOffset = 0.0f; 123d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for (SVGStopElement* stop = Traversal<SVGStopElement>::firstChild(*this); stop; stop = Traversal<SVGStopElement>::nextSibling(*stop)) { 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Figure out right monotonic offset 12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) float offset = stop->offset()->currentValue()->value(); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) offset = std::min(std::max(previousOffset, offset), 1.0f); 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) previousOffset = offset; 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) stops.append(Gradient::ColorStop(offset, stop->stopColorIncludingOpacity())); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return stops; 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 136