1/*
2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4 * Copyright (C) 2009, 2014 Apple Inc. All rights reserved.
5 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
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., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#ifndef SVGElement_h
24#define SVGElement_h
25
26#include "CSSPropertyNames.h"
27#include "SVGAnimatedString.h"
28#include "SVGElementTypeHelpers.h"
29#include "SVGLangSpace.h"
30#include "SVGLocatable.h"
31#include "SVGParsingError.h"
32#include "SVGPropertyInfo.h"
33#include "StyledElement.h"
34#include "Timer.h"
35#include <wtf/HashMap.h>
36#include <wtf/HashSet.h>
37#include <wtf/PassRefPtr.h>
38
39namespace WebCore {
40
41class AffineTransform;
42class CSSCursorImageValue;
43class CSSStyleDeclaration;
44class CSSValue;
45class Document;
46class SVGAttributeToPropertyMap;
47class SVGCursorElement;
48class SVGDocumentExtensions;
49class SVGElementInstance;
50class SVGElementRareData;
51class SVGSVGElement;
52
53void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName);
54
55class SVGElement : public StyledElement, public SVGLangSpace {
56public:
57    bool isOutermostSVGSVGElement() const;
58
59    String xmlbase() const;
60    void setXmlbase(const String&, ExceptionCode&);
61
62    SVGSVGElement* ownerSVGElement() const;
63    SVGElement* viewportElement() const;
64
65    virtual String title() const override;
66    static bool isAnimatableCSSProperty(const QualifiedName&);
67    bool isKnownAttribute(const QualifiedName&);
68    PassRefPtr<CSSValue> getPresentationAttribute(const String& name);
69    virtual bool supportsMarkers() const { return false; }
70    bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); }
71    virtual bool needsPendingResourceHandling() const { return true; }
72    bool instanceUpdatesBlocked() const;
73    void setInstanceUpdatesBlocked(bool);
74    virtual AffineTransform localCoordinateSpaceTransform(SVGLocatable::CTMScope) const;
75
76    SVGDocumentExtensions* accessDocumentSVGExtensions();
77
78    virtual bool isSVGGraphicsElement() const { return false; }
79    virtual bool isFilterEffect() const { return false; }
80    virtual bool isGradientStop() const { return false; }
81    virtual bool isTextContent() const { return false; }
82    virtual bool isSMILElement() const { return false; }
83
84    // For SVGTests
85    virtual bool isValid() const { return true; }
86
87    virtual void svgAttributeChanged(const QualifiedName&);
88
89    virtual void animatedPropertyTypeForAttribute(const QualifiedName&, Vector<AnimatedPropertyType>&);
90
91    void sendSVGLoadEventIfPossible(bool sendParentLoadEvents = false);
92    void sendSVGLoadEventIfPossibleAsynchronously();
93    void svgLoadEventTimerFired(Timer<SVGElement>*);
94    virtual Timer<SVGElement>* svgLoadEventTimer();
95
96    virtual AffineTransform* supplementalTransform() { return 0; }
97
98    void invalidateSVGAttributes() { ensureUniqueElementData().setAnimatedSVGAttributesAreDirty(true); }
99    void invalidateSVGPresentationAttributeStyle() { ensureUniqueElementData().setPresentationAttributeStyleIsDirty(true); }
100
101    const HashSet<SVGElementInstance*>& instancesForElement() const;
102
103    bool getBoundingBox(FloatRect&, SVGLocatable::StyleUpdateStrategy = SVGLocatable::AllowStyleUpdate);
104
105    void setCursorElement(SVGCursorElement*);
106    void cursorElementRemoved();
107    void setCursorImageValue(CSSCursorImageValue*);
108    void cursorImageValueRemoved();
109
110    SVGElement* correspondingElement();
111    void setCorrespondingElement(SVGElement*);
112
113    void synchronizeAnimatedSVGAttribute(const QualifiedName&) const;
114    static void synchronizeAllAnimatedSVGAttribute(SVGElement*);
115
116    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
117
118    static void synchronizeRequiredFeatures(SVGElement* contextElement);
119    static void synchronizeRequiredExtensions(SVGElement* contextElement);
120    static void synchronizeSystemLanguage(SVGElement* contextElement);
121
122    virtual void synchronizeRequiredFeatures() { }
123    virtual void synchronizeRequiredExtensions() { }
124    virtual void synchronizeSystemLanguage() { }
125
126    static QualifiedName animatableAttributeForName(const AtomicString&);
127#ifndef NDEBUG
128    bool isAnimatableAttribute(const QualifiedName&) const;
129#endif
130
131    MutableStyleProperties* animatedSMILStyleProperties() const;
132    MutableStyleProperties& ensureAnimatedSMILStyleProperties();
133    void setUseOverrideComputedStyle(bool);
134
135    virtual bool haveLoadedRequiredResources();
136
137    virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture) override;
138    virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) override;
139    bool hasFocusEventListeners() const;
140
141#if ENABLE(CSS_REGIONS)
142    virtual bool shouldMoveToFlowThread(const RenderStyle&) const override;
143#endif
144
145    bool hasTagName(const SVGQualifiedName& name) const { return hasLocalName(name.localName()); }
146    virtual short tabIndex() const override;
147
148    void callClearTarget() { clearTarget(); }
149
150protected:
151    SVGElement(const QualifiedName&, Document&);
152    virtual ~SVGElement();
153
154    virtual bool isMouseFocusable() const override;
155    virtual bool supportsFocus() const override { return false; }
156
157    virtual bool rendererIsNeeded(const RenderStyle&) override;
158    virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
159
160    virtual void finishParsingChildren() override;
161    virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly) override;
162    virtual bool childShouldCreateRenderer(const Node&) const override;
163
164    SVGElementRareData& ensureSVGRareData();
165
166    void reportAttributeParsingError(SVGParsingError, const QualifiedName&, const AtomicString&);
167    static CSSPropertyID cssPropertyIdForSVGAttributeName(const QualifiedName&);
168
169    virtual bool isPresentationAttribute(const QualifiedName&) const override;
170    virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;
171    virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
172    virtual void removedFrom(ContainerNode&) override;
173    virtual void childrenChanged(const ChildChange&) override;
174    virtual bool selfHasRelativeLengths() const { return false; }
175    void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), this); }
176    void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement*);
177
178private:
179    friend class SVGElementInstance;
180
181    virtual RenderStyle* computedStyle(PseudoId = NOPSEUDO) override final;
182    virtual bool willRecalcStyle(Style::Change) override;
183
184    virtual bool isSupported(StringImpl* feature, StringImpl* version) const;
185
186    virtual void clearTarget() { }
187
188    void mapInstanceToElement(SVGElementInstance*);
189    void removeInstanceMapping(SVGElementInstance*);
190
191    void buildPendingResourcesIfNeeded();
192    virtual void accessKeyAction(bool sendMouseEvents) override;
193
194#ifndef NDEBUG
195    virtual bool filterOutAnimatableAttribute(const QualifiedName&) const;
196#endif
197
198    std::unique_ptr<SVGElementRareData> m_svgRareData;
199
200    HashSet<SVGElement*> m_elementsWithRelativeLengths;
201
202    BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGElement)
203        DECLARE_ANIMATED_STRING(ClassName, className)
204    END_DECLARE_ANIMATED_PROPERTIES
205
206};
207
208struct SVGAttributeHashTranslator {
209    static unsigned hash(const QualifiedName& key)
210    {
211        if (key.hasPrefix()) {
212            QualifiedNameComponents components = { nullAtom.impl(), key.localName().impl(), key.namespaceURI().impl() };
213            return hashComponents(components);
214        }
215        return DefaultHash<QualifiedName>::Hash::hash(key);
216    }
217    static bool equal(const QualifiedName& a, const QualifiedName& b) { return a.matches(b); }
218};
219
220void isSVGElement(const SVGElement&); // Catch unnecessary runtime check of type known at compile time.
221inline bool isSVGElement(const Node& node) { return node.isSVGElement(); }
222template <> inline bool isElementOfType<const SVGElement>(const Element& element) { return element.isSVGElement(); }
223
224NODE_TYPE_CASTS(SVGElement)
225
226inline bool Node::hasTagName(const SVGQualifiedName& name) const
227{
228    return isSVGElement() && toSVGElement(*this).hasTagName(name);
229}
230
231}
232
233#endif
234