File indexing completed on 2024-04-28 15:24:28

0001 /*
0002     Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003                   2004, 2005, 2006, 2007, 2008 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 "SVGClipPathElement.h"
0027 
0028 #include "css/cssstyleselector.h"
0029 #include "Document.h"
0030 #include "SVGNames.h"
0031 #include "SVGTransformList.h"
0032 #include "SVGUnitTypes.h"
0033 
0034 namespace WebCore
0035 {
0036 
0037 SVGClipPathElement::SVGClipPathElement(const QualifiedName &tagName, Document *doc)
0038     : SVGStyledTransformableElement(tagName, doc)
0039     , SVGTests()
0040     , SVGLangSpace()
0041     , SVGExternalResourcesRequired()
0042     , m_clipPathUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
0043 {
0044 }
0045 
0046 SVGClipPathElement::~SVGClipPathElement()
0047 {
0048 }
0049 
0050 ANIMATED_PROPERTY_DEFINITIONS(SVGClipPathElement, int, Enumeration, enumeration, ClipPathUnits, clipPathUnits, SVGNames::clipPathUnitsAttr, m_clipPathUnits)
0051 
0052 void SVGClipPathElement::parseMappedAttribute(MappedAttribute *attr)
0053 {
0054     if (attr->name() == SVGNames::clipPathUnitsAttr) {
0055         if (attr->value() == "userSpaceOnUse") {
0056             setClipPathUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
0057         } else if (attr->value() == "objectBoundingBox") {
0058             setClipPathUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
0059         }
0060     } else {
0061         if (SVGTests::parseMappedAttribute(attr)) {
0062             return;
0063         }
0064         if (SVGLangSpace::parseMappedAttribute(attr)) {
0065             return;
0066         }
0067         if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) {
0068             return;
0069         }
0070         SVGStyledTransformableElement::parseMappedAttribute(attr);
0071     }
0072 }
0073 
0074 void SVGClipPathElement::svgAttributeChanged(const QualifiedName &attrName)
0075 {
0076     SVGStyledTransformableElement::svgAttributeChanged(attrName);
0077 
0078     if (!m_clipper) {
0079         return;
0080     }
0081 
0082     if (attrName == SVGNames::clipPathUnitsAttr ||
0083             SVGTests::isKnownAttribute(attrName) ||
0084             SVGLangSpace::isKnownAttribute(attrName) ||
0085             SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
0086             SVGStyledTransformableElement::isKnownAttribute(attrName)) {
0087         m_clipper->invalidate();
0088     }
0089 }
0090 
0091 void SVGClipPathElement::childrenChanged(bool changedByParser, Node *beforeChange, Node *afterChange, int childCountDelta)
0092 {
0093     SVGStyledTransformableElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
0094 
0095     if (!m_clipper) {
0096         return;
0097     }
0098 
0099     m_clipper->invalidate();
0100 }
0101 
0102 SVGResource *SVGClipPathElement::canvasResource()
0103 {
0104     if (!m_clipper) {
0105         m_clipper = SVGResourceClipper::create();
0106     } else {
0107         m_clipper->resetClipData();
0108     }
0109 
0110     bool bbox = clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
0111 
0112     //RenderStyle* clipPathStyle = styleForRenderer(parent()->renderer()); // FIXME: Manual style resolution is a hack
0113     for (Node *n = firstChild(); n; n = n->nextSibling()) {
0114         if (n->isSVGElement() && static_cast<SVGElement *>(n)->isStyledTransformable()) {
0115             SVGStyledTransformableElement *styled = static_cast<SVGStyledTransformableElement *>(n);
0116             RenderStyle *pathStyle = document()->styleSelector()->styleForElement(styled/*khtml, clipPathStyle*/);
0117             if (pathStyle->display() != NONE) {
0118                 Path pathData = styled->toClipPath();
0119                 // FIXME: How do we know the element has done a layout?
0120                 pathData.transform(styled->animatedLocalTransform());
0121                 if (!pathData.isEmpty()) {
0122                     m_clipper->addClipData(pathData, pathStyle->svgStyle()->clipRule(), bbox);
0123                 }
0124             }
0125             //khtml pathStyle->deref(document()->renderArena());
0126         }
0127     }
0128     if (m_clipper->clipData().isEmpty()) {
0129         Path pathData;
0130         pathData.addRect(FloatRect());
0131         m_clipper->addClipData(pathData, RULE_EVENODD, bbox);
0132     }
0133     //khtml clipPathStyle->deref(document()->renderArena());
0134     return m_clipper.get();
0135 }
0136 
0137 }
0138 
0139 #endif // ENABLE(SVG)