Home | History | Annotate | Download | only in svg
      1 /*
      2     Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      3                   2004, 2005, 2006, 2007, 2008 Rob Buis <buis (at) kde.org>
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public License
     16     along with this library; see the file COPYING.LIB.  If not, write to
     17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18     Boston, MA 02110-1301, USA.
     19 */
     20 
     21 #include "config.h"
     22 
     23 #if ENABLE(SVG)
     24 #include "SVGClipPathElement.h"
     25 
     26 #include "CSSStyleSelector.h"
     27 #include "Document.h"
     28 #include "MappedAttribute.h"
     29 #include "RenderSVGHiddenContainer.h"
     30 #include "SVGNames.h"
     31 #include "SVGTransformList.h"
     32 #include "SVGUnitTypes.h"
     33 
     34 namespace WebCore {
     35 
     36 SVGClipPathElement::SVGClipPathElement(const QualifiedName& tagName, Document* doc)
     37     : SVGStyledTransformableElement(tagName, doc)
     38     , SVGTests()
     39     , SVGLangSpace()
     40     , SVGExternalResourcesRequired()
     41     , m_clipPathUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
     42 {
     43 }
     44 
     45 SVGClipPathElement::~SVGClipPathElement()
     46 {
     47 }
     48 
     49 void SVGClipPathElement::parseMappedAttribute(MappedAttribute* attr)
     50 {
     51     if (attr->name() == SVGNames::clipPathUnitsAttr) {
     52         if (attr->value() == "userSpaceOnUse")
     53             setClipPathUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
     54         else if (attr->value() == "objectBoundingBox")
     55             setClipPathUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
     56     } else {
     57         if (SVGTests::parseMappedAttribute(attr))
     58             return;
     59         if (SVGLangSpace::parseMappedAttribute(attr))
     60             return;
     61         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
     62             return;
     63         SVGStyledTransformableElement::parseMappedAttribute(attr);
     64     }
     65 }
     66 
     67 void SVGClipPathElement::svgAttributeChanged(const QualifiedName& attrName)
     68 {
     69     SVGStyledTransformableElement::svgAttributeChanged(attrName);
     70 
     71     if (!m_clipper)
     72         return;
     73 
     74     if (attrName == SVGNames::clipPathUnitsAttr ||
     75         SVGTests::isKnownAttribute(attrName) ||
     76         SVGLangSpace::isKnownAttribute(attrName) ||
     77         SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
     78         SVGStyledTransformableElement::isKnownAttribute(attrName))
     79         m_clipper->invalidate();
     80 }
     81 
     82 void SVGClipPathElement::synchronizeProperty(const QualifiedName& attrName)
     83 {
     84     SVGStyledTransformableElement::synchronizeProperty(attrName);
     85 
     86     if (attrName == anyQName()) {
     87         synchronizeClipPathUnits();
     88         synchronizeExternalResourcesRequired();
     89         return;
     90     }
     91 
     92     if (attrName == SVGNames::clipPathUnitsAttr)
     93         synchronizeClipPathUnits();
     94     else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
     95         synchronizeExternalResourcesRequired();
     96 }
     97 
     98 void SVGClipPathElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
     99 {
    100     SVGStyledTransformableElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
    101 
    102     if (!m_clipper)
    103         return;
    104 
    105     m_clipper->invalidate();
    106 }
    107 
    108 RenderObject* SVGClipPathElement::createRenderer(RenderArena* arena, RenderStyle*)
    109 {
    110     return new (arena) RenderSVGHiddenContainer(this);
    111 }
    112 
    113 SVGResource* SVGClipPathElement::canvasResource(const RenderObject*)
    114 {
    115     if (!m_clipper)
    116         m_clipper = SVGResourceClipper::create();
    117     else
    118         m_clipper->resetClipData();
    119 
    120     bool bbox = clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    121 
    122     for (Node* node = firstChild(); node; node = node->nextSibling()) {
    123         if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyledTransformable())
    124             continue;
    125         SVGStyledTransformableElement* styled = static_cast<SVGStyledTransformableElement*>(node);
    126         RenderStyle* style = styled->renderer() ? styled->renderer()->style() : 0;
    127         if (!style || style->display() == NONE)
    128             continue;
    129         Path pathData = styled->toClipPath();
    130         if (pathData.isEmpty())
    131             continue;
    132         m_clipper->addClipData(pathData, style->svgStyle()->clipRule(), bbox);
    133     }
    134     if (m_clipper->clipData().isEmpty()) {
    135         Path pathData;
    136         pathData.addRect(FloatRect());
    137         m_clipper->addClipData(pathData, RULE_EVENODD, bbox);
    138     }
    139     return m_clipper.get();
    140 }
    141 
    142 }
    143 
    144 #endif // ENABLE(SVG)
    145