File indexing completed on 2024-04-28 11:39:13

0001 /*
0002     Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
0003     Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
0004     Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
0005 
0006     This file is part of the KDE project
0007 
0008     This library is free software; you can redistribute it and/or
0009     modify it under the terms of the GNU Library General Public
0010     License as published by the Free Software Foundation; either
0011     version 2 of the License, or (at your option) any later version.
0012 
0013     This library is distributed in the hope that it will be useful,
0014     but WITHOUT ANY WARRANTY; without even the implied warranty of
0015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016     Library General Public License for more details.
0017 
0018     You should have received a copy of the GNU Library General Public License
0019     along with this library; see the file COPYING.LIB.  If not, write to
0020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021     Boston, MA 02110-1301, USA.
0022 */
0023 
0024 #if ENABLE(SVG) && ENABLE(SVG_FILTERS)
0025 #include "SVGFilterElement.h"
0026 
0027 #include "Attr.h"
0028 #include "SVGFilterPrimitiveStandardAttributes.h"
0029 #include "SVGLength.h"
0030 #include "SVGNames.h"
0031 #include "SVGUnitTypes.h"
0032 
0033 namespace WebCore
0034 {
0035 
0036 SVGFilterElement::SVGFilterElement(const QualifiedName &tagName, Document *doc)
0037     : SVGStyledElement(tagName, doc)
0038     , SVGURIReference()
0039     , SVGLangSpace()
0040     , SVGExternalResourcesRequired()
0041     , m_filterUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
0042     , m_primitiveUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
0043     , m_x(this, LengthModeWidth)
0044     , m_y(this, LengthModeHeight)
0045     , m_width(this, LengthModeWidth)
0046     , m_height(this, LengthModeHeight)
0047     , m_filterResX(0)
0048     , m_filterResY(0)
0049 {
0050     // Spec: If the attribute is not specified, the effect is as if a value of "-10%" were specified.
0051     setXBaseValue(SVGLength(this, LengthModeWidth, "-10%"));
0052     setYBaseValue(SVGLength(this, LengthModeHeight, "-10%"));
0053 
0054     // Spec: If the attribute is not specified, the effect is as if a value of "120%" were specified.
0055     setWidthBaseValue(SVGLength(this, LengthModeWidth, "120%"));
0056     setHeightBaseValue(SVGLength(this, LengthModeHeight, "120%"));
0057 }
0058 
0059 SVGFilterElement::~SVGFilterElement()
0060 {
0061 }
0062 
0063 ANIMATED_PROPERTY_DEFINITIONS(SVGFilterElement, int, Enumeration, enumeration, FilterUnits, filterUnits, SVGNames::filterUnitsAttr, m_filterUnits)
0064 ANIMATED_PROPERTY_DEFINITIONS(SVGFilterElement, int, Enumeration, enumeration, PrimitiveUnits, primitiveUnits, SVGNames::primitiveUnitsAttr, m_primitiveUnits)
0065 ANIMATED_PROPERTY_DEFINITIONS(SVGFilterElement, SVGLength, Length, length, X, x, SVGNames::xAttr, m_x)
0066 ANIMATED_PROPERTY_DEFINITIONS(SVGFilterElement, SVGLength, Length, length, Y, y, SVGNames::yAttr, m_y)
0067 ANIMATED_PROPERTY_DEFINITIONS(SVGFilterElement, SVGLength, Length, length, Width, width, SVGNames::widthAttr, m_width)
0068 ANIMATED_PROPERTY_DEFINITIONS(SVGFilterElement, SVGLength, Length, length, Height, height, SVGNames::heightAttr, m_height)
0069 ANIMATED_PROPERTY_DEFINITIONS_WITH_CUSTOM_IDENTIFIER(SVGFilterElement, long, Integer, integer, FilterResX, filterResX, SVGNames::filterResAttr, "filterResX", m_filterResX)
0070 ANIMATED_PROPERTY_DEFINITIONS_WITH_CUSTOM_IDENTIFIER(SVGFilterElement, long, Integer, integer, FilterResY, filterResY, SVGNames::filterResAttr, "filterResY", m_filterResY)
0071 
0072 void SVGFilterElement::setFilterRes(unsigned long, unsigned long) const
0073 {
0074 }
0075 
0076 void SVGFilterElement::parseMappedAttribute(MappedAttribute *attr)
0077 {
0078     const String &value = attr->value();
0079     if (attr->name() == SVGNames::filterUnitsAttr) {
0080         if (value == "userSpaceOnUse") {
0081             setFilterUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
0082         } else if (value == "objectBoundingBox") {
0083             setFilterUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
0084         }
0085     } else if (attr->name() == SVGNames::primitiveUnitsAttr) {
0086         if (value == "userSpaceOnUse") {
0087             setPrimitiveUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
0088         } else if (value == "objectBoundingBox") {
0089             setPrimitiveUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
0090         }
0091     } else if (attr->name() == SVGNames::xAttr) {
0092         setXBaseValue(SVGLength(this, LengthModeWidth, value));
0093     } else if (attr->name() == SVGNames::yAttr) {
0094         setYBaseValue(SVGLength(this, LengthModeHeight, value));
0095     } else if (attr->name() == SVGNames::widthAttr) {
0096         setWidthBaseValue(SVGLength(this, LengthModeWidth, value));
0097     } else if (attr->name() == SVGNames::heightAttr) {
0098         setHeightBaseValue(SVGLength(this, LengthModeHeight, value));
0099     } else {
0100         if (SVGURIReference::parseMappedAttribute(attr)) {
0101             return;
0102         }
0103         if (SVGLangSpace::parseMappedAttribute(attr)) {
0104             return;
0105         }
0106         if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) {
0107             return;
0108         }
0109 
0110         SVGStyledElement::parseMappedAttribute(attr);
0111     }
0112 }
0113 
0114 SVGResource *SVGFilterElement::canvasResource()
0115 {
0116     if (!attached()) {
0117         return 0;
0118     }
0119 
0120     if (!m_filter) {
0121         m_filter = new SVGResourceFilter();
0122     }
0123 
0124     bool filterBBoxMode = filterUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
0125     m_filter->setFilterBoundingBoxMode(filterBBoxMode);
0126 
0127     float _x, _y, _width, _height;
0128 
0129     if (filterBBoxMode) {
0130         _x = x().valueAsPercentage();
0131         _y = y().valueAsPercentage();
0132         _width = width().valueAsPercentage();
0133         _height = height().valueAsPercentage();
0134     } else {
0135         m_filter->setXBoundingBoxMode(x().unitType() == LengthTypePercentage);
0136         m_filter->setYBoundingBoxMode(y().unitType() == LengthTypePercentage);
0137 
0138         _x = x().value();
0139         _y = y().value();
0140         _width = width().value();
0141         _height = height().value();
0142     }
0143 
0144     m_filter->setFilterRect(FloatRect(_x, _y, _width, _height));
0145 
0146     bool primitiveBBoxMode = primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
0147     m_filter->setEffectBoundingBoxMode(primitiveBBoxMode);
0148 
0149     // TODO : use switch/case instead?
0150     m_filter->clearEffects();
0151     for (Node *n = firstChild(); n != 0; n = n->nextSibling()) {
0152         SVGElement *element = 0;
0153         if (n->isSVGElement()) {
0154             element = static_cast<SVGElement *>(n);
0155         }
0156         if (element && element->isFilterEffect()) {
0157             SVGFilterPrimitiveStandardAttributes *filterAttributes = static_cast<SVGFilterPrimitiveStandardAttributes *>(element);
0158             SVGFilterEffect *filterEffect = filterAttributes->filterEffect(m_filter.get());
0159             if (!filterEffect) {
0160                 continue;
0161             }
0162 
0163             m_filter->addFilterEffect(filterEffect);
0164         }
0165     }
0166 
0167     return m_filter.get();
0168 }
0169 
0170 }
0171 
0172 #endif // ENABLE(SVG)
0173