File indexing completed on 2024-04-28 15:24:34
0001 /* 0002 Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> 0003 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 0004 0005 This file is part of the KDE project 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "wtf/Platform.h" 0024 0025 #if ENABLE(SVG) 0026 #include "SVGGradientElement.h" 0027 0028 #include "css/cssstyleselector.h" 0029 #include "RenderPath.h" 0030 #include "RenderSVGHiddenContainer.h" 0031 #include "SVGNames.h" 0032 #include "SVGPaintServerLinearGradient.h" 0033 #include "SVGPaintServerRadialGradient.h" 0034 #include "SVGStopElement.h" 0035 #include "SVGTransformList.h" 0036 #include "SVGTransformable.h" 0037 #include "SVGUnitTypes.h" 0038 0039 namespace WebCore 0040 { 0041 0042 SVGGradientElement::SVGGradientElement(const QualifiedName &tagName, Document *doc) 0043 : SVGStyledElement(tagName, doc) 0044 , SVGURIReference() 0045 , SVGExternalResourcesRequired() 0046 , m_spreadMethod(0) 0047 , m_gradientUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) 0048 , m_gradientTransform(SVGTransformList::create(SVGNames::gradientTransformAttr)) 0049 { 0050 } 0051 0052 SVGGradientElement::~SVGGradientElement() 0053 { 0054 } 0055 0056 ANIMATED_PROPERTY_DEFINITIONS(SVGGradientElement, int, Enumeration, enumeration, GradientUnits, gradientUnits, SVGNames::gradientUnitsAttr, m_gradientUnits) 0057 ANIMATED_PROPERTY_DEFINITIONS(SVGGradientElement, SVGTransformList *, TransformList, transformList, GradientTransform, gradientTransform, SVGNames::gradientTransformAttr, m_gradientTransform.get()) 0058 ANIMATED_PROPERTY_DEFINITIONS(SVGGradientElement, int, Enumeration, enumeration, SpreadMethod, spreadMethod, SVGNames::spreadMethodAttr, m_spreadMethod) 0059 0060 void SVGGradientElement::parseMappedAttribute(MappedAttribute *attr) 0061 { 0062 if (attr->name() == SVGNames::gradientUnitsAttr) { 0063 if (attr->value() == "userSpaceOnUse") { 0064 setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE); 0065 } else if (attr->value() == "objectBoundingBox") { 0066 setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); 0067 } 0068 } else if (attr->name() == SVGNames::gradientTransformAttr) { 0069 SVGTransformList *gradientTransforms = gradientTransformBaseValue(); 0070 if (!SVGTransformable::parseTransformAttribute(gradientTransforms, attr->value())) { 0071 ExceptionCode ec = 0; 0072 gradientTransforms->clear(ec); 0073 } 0074 } else if (attr->name() == SVGNames::spreadMethodAttr) { 0075 if (attr->value() == "reflect") { 0076 setSpreadMethodBaseValue(SVG_SPREADMETHOD_REFLECT); 0077 } else if (attr->value() == "repeat") { 0078 setSpreadMethodBaseValue(SVG_SPREADMETHOD_REPEAT); 0079 } else if (attr->value() == "pad") { 0080 setSpreadMethodBaseValue(SVG_SPREADMETHOD_PAD); 0081 } 0082 } else { 0083 if (SVGURIReference::parseMappedAttribute(attr)) { 0084 return; 0085 } 0086 if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) { 0087 return; 0088 } 0089 0090 SVGStyledElement::parseMappedAttribute(attr); 0091 } 0092 } 0093 0094 void SVGGradientElement::svgAttributeChanged(const QualifiedName &attrName) 0095 { 0096 SVGStyledElement::svgAttributeChanged(attrName); 0097 0098 if (!m_resource) { 0099 return; 0100 } 0101 0102 if (attrName == SVGNames::gradientUnitsAttr || 0103 attrName == SVGNames::gradientTransformAttr || 0104 attrName == SVGNames::spreadMethodAttr || 0105 SVGURIReference::isKnownAttribute(attrName) || 0106 SVGExternalResourcesRequired::isKnownAttribute(attrName) || 0107 SVGStyledElement::isKnownAttribute(attrName)) { 0108 m_resource->invalidate(); 0109 } 0110 } 0111 0112 void SVGGradientElement::childrenChanged(bool changedByParser, Node *beforeChange, Node *afterChange, int childCountDelta) 0113 { 0114 SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 0115 0116 if (m_resource) { 0117 m_resource->invalidate(); 0118 } 0119 } 0120 0121 RenderObject *SVGGradientElement::createRenderer(RenderArena *arena, RenderStyle *) 0122 { 0123 return new(arena) RenderSVGHiddenContainer(this); 0124 } 0125 0126 SVGResource *SVGGradientElement::canvasResource() 0127 { 0128 // qCDebug(KHTML_LOG) << "request gradient paint server"; 0129 if (!m_resource) { 0130 if (gradientType() == LinearGradientPaintServer) { 0131 m_resource = SVGPaintServerLinearGradient::create(this); 0132 } else { 0133 m_resource = SVGPaintServerRadialGradient::create(this); 0134 } 0135 } 0136 0137 return m_resource.get(); 0138 } 0139 0140 Vector<SVGGradientStop> SVGGradientElement::buildStops() const 0141 { 0142 Vector<SVGGradientStop> stops; 0143 0144 for (Node *n = firstChild(); n; n = n->nextSibling()) { 0145 SVGElement *element = n->isSVGElement() ? static_cast<SVGElement *>(n) : nullptr; 0146 0147 if (element && element->isGradientStop()) { 0148 SVGStopElement *stop = static_cast<SVGStopElement *>(element); 0149 float stopOffset = stop->offset(); 0150 0151 RenderStyle *stopStyle = stop->computedStyle(); 0152 QColor color = stopStyle->svgStyle()->stopColor(); 0153 float opacity = stopStyle->svgStyle()->stopOpacity(); 0154 0155 stops.append(makeGradientStop(stopOffset, QColor(color.red(), color.green(), color.blue(), int(opacity * 255.)))); 0156 } 0157 } 0158 0159 return stops; 0160 } 0161 0162 } 0163 0164 #endif // ENABLE(SVG)