1 /* 2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2009, 2014 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #ifndef SVGElement_h 23 #define SVGElement_h 24 25 #include "core/SVGNames.h" 26 #include "core/dom/Element.h" 27 #include "core/svg/SVGAnimatedString.h" 28 #include "core/svg/SVGParsingError.h" 29 #include "core/svg/properties/SVGPropertyInfo.h" 30 #include "platform/Timer.h" 31 #include "wtf/HashMap.h" 32 #include "wtf/OwnPtr.h" 33 34 namespace blink { 35 36 class AffineTransform; 37 class CSSCursorImageValue; 38 class Document; 39 class SVGAnimatedPropertyBase; 40 class SubtreeLayoutScope; 41 class SVGCursorElement; 42 class SVGDocumentExtensions; 43 class SVGElement; 44 class SVGElementRareData; 45 class SVGFitToViewBox; 46 class SVGSVGElement; 47 class SVGUseElement; 48 49 void mapAttributeToCSSProperty(HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName); 50 51 typedef WillBeHeapHashSet<RawPtrWillBeMember<SVGElement> > SVGElementSet; 52 53 class SVGElement : public Element { 54 DEFINE_WRAPPERTYPEINFO(); 55 public: 56 virtual ~SVGElement(); 57 virtual void attach(const AttachContext&) OVERRIDE; 58 virtual void detach(const AttachContext&) OVERRIDE; 59 60 virtual short tabIndex() const OVERRIDE; 61 virtual bool supportsFocus() const OVERRIDE { return false; } 62 63 bool isOutermostSVGSVGElement() const; 64 65 bool hasTagName(const SVGQualifiedName& name) const { return hasLocalName(name.localName()); } 66 67 virtual String title() const OVERRIDE; 68 bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); } 69 static bool isAnimatableCSSProperty(const QualifiedName&); 70 enum CTMScope { 71 NearestViewportScope, // Used by SVGGraphicsElement::getCTM() 72 ScreenScope, // Used by SVGGraphicsElement::getScreenCTM() 73 AncestorScope // Used by SVGSVGElement::get{Enclosure|Intersection}List() 74 }; 75 virtual AffineTransform localCoordinateSpaceTransform(CTMScope) const; 76 virtual bool needsPendingResourceHandling() const { return true; } 77 78 bool instanceUpdatesBlocked() const; 79 void setInstanceUpdatesBlocked(bool); 80 81 SVGSVGElement* ownerSVGElement() const; 82 SVGElement* viewportElement() const; 83 84 SVGDocumentExtensions& accessDocumentSVGExtensions(); 85 86 virtual bool isSVGGraphicsElement() const { return false; } 87 virtual bool isFilterEffect() const { return false; } 88 virtual bool isTextContent() const { return false; } 89 virtual bool isTextPositioning() const { return false; } 90 virtual bool isStructurallyExternal() const { return false; } 91 92 // For SVGTests 93 virtual bool isValid() const { return true; } 94 95 virtual void svgAttributeChanged(const QualifiedName&); 96 97 PassRefPtr<SVGAnimatedPropertyBase> propertyFromAttribute(const QualifiedName& attributeName); 98 static AnimatedPropertyType animatedPropertyTypeForCSSAttribute(const QualifiedName& attributeName); 99 100 void sendSVGLoadEventToSelfAndAncestorChainIfPossible(); 101 bool sendSVGLoadEventIfPossible(); 102 void sendSVGLoadEventIfPossibleAsynchronously(); 103 void svgLoadEventTimerFired(Timer<SVGElement>*); 104 virtual Timer<SVGElement>* svgLoadEventTimer(); 105 106 virtual AffineTransform* supplementalTransform() { return 0; } 107 108 void invalidateSVGAttributes() { ensureUniqueElementData().m_animatedSVGAttributesAreDirty = true; } 109 void invalidateSVGPresentationAttributeStyle() { ensureUniqueElementData().m_presentationAttributeStyleIsDirty = true; } 110 111 const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& instancesForElement() const; 112 void mapInstanceToElement(SVGElement*); 113 void removeInstanceMapping(SVGElement*); 114 115 bool getBoundingBox(FloatRect&); 116 117 void setCursorElement(SVGCursorElement*); 118 void setCursorImageValue(CSSCursorImageValue*); 119 120 #if !ENABLE(OILPAN) 121 void cursorElementRemoved(); 122 void cursorImageValueRemoved(); 123 #endif 124 125 SVGElement* correspondingElement(); 126 void setCorrespondingElement(SVGElement*); 127 SVGUseElement* correspondingUseElement() const; 128 129 void synchronizeAnimatedSVGAttribute(const QualifiedName&) const; 130 131 virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE FINAL; 132 133 virtual void synchronizeRequiredFeatures() { } 134 virtual void synchronizeRequiredExtensions() { } 135 virtual void synchronizeSystemLanguage() { } 136 137 #if ENABLE(ASSERT) 138 virtual bool isAnimatableAttribute(const QualifiedName&) const; 139 #endif 140 141 MutableStylePropertySet* animatedSMILStyleProperties() const; 142 MutableStylePropertySet* ensureAnimatedSMILStyleProperties(); 143 void setUseOverrideComputedStyle(bool); 144 145 virtual bool haveLoadedRequiredResources(); 146 147 virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture = false) OVERRIDE FINAL; 148 virtual bool removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture = false) OVERRIDE FINAL; 149 150 void invalidateRelativeLengthClients(SubtreeLayoutScope* = 0); 151 152 void addToPropertyMap(PassRefPtr<SVGAnimatedPropertyBase>); 153 154 SVGAnimatedString* className() { return m_className.get(); } 155 156 bool inUseShadowTree() const; 157 158 SVGElementSet* setOfIncomingReferences() const; 159 void addReferenceTo(SVGElement*); 160 void rebuildAllIncomingReferences(); 161 void removeAllIncomingReferences(); 162 void removeAllOutgoingReferences(); 163 164 class InvalidationGuard { 165 STACK_ALLOCATED(); 166 WTF_MAKE_NONCOPYABLE(InvalidationGuard); 167 public: 168 InvalidationGuard(SVGElement* element) : m_element(element) { } 169 ~InvalidationGuard() { m_element->invalidateInstances(); } 170 171 private: 172 RawPtrWillBeMember<SVGElement> m_element; 173 }; 174 175 class InstanceUpdateBlocker { 176 STACK_ALLOCATED(); 177 WTF_MAKE_NONCOPYABLE(InstanceUpdateBlocker); 178 public: 179 InstanceUpdateBlocker(SVGElement* targetElement); 180 ~InstanceUpdateBlocker(); 181 182 private: 183 RawPtrWillBeMember<SVGElement> m_targetElement; 184 }; 185 186 void invalidateInstances(); 187 188 virtual void trace(Visitor*) OVERRIDE; 189 190 static const AtomicString& eventParameterName(); 191 192 protected: 193 SVGElement(const QualifiedName&, Document&, ConstructionType = CreateSVGElement); 194 195 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; 196 197 // FIXME: |parseAttributeNew| is a new implementation of parseAttribute 198 // which maps attribute using |m_attributeToPropertyMap|. 199 // This is to replace |parseAttribute()| after all derived class switch to call this. 200 void parseAttributeNew(const QualifiedName&, const AtomicString&); 201 202 virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly) OVERRIDE; 203 204 virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; 205 virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; 206 207 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 208 virtual void removedFrom(ContainerNode*) OVERRIDE; 209 virtual void childrenChanged(const ChildrenChange&) OVERRIDE; 210 211 static CSSPropertyID cssPropertyIdForSVGAttributeName(const QualifiedName&); 212 void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), this); } 213 void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement*); 214 215 virtual bool selfHasRelativeLengths() const { return false; } 216 217 SVGElementRareData* ensureSVGRareData(); 218 inline bool hasSVGRareData() const { return m_SVGRareData; } 219 inline SVGElementRareData* svgRareData() const 220 { 221 ASSERT(m_SVGRareData); 222 return m_SVGRareData.get(); 223 } 224 225 // SVGFitToViewBox::parseAttribute uses reportAttributeParsingError. 226 friend class SVGFitToViewBox; 227 void reportAttributeParsingError(SVGParsingError, const QualifiedName&, const AtomicString&); 228 bool hasFocusEventListeners() const; 229 230 private: 231 // FIXME: Author shadows should be allowed 232 // https://bugs.webkit.org/show_bug.cgi?id=77938 233 virtual bool areAuthorShadowsAllowed() const OVERRIDE FINAL { return false; } 234 235 bool isSVGElement() const WTF_DELETED_FUNCTION; // This will catch anyone doing an unnecessary check. 236 bool isStyledElement() const WTF_DELETED_FUNCTION; // This will catch anyone doing an unnecessary check. 237 238 RenderStyle* computedStyle(PseudoId = NOPSEUDO); 239 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) OVERRIDE FINAL { return computedStyle(pseudoElementSpecifier); } 240 virtual void willRecalcStyle(StyleRecalcChange) OVERRIDE; 241 242 void buildPendingResourcesIfNeeded(); 243 244 WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> > m_elementsWithRelativeLengths; 245 246 typedef HashMap<QualifiedName, RefPtr<SVGAnimatedPropertyBase> > AttributeToPropertyMap; 247 AttributeToPropertyMap m_attributeToPropertyMap; 248 249 #if ENABLE(ASSERT) 250 bool m_inRelativeLengthClientsInvalidation; 251 #endif 252 253 OwnPtrWillBeMember<SVGElementRareData> m_SVGRareData; 254 RefPtr<SVGAnimatedString> m_className; 255 }; 256 257 struct SVGAttributeHashTranslator { 258 static unsigned hash(const QualifiedName& key) 259 { 260 if (key.hasPrefix()) { 261 QualifiedNameComponents components = { nullAtom.impl(), key.localName().impl(), key.namespaceURI().impl() }; 262 return hashComponents(components); 263 } 264 return DefaultHash<QualifiedName>::Hash::hash(key); 265 } 266 static bool equal(const QualifiedName& a, const QualifiedName& b) { return a.matches(b); } 267 }; 268 269 DEFINE_ELEMENT_TYPE_CASTS(SVGElement, isSVGElement()); 270 271 template <typename T> bool isElementOfType(const SVGElement&); 272 template <> inline bool isElementOfType<const SVGElement>(const SVGElement&) { return true; } 273 274 inline bool Node::hasTagName(const SVGQualifiedName& name) const 275 { 276 return isSVGElement() && toSVGElement(*this).hasTagName(name); 277 } 278 279 // This requires isSVG*Element(const SVGElement&). 280 #define DEFINE_SVGELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) \ 281 inline bool is##thisType(const thisType* element); \ 282 inline bool is##thisType(const thisType& element); \ 283 inline bool is##thisType(const SVGElement* element) { return element && is##thisType(*element); } \ 284 inline bool is##thisType(const Node& node) { return node.isSVGElement() ? is##thisType(toSVGElement(node)) : false; } \ 285 inline bool is##thisType(const Node* node) { return node && is##thisType(*node); } \ 286 template<typename T> inline bool is##thisType(const PassRefPtr<T>& node) { return is##thisType(node.get()); } \ 287 template<typename T> inline bool is##thisType(const RefPtr<T>& node) { return is##thisType(node.get()); } \ 288 template <> inline bool isElementOfType<const thisType>(const SVGElement& element) { return is##thisType(element); } \ 289 DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) 290 291 } // namespace blink 292 293 #include "core/SVGElementTypeHelpers.h" 294 295 #endif // SVGElement_h 296