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)