Reviewed by Eric. Rubber stamped by Oliver.
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGStyledElement.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005 Rob Buis <buis@kde.org>
4
5     This file is part of the KDE project
6
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20     Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24
25 #ifdef SVG_SUPPORT
26 #include "SVGStyledElement.h"
27
28 #include "Attr.h"
29 #include "HTMLNames.h"
30 #include "Document.h"
31 #include "PlatformString.h"
32 #include "RenderView.h"
33 #include "RenderPath.h"
34 #include "SVGElement.h"
35 #include "SVGHelper.h"
36 #include "SVGMatrix.h"
37 #include "SVGNames.h"
38 #include "SVGRenderStyle.h"
39 #include "SVGSVGElement.h"
40 #include "ksvgcssproperties.h"
41
42 #include <wtf/Assertions.h>
43
44 namespace WebCore {
45
46 // Defined in CSSGrammar.y, but not in any header, so just declare it here for now.
47 int getPropertyID(const char* str, int len);
48
49 using namespace SVGNames;
50
51 SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* doc)
52     : SVGElement(tagName, doc)
53     , m_updateVectorial(false)
54 {
55 }
56
57 SVGStyledElement::~SVGStyledElement()
58 {
59 }
60
61 ANIMATED_PROPERTY_DEFINITIONS(SVGStyledElement, String, String, string, ClassName, className, HTMLNames::classAttr.localName(), m_className)
62
63 RenderObject* SVGStyledElement::createRenderer(RenderArena* arena, RenderStyle* style)
64 {
65     Path pathData = toPathData();
66     if (pathData.isEmpty())
67         return 0;
68
69     RenderPath *item = new (arena) RenderPath(style, this);
70     item->setPath(pathData);
71     return item;
72 }
73
74 void SVGStyledElement::parseMappedAttribute(MappedAttribute* attr)
75 {
76     const String& value = attr->value();
77     // id and class are handled by StyledElement
78     DeprecatedString qProp = attr->name().localName().deprecatedString();
79     int propId = getPropertyID(qProp.ascii(), qProp.length());
80     if (propId == 0)
81         propId = SVG::getSVGCSSPropertyID(qProp.ascii(), qProp.length());
82     if (propId > 0) {
83         addCSSProperty(attr, propId, value);
84         setChanged();
85         return;
86     }
87     
88     SVGElement::parseMappedAttribute(attr);
89 }
90
91 void SVGStyledElement::notifyAttributeChange() const
92 {
93     // For most cases we need to handle vectorial data changes (ie. rect x changed)
94     if (!ownerDocument()->parsing()) {
95         // TODO: Use a more optimized way of updating, means not calling updateCanvasItem() here!
96         const_cast<SVGStyledElement*>(this)->m_updateVectorial = true;
97         const_cast<SVGStyledElement*>(this)->updateCanvasItem();
98     }
99 }
100
101 void SVGStyledElement::attributeChanged(Attribute* attr, bool preserveDecls)
102 {
103     // FIXME: Eventually subclasses from SVGElement should implement
104     // attributeChanged() instead of notifyAttributeChange()
105     // This is a quick fix to allow dynamic updates of SVG elements
106     // but will result in slower dynamic-update performance than necessary.
107     SVGElement::attributeChanged(attr, preserveDecls);
108     notifyAttributeChange();
109 }
110
111 RenderView* SVGStyledElement::view() const
112 {
113     return static_cast<RenderView*>(document()->renderer());
114 }
115
116 void SVGStyledElement::updateCanvasItem()
117 {
118     if (!m_updateVectorial || !renderer() || !renderer()->isRenderPath())
119         return;
120     
121     RenderPath* renderPath = static_cast<RenderPath*>(renderer());
122     bool renderSection = false;
123     
124     SVGElement* parentElement = svg_dynamic_cast(parentNode());
125     if (parentElement && parentElement->renderer() && parentElement->isStyled()
126         && parentElement->childShouldCreateRenderer(this))
127         renderSection = true;
128
129     renderPath->setPath(toPathData());
130
131     if (renderSection)
132         renderPath->setNeedsLayout(true);
133
134     m_updateVectorial = false;
135 }
136
137 const SVGStyledElement* SVGStyledElement::pushAttributeContext(const SVGStyledElement*)
138 {
139     if (view())
140         static_cast<RenderPath*>(renderer())->setPath(toPathData());
141
142     return 0;
143 }
144
145 }
146
147 // vim:ts=4:noet
148 #endif // SVG_SUPPORT
149