OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde .org> | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde .org> |
3 * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org> |
4 * Copyright (C) 2008 Apple Inc. All rights reserved. | 4 * Copyright (C) 2008 Apple Inc. All rights reserved. |
5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> | 5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> |
6 * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> | 6 * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "config.h" | 24 #include "config.h" |
25 | 25 |
26 #include "core/svg/SVGElement.h" | 26 #include "core/svg/SVGElement.h" |
27 | 27 |
28 #include "HTMLNames.h" | 28 #include "HTMLNames.h" |
29 #include "SVGNames.h" | 29 #include "SVGNames.h" |
30 #include "XLinkNames.h" | 30 #include "XLinkNames.h" |
31 #include "XMLNames.h" | 31 #include "XMLNames.h" |
32 #include "bindings/v8/ScriptEventListener.h" | 32 #include "bindings/v8/ScriptEventListener.h" |
33 #include "core/css/CSSCursorImageValue.h" | 33 #include "core/css/CSSCursorImageValue.h" |
34 #include "core/css/CSSParser.h" | |
34 #include "core/dom/DOMImplementation.h" | 35 #include "core/dom/DOMImplementation.h" |
35 #include "core/dom/Document.h" | 36 #include "core/dom/Document.h" |
36 #include "core/dom/Event.h" | 37 #include "core/dom/Event.h" |
37 #include "core/dom/NodeRenderingContext.h" | 38 #include "core/dom/NodeRenderingContext.h" |
39 #include "core/dom/NodeTraversal.h" | |
40 #include "core/dom/shadow/ShadowRoot.h" | |
38 #include "core/rendering/RenderObject.h" | 41 #include "core/rendering/RenderObject.h" |
42 #include "core/rendering/svg/RenderSVGResourceContainer.h" | |
39 #include "core/svg/SVGCursorElement.h" | 43 #include "core/svg/SVGCursorElement.h" |
40 #include "core/svg/SVGDocumentExtensions.h" | 44 #include "core/svg/SVGDocumentExtensions.h" |
41 #include "core/svg/SVGElementInstance.h" | 45 #include "core/svg/SVGElementInstance.h" |
42 #include "core/svg/SVGElementRareData.h" | 46 #include "core/svg/SVGElementRareData.h" |
43 #include "core/svg/SVGGraphicsElement.h" | 47 #include "core/svg/SVGGraphicsElement.h" |
44 #include "core/svg/SVGSVGElement.h" | 48 #include "core/svg/SVGSVGElement.h" |
49 #include "core/svg/SVGUseElement.h" | |
45 | 50 |
46 namespace WebCore { | 51 namespace WebCore { |
47 | 52 |
53 // Animated property definitions | |
54 DEFINE_ANIMATED_STRING(SVGElement, HTMLNames::classAttr, ClassName, className) | |
55 | |
56 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGElement) | |
57 REGISTER_LOCAL_ANIMATED_PROPERTY(className) | |
58 END_REGISTER_ANIMATED_PROPERTIES | |
59 | |
48 using namespace HTMLNames; | 60 using namespace HTMLNames; |
61 using namespace SVGNames; | |
62 | |
63 void mapAttributeToCSSProperty(HashMap<StringImpl*, CSSPropertyID>* propertyName ToIdMap, const QualifiedName& attrName) | |
64 { | |
65 // FIXME: when CSS supports "transform-origin" the special case for transfor m_originAttr can be removed. | |
66 CSSPropertyID propertyId = cssPropertyID(attrName.localName()); | |
67 if (!propertyId && attrName == transform_originAttr) | |
68 propertyId = CSSPropertyWebkitTransformOrigin; // cssPropertyID("-webkit -transform-origin") | |
69 ASSERT(propertyId > 0); | |
70 propertyNameToIdMap->set(attrName.localName().impl(), propertyId); | |
71 } | |
49 | 72 |
50 SVGElement::SVGElement(const QualifiedName& tagName, Document* document, Constru ctionType constructionType) | 73 SVGElement::SVGElement(const QualifiedName& tagName, Document* document, Constru ctionType constructionType) |
51 : Element(tagName, document, constructionType) | 74 : Element(tagName, document, constructionType) |
52 { | 75 { |
53 ScriptWrappable::init(this); | 76 ScriptWrappable::init(this); |
77 registerAnimatedPropertiesForSVGElement(); | |
54 setHasCustomStyleCallbacks(); | 78 setHasCustomStyleCallbacks(); |
55 } | 79 } |
56 | 80 |
57 PassRefPtr<SVGElement> SVGElement::create(const QualifiedName& tagName, Document * document) | 81 PassRefPtr<SVGElement> SVGElement::create(const QualifiedName& tagName, Document * document) |
58 { | 82 { |
59 return adoptRef(new SVGElement(tagName, document)); | 83 return adoptRef(new SVGElement(tagName, document)); |
60 } | 84 } |
61 | 85 |
62 SVGElement::~SVGElement() | 86 SVGElement::~SVGElement() |
63 { | 87 { |
(...skipping 11 matching lines...) Expand all Loading... | |
75 cursorElement->removeClient(this); | 99 cursorElement->removeClient(this); |
76 if (CSSCursorImageValue* cursorImageValue = rareData->cursorImageValue() ) | 100 if (CSSCursorImageValue* cursorImageValue = rareData->cursorImageValue() ) |
77 cursorImageValue->removeReferencedElement(this); | 101 cursorImageValue->removeReferencedElement(this); |
78 | 102 |
79 delete rareData; | 103 delete rareData; |
80 | 104 |
81 // The rare data cleanup may have caused other SVG nodes to be deleted, | 105 // The rare data cleanup may have caused other SVG nodes to be deleted, |
82 // modifying the rare data map. Do not rely on the existing iterator. | 106 // modifying the rare data map. Do not rely on the existing iterator. |
83 ASSERT(rareDataMap.contains(this)); | 107 ASSERT(rareDataMap.contains(this)); |
84 rareDataMap.remove(this); | 108 rareDataMap.remove(this); |
109 // Clear HasSVGRareData flag now so that we are in a consistent state wh en | |
110 // calling rebuildAllElementReferencesForTarget() and | |
111 // removeAllElementReferencesForTarget() below. | |
112 clearHasSVGRareData(); | |
85 } | 113 } |
86 ASSERT(document()); | 114 ASSERT(document()); |
87 document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget(this ); | 115 document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget(this ); |
88 document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this) ; | 116 document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this) ; |
89 } | 117 } |
90 | 118 |
91 void SVGElement::willRecalcStyle(StyleChange change) | 119 void SVGElement::willRecalcStyle(StyleChange change) |
92 { | 120 { |
93 // FIXME: This assumes that when shouldNotifyRendererWithIdenticalStyles() i s true | 121 // FIXME: This assumes that when shouldNotifyRendererWithIdenticalStyles() i s true |
94 // the change came from a SMIL animation, but what if there were non-SMIL ch anges | 122 // the change came from a SMIL animation, but what if there were non-SMIL ch anges |
95 // since then? I think we should remove the shouldNotifyRendererWithIdentica lStyles | 123 // since then? I think we should remove the shouldNotifyRendererWithIdentica lStyles |
96 // check. | 124 // check. |
97 if (!hasSVGRareData() || shouldNotifyRendererWithIdenticalStyles()) | 125 if (!hasSVGRareData() || shouldNotifyRendererWithIdenticalStyles()) |
98 return; | 126 return; |
99 // If the style changes because of a regular property change (not induced by SMIL animations themselves) | 127 // If the style changes because of a regular property change (not induced by SMIL animations themselves) |
100 // reset the "computed style without SMIL style properties", so the base val ue change gets reflected. | 128 // reset the "computed style without SMIL style properties", so the base val ue change gets reflected. |
101 if (change > NoChange || needsStyleRecalc()) | 129 if (change > NoChange || needsStyleRecalc()) |
102 svgRareData()->setNeedsOverrideComputedStyleUpdate(); | 130 svgRareData()->setNeedsOverrideComputedStyleUpdate(); |
103 } | 131 } |
104 | 132 |
133 void SVGElement::buildPendingResourcesIfNeeded() | |
134 { | |
135 Document* document = this->document(); | |
136 if (!needsPendingResourceHandling() || !document || !inDocument() || isInSha dowTree()) | |
137 return; | |
138 | |
139 SVGDocumentExtensions* extensions = document->accessSVGExtensions(); | |
140 String resourceId = getIdAttribute(); | |
141 if (!extensions->hasPendingResource(resourceId)) | |
142 return; | |
143 | |
144 // Mark pending resources as pending for removal. | |
145 extensions->markPendingResourcesForRemoval(resourceId); | |
146 | |
147 // Rebuild pending resources for each client of a pending resource that is b eing removed. | |
148 while (Element* clientElement = extensions->removeElementFromPendingResource sForRemoval(resourceId)) { | |
149 ASSERT(clientElement->hasPendingResources()); | |
150 if (clientElement->hasPendingResources()) { | |
151 clientElement->buildPendingResource(); | |
152 extensions->clearHasPendingResourcesIfPossible(clientElement); | |
153 } | |
154 } | |
155 } | |
156 | |
157 bool SVGElement::rendererIsNeededInternal(const NodeRenderingContext& context) | |
do-not-use
2013/07/30 15:44:07
This is the tough part:
- SVGElement::rendererIsNe
| |
158 { | |
159 // http://www.w3.org/TR/SVG/extend.html#PrivateData | |
160 // Prevent anything other than SVG renderers from appearing in our render tr ee | |
161 // Spec: SVG allows inclusion of elements from foreign namespaces anywhere | |
162 // with the SVG content. In general, the SVG user agent will include the unk nown | |
163 // elements in the DOM but will otherwise ignore unknown elements. | |
164 if (!parentOrShadowHostElement() || parentOrShadowHostElement()->isSVGElemen t()) | |
165 return Element::rendererIsNeeded(context); | |
166 | |
167 return false; | |
168 } | |
169 | |
105 SVGElementRareData* SVGElement::svgRareData() const | 170 SVGElementRareData* SVGElement::svgRareData() const |
106 { | 171 { |
107 ASSERT(hasSVGRareData()); | 172 ASSERT(hasSVGRareData()); |
108 return SVGElementRareData::rareDataFromMap(this); | 173 return SVGElementRareData::rareDataFromMap(this); |
109 } | 174 } |
110 | 175 |
111 SVGElementRareData* SVGElement::ensureSVGRareData() | 176 SVGElementRareData* SVGElement::ensureSVGRareData() |
112 { | 177 { |
113 if (hasSVGRareData()) | 178 if (hasSVGRareData()) |
114 return svgRareData(); | 179 return svgRareData(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 | 228 |
164 ASSERT_NOT_REACHED(); | 229 ASSERT_NOT_REACHED(); |
165 } | 230 } |
166 | 231 |
167 | 232 |
168 bool SVGElement::isSupported(StringImpl* feature, StringImpl* version) const | 233 bool SVGElement::isSupported(StringImpl* feature, StringImpl* version) const |
169 { | 234 { |
170 return DOMImplementation::hasFeature(feature, version); | 235 return DOMImplementation::hasFeature(feature, version); |
171 } | 236 } |
172 | 237 |
238 String SVGElement::title() const | |
239 { | |
240 // According to spec, we should not return titles when hovering over root <s vg> elements (those | |
241 // <title> elements are the title of the document, not a tooltip) so we inst antly return. | |
242 if (isOutermostSVGSVGElement()) | |
243 return String(); | |
244 | |
245 // Walk up the tree, to find out whether we're inside a <use> shadow tree, t o find the right title. | |
246 if (isInShadowTree()) { | |
247 Element* shadowHostElement = toShadowRoot(treeScope()->rootNode())->host (); | |
248 // At this time, SVG nodes are not allowed in non-<use> shadow trees, so any shadow root we do | |
249 // have should be a use. The assert and following test is here to catch future shadow DOM changes | |
250 // that do enable SVG in a shadow tree. | |
251 ASSERT(!shadowHostElement || shadowHostElement->hasTagName(SVGNames::use Tag)); | |
252 if (shadowHostElement && shadowHostElement->hasTagName(SVGNames::useTag) ) { | |
253 SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowHostEl ement); | |
254 | |
255 // If the <use> title is not empty we found the title to use. | |
256 String useTitle(useElement->title()); | |
257 if (!useTitle.isEmpty()) | |
258 return useTitle; | |
259 } | |
260 } | |
261 | |
262 // If we aren't an instance in a <use> or the <use> title was not found, the n find the first | |
263 // <title> child of this element. | |
264 Element* titleElement = ElementTraversal::firstWithin(this); | |
265 for (; titleElement; titleElement = ElementTraversal::nextSkippingChildren(t itleElement, this)) { | |
266 if (titleElement->hasTagName(SVGNames::titleTag) && titleElement->isSVGE lement()) | |
267 break; | |
268 } | |
269 | |
270 // If a title child was found, return the text contents. | |
271 if (titleElement) | |
272 return titleElement->innerText(); | |
273 | |
274 // Otherwise return a null/empty string. | |
275 return String(); | |
276 } | |
277 | |
278 PassRefPtr<CSSValue> SVGElement::getPresentationAttribute(const String& name) | |
279 { | |
280 if (!hasAttributesWithoutUpdate()) | |
281 return 0; | |
282 | |
283 QualifiedName attributeName(nullAtom, name, nullAtom); | |
284 const Attribute* attr = getAttributeItem(attributeName); | |
285 if (!attr) | |
286 return 0; | |
287 | |
288 RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(SVGA ttributeMode); | |
289 CSSPropertyID propertyID = SVGElement::cssPropertyIdForSVGAttributeName(attr ->name()); | |
290 style->setProperty(propertyID, attr->value()); | |
291 RefPtr<CSSValue> cssValue = style->getPropertyCSSValue(propertyID); | |
292 return cssValue ? cssValue->cloneForCSSOM() : 0; | |
293 } | |
294 | |
295 bool SVGElement::isKnownAttribute(const QualifiedName& attrName) | |
296 { | |
297 return isIdAttributeName(attrName); | |
298 } | |
299 | |
300 bool SVGElement::instanceUpdatesBlocked() const | |
301 { | |
302 return hasSVGRareData() && svgRareData()->instanceUpdatesBlocked(); | |
303 } | |
304 | |
305 void SVGElement::setInstanceUpdatesBlocked(bool value) | |
306 { | |
307 if (hasSVGRareData()) | |
308 svgRareData()->setInstanceUpdatesBlocked(value); | |
309 } | |
310 | |
311 AffineTransform SVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope ) const | |
312 { | |
313 // To be overriden by SVGGraphicsElement (or as special case SVGTextElement and SVGPatternElement) | |
314 return AffineTransform(); | |
315 } | |
316 | |
173 String SVGElement::xmlbase() const | 317 String SVGElement::xmlbase() const |
174 { | 318 { |
175 return fastGetAttribute(XMLNames::baseAttr); | 319 return fastGetAttribute(XMLNames::baseAttr); |
176 } | 320 } |
177 | 321 |
178 void SVGElement::setXmlbase(const String& value) | 322 void SVGElement::setXmlbase(const String& value) |
179 { | 323 { |
180 setAttribute(XMLNames::baseAttr, value); | 324 setAttribute(XMLNames::baseAttr, value); |
181 } | 325 } |
182 | 326 |
327 Node::InsertionNotificationRequest SVGElement::insertedInto(ContainerNode* rootP arent) | |
328 { | |
329 Element::insertedInto(rootParent); | |
330 updateRelativeLengthsInformation(); | |
331 buildPendingResourcesIfNeeded(); | |
332 return InsertionDone; | |
333 } | |
334 | |
183 void SVGElement::removedFrom(ContainerNode* rootParent) | 335 void SVGElement::removedFrom(ContainerNode* rootParent) |
184 { | 336 { |
185 bool wasInDocument = rootParent->inDocument(); | 337 bool wasInDocument = rootParent->inDocument(); |
186 | 338 |
339 if (wasInDocument) | |
340 updateRelativeLengthsInformation(false, this); | |
341 | |
187 Element::removedFrom(rootParent); | 342 Element::removedFrom(rootParent); |
188 | 343 |
189 if (wasInDocument) { | 344 if (wasInDocument) { |
190 document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget( this); | 345 document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget( this); |
191 document()->accessSVGExtensions()->removeAllElementReferencesForTarget(t his); | 346 document()->accessSVGExtensions()->removeAllElementReferencesForTarget(t his); |
192 } | 347 } |
348 | |
349 SVGElementInstance::invalidateAllInstancesOfElement(this); | |
350 } | |
351 | |
352 void SVGElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) | |
353 { | |
354 Element::childrenChanged(changedByParser, beforeChange, afterChange, childCo untDelta); | |
355 | |
356 // Invalidate all SVGElementInstances associated with us. | |
357 if (!changedByParser) | |
358 SVGElementInstance::invalidateAllInstancesOfElement(this); | |
359 } | |
360 | |
361 CSSPropertyID SVGElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName) | |
362 { | |
363 if (!attrName.namespaceURI().isNull()) | |
364 return CSSPropertyInvalid; | |
365 | |
366 static HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap = 0; | |
367 if (!propertyNameToIdMap) { | |
368 propertyNameToIdMap = new HashMap<StringImpl*, CSSPropertyID>; | |
369 // This is a list of all base CSS and SVG CSS properties which are expos ed as SVG XML attributes | |
370 mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr); | |
371 mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr); | |
372 mapAttributeToCSSProperty(propertyNameToIdMap, buffered_renderingAttr); | |
373 mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr); | |
374 mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr); | |
375 mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr); | |
376 mapAttributeToCSSProperty(propertyNameToIdMap, SVGNames::colorAttr); | |
377 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr); | |
378 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filte rsAttr); | |
379 mapAttributeToCSSProperty(propertyNameToIdMap, color_profileAttr); | |
380 mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr); | |
381 mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr); | |
382 mapAttributeToCSSProperty(propertyNameToIdMap, SVGNames::directionAttr); | |
383 mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr); | |
384 mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr); | |
385 mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr); | |
386 mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr); | |
387 mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr); | |
388 mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr); | |
389 mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr); | |
390 mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr); | |
391 mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr); | |
392 mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr); | |
393 mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr); | |
394 mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr); | |
395 mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr); | |
396 mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr); | |
397 mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr); | |
398 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizon talAttr); | |
399 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_vertica lAttr); | |
400 mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr); | |
401 mapAttributeToCSSProperty(propertyNameToIdMap, kerningAttr); | |
402 mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr); | |
403 mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr); | |
404 mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr); | |
405 mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr); | |
406 mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr); | |
407 mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr); | |
408 mapAttributeToCSSProperty(propertyNameToIdMap, mask_typeAttr); | |
409 mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr); | |
410 mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr); | |
411 mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr); | |
412 mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr); | |
413 mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr); | |
414 mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr); | |
415 mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr); | |
416 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr); | |
417 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr); | |
418 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr); | |
419 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr); | |
420 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr); | |
421 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr); | |
422 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr); | |
423 mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr); | |
424 mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr); | |
425 mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr); | |
426 mapAttributeToCSSProperty(propertyNameToIdMap, transform_originAttr); | |
427 mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr); | |
428 mapAttributeToCSSProperty(propertyNameToIdMap, vector_effectAttr); | |
429 mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr); | |
430 mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr); | |
431 mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr); | |
432 } | |
433 | |
434 return propertyNameToIdMap->get(attrName.localName().impl()); | |
435 } | |
436 | |
437 void SVGElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGEl ement* element) | |
438 { | |
439 // If we're not yet in a document, this function will be called again from i nsertedInto(). Do nothing now. | |
440 if (!inDocument()) | |
441 return; | |
442 | |
443 // An element wants to notify us that its own relative lengths state changed . | |
444 // Register it in the relative length map, and register us in the parent rel ative length map. | |
445 // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree. | |
446 if (hasRelativeLengths) { | |
447 m_elementsWithRelativeLengths.add(element); | |
448 } else { | |
449 if (!m_elementsWithRelativeLengths.contains(element)) { | |
450 // We were never registered. Do nothing. | |
451 return; | |
452 } | |
453 | |
454 m_elementsWithRelativeLengths.remove(element); | |
455 } | |
456 | |
457 // Find first styled parent node, and notify it that we've changed our relat ive length state. | |
458 ContainerNode* node = parentNode(); | |
459 while (node) { | |
460 if (!node->isSVGElement()) | |
461 break; | |
462 | |
463 SVGElement* element = toSVGElement(node); | |
464 | |
465 // Register us in the parent element map. | |
466 element->updateRelativeLengthsInformation(hasRelativeLengths, this); | |
467 break; | |
468 } | |
193 } | 469 } |
194 | 470 |
195 SVGSVGElement* SVGElement::ownerSVGElement() const | 471 SVGSVGElement* SVGElement::ownerSVGElement() const |
196 { | 472 { |
197 ContainerNode* n = parentOrShadowHostNode(); | 473 ContainerNode* n = parentOrShadowHostNode(); |
198 while (n) { | 474 while (n) { |
199 if (n->hasTagName(SVGNames::svgTag)) | 475 if (n->hasTagName(SVGNames::svgTag)) |
200 return toSVGSVGElement(n); | 476 return toSVGSVGElement(n); |
201 | 477 |
202 n = n->parentOrShadowHostNode(); | 478 n = n->parentOrShadowHostNode(); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 else if (name == onmouseoverAttr) | 607 else if (name == onmouseoverAttr) |
332 setAttributeEventListener(eventNames().mouseoverEvent, createAttributeEv entListener(this, name, value)); | 608 setAttributeEventListener(eventNames().mouseoverEvent, createAttributeEv entListener(this, name, value)); |
333 else if (name == onmouseupAttr) | 609 else if (name == onmouseupAttr) |
334 setAttributeEventListener(eventNames().mouseupEvent, createAttributeEven tListener(this, name, value)); | 610 setAttributeEventListener(eventNames().mouseupEvent, createAttributeEven tListener(this, name, value)); |
335 else if (name == SVGNames::onfocusinAttr) | 611 else if (name == SVGNames::onfocusinAttr) |
336 setAttributeEventListener(eventNames().focusinEvent, createAttributeEven tListener(this, name, value)); | 612 setAttributeEventListener(eventNames().focusinEvent, createAttributeEven tListener(this, name, value)); |
337 else if (name == SVGNames::onfocusoutAttr) | 613 else if (name == SVGNames::onfocusoutAttr) |
338 setAttributeEventListener(eventNames().focusoutEvent, createAttributeEve ntListener(this, name, value)); | 614 setAttributeEventListener(eventNames().focusoutEvent, createAttributeEve ntListener(this, name, value)); |
339 else if (name == SVGNames::onactivateAttr) | 615 else if (name == SVGNames::onactivateAttr) |
340 setAttributeEventListener(eventNames().DOMActivateEvent, createAttribute EventListener(this, name, value)); | 616 setAttributeEventListener(eventNames().DOMActivateEvent, createAttribute EventListener(this, name, value)); |
341 else if (SVGLangSpace::parseAttribute(name, value)) { | 617 else if (name == HTMLNames::classAttr) { |
618 // SVG animation has currently requires special storage of values so we set | |
619 // the className here. svgAttributeChanged actually causes the resulting | |
620 // style updates (instead of Element::parseAttribute). We don't | |
621 // tell Element about the change to avoid parsing the class list twice | |
622 setClassNameBaseValue(value); | |
623 } else if (SVGLangSpace::parseAttribute(name, value)) { | |
342 } else | 624 } else |
343 Element::parseAttribute(name, value); | 625 Element::parseAttribute(name, value); |
344 } | 626 } |
345 | 627 |
628 typedef HashMap<QualifiedName, AnimatedPropertyType> AttributeToPropertyTypeMap; | |
629 static inline AttributeToPropertyTypeMap& cssPropertyToTypeMap() | |
630 { | |
631 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_cssPropertyMap, ()); | |
632 | |
633 if (!s_cssPropertyMap.isEmpty()) | |
634 return s_cssPropertyMap; | |
635 | |
636 // Fill the map for the first use. | |
637 s_cssPropertyMap.set(alignment_baselineAttr, AnimatedString); | |
638 s_cssPropertyMap.set(baseline_shiftAttr, AnimatedString); | |
639 s_cssPropertyMap.set(buffered_renderingAttr, AnimatedString); | |
640 s_cssPropertyMap.set(clipAttr, AnimatedRect); | |
641 s_cssPropertyMap.set(clip_pathAttr, AnimatedString); | |
642 s_cssPropertyMap.set(clip_ruleAttr, AnimatedString); | |
643 s_cssPropertyMap.set(SVGNames::colorAttr, AnimatedColor); | |
644 s_cssPropertyMap.set(color_interpolationAttr, AnimatedString); | |
645 s_cssPropertyMap.set(color_interpolation_filtersAttr, AnimatedString); | |
646 s_cssPropertyMap.set(color_profileAttr, AnimatedString); | |
647 s_cssPropertyMap.set(color_renderingAttr, AnimatedString); | |
648 s_cssPropertyMap.set(cursorAttr, AnimatedString); | |
649 s_cssPropertyMap.set(displayAttr, AnimatedString); | |
650 s_cssPropertyMap.set(dominant_baselineAttr, AnimatedString); | |
651 s_cssPropertyMap.set(fillAttr, AnimatedColor); | |
652 s_cssPropertyMap.set(fill_opacityAttr, AnimatedNumber); | |
653 s_cssPropertyMap.set(fill_ruleAttr, AnimatedString); | |
654 s_cssPropertyMap.set(filterAttr, AnimatedString); | |
655 s_cssPropertyMap.set(flood_colorAttr, AnimatedColor); | |
656 s_cssPropertyMap.set(flood_opacityAttr, AnimatedNumber); | |
657 s_cssPropertyMap.set(font_familyAttr, AnimatedString); | |
658 s_cssPropertyMap.set(font_sizeAttr, AnimatedLength); | |
659 s_cssPropertyMap.set(font_stretchAttr, AnimatedString); | |
660 s_cssPropertyMap.set(font_styleAttr, AnimatedString); | |
661 s_cssPropertyMap.set(font_variantAttr, AnimatedString); | |
662 s_cssPropertyMap.set(font_weightAttr, AnimatedString); | |
663 s_cssPropertyMap.set(image_renderingAttr, AnimatedString); | |
664 s_cssPropertyMap.set(kerningAttr, AnimatedLength); | |
665 s_cssPropertyMap.set(letter_spacingAttr, AnimatedLength); | |
666 s_cssPropertyMap.set(lighting_colorAttr, AnimatedColor); | |
667 s_cssPropertyMap.set(marker_endAttr, AnimatedString); | |
668 s_cssPropertyMap.set(marker_midAttr, AnimatedString); | |
669 s_cssPropertyMap.set(marker_startAttr, AnimatedString); | |
670 s_cssPropertyMap.set(maskAttr, AnimatedString); | |
671 s_cssPropertyMap.set(mask_typeAttr, AnimatedString); | |
672 s_cssPropertyMap.set(opacityAttr, AnimatedNumber); | |
673 s_cssPropertyMap.set(overflowAttr, AnimatedString); | |
674 s_cssPropertyMap.set(pointer_eventsAttr, AnimatedString); | |
675 s_cssPropertyMap.set(shape_renderingAttr, AnimatedString); | |
676 s_cssPropertyMap.set(stop_colorAttr, AnimatedColor); | |
677 s_cssPropertyMap.set(stop_opacityAttr, AnimatedNumber); | |
678 s_cssPropertyMap.set(strokeAttr, AnimatedColor); | |
679 s_cssPropertyMap.set(stroke_dasharrayAttr, AnimatedLengthList); | |
680 s_cssPropertyMap.set(stroke_dashoffsetAttr, AnimatedLength); | |
681 s_cssPropertyMap.set(stroke_linecapAttr, AnimatedString); | |
682 s_cssPropertyMap.set(stroke_linejoinAttr, AnimatedString); | |
683 s_cssPropertyMap.set(stroke_miterlimitAttr, AnimatedNumber); | |
684 s_cssPropertyMap.set(stroke_opacityAttr, AnimatedNumber); | |
685 s_cssPropertyMap.set(stroke_widthAttr, AnimatedLength); | |
686 s_cssPropertyMap.set(text_anchorAttr, AnimatedString); | |
687 s_cssPropertyMap.set(text_decorationAttr, AnimatedString); | |
688 s_cssPropertyMap.set(text_renderingAttr, AnimatedString); | |
689 s_cssPropertyMap.set(vector_effectAttr, AnimatedString); | |
690 s_cssPropertyMap.set(visibilityAttr, AnimatedString); | |
691 s_cssPropertyMap.set(word_spacingAttr, AnimatedLength); | |
692 return s_cssPropertyMap; | |
693 } | |
694 | |
346 void SVGElement::animatedPropertyTypeForAttribute(const QualifiedName& attribute Name, Vector<AnimatedPropertyType>& propertyTypes) | 695 void SVGElement::animatedPropertyTypeForAttribute(const QualifiedName& attribute Name, Vector<AnimatedPropertyType>& propertyTypes) |
347 { | 696 { |
348 localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName , propertyTypes); | 697 localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName , propertyTypes); |
698 if (!propertyTypes.isEmpty()) | |
699 return; | |
700 | |
701 AttributeToPropertyTypeMap& cssPropertyTypeMap = cssPropertyToTypeMap(); | |
702 if (cssPropertyTypeMap.contains(attributeName)) | |
703 propertyTypes.append(cssPropertyTypeMap.get(attributeName)); | |
704 } | |
705 | |
706 bool SVGElement::isAnimatableCSSProperty(const QualifiedName& attrName) | |
707 { | |
708 return cssPropertyToTypeMap().contains(attrName); | |
709 } | |
710 | |
711 bool SVGElement::isPresentationAttribute(const QualifiedName& name) const | |
712 { | |
713 return cssPropertyIdForSVGAttributeName(name) > 0; | |
714 } | |
715 | |
716 void SVGElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) | |
717 { | |
718 CSSPropertyID propertyID = cssPropertyIdForSVGAttributeName(name); | |
719 if (propertyID > 0) | |
720 addPropertyToPresentationAttributeStyle(style, propertyID, value); | |
349 } | 721 } |
350 | 722 |
351 bool SVGElement::haveLoadedRequiredResources() | 723 bool SVGElement::haveLoadedRequiredResources() |
352 { | 724 { |
353 Node* child = firstChild(); | 725 Node* child = firstChild(); |
354 while (child) { | 726 while (child) { |
355 if (child->isSVGElement() && !toSVGElement(child)->haveLoadedRequiredRes ources()) | 727 if (child->isSVGElement() && !toSVGElement(child)->haveLoadedRequiredRes ources()) |
356 return false; | 728 return false; |
357 child = child->nextSibling(); | 729 child = child->nextSibling(); |
358 } | 730 } |
359 return true; | 731 return true; |
360 } | 732 } |
361 | 733 |
362 static inline void collectInstancesForSVGElement(SVGElement* element, HashSet<SV GElementInstance*>& instances) | 734 static inline void collectInstancesForSVGElement(SVGElement* element, HashSet<SV GElementInstance*>& instances) |
363 { | 735 { |
364 ASSERT(element); | 736 ASSERT(element); |
365 if (element->containingShadowRoot()) | 737 if (element->containingShadowRoot()) |
366 return; | 738 return; |
367 | 739 |
368 if (!element->isSVGStyledElement()) | 740 ASSERT(!element->instanceUpdatesBlocked()); |
369 return; | |
370 | 741 |
371 SVGStyledElement* styledElement = toSVGStyledElement(element); | 742 instances = element->instancesForElement(); |
372 ASSERT(!styledElement->instanceUpdatesBlocked()); | |
373 | |
374 instances = styledElement->instancesForElement(); | |
375 } | 743 } |
376 | 744 |
377 bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<Even tListener> prpListener, bool useCapture) | 745 bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<Even tListener> prpListener, bool useCapture) |
378 { | 746 { |
379 RefPtr<EventListener> listener = prpListener; | 747 RefPtr<EventListener> listener = prpListener; |
380 | 748 |
381 // Add event listener to regular DOM element | 749 // Add event listener to regular DOM element |
382 if (!Node::addEventListener(eventType, listener, useCapture)) | 750 if (!Node::addEventListener(eventType, listener, useCapture)) |
383 return false; | 751 return false; |
384 | 752 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
550 | 918 |
551 if (isIdAttributeName(name)) | 919 if (isIdAttributeName(name)) |
552 document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget( this); | 920 document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget( this); |
553 | 921 |
554 // Changes to the style attribute are processed lazily (see Element::getAttr ibute() and related methods), | 922 // Changes to the style attribute are processed lazily (see Element::getAttr ibute() and related methods), |
555 // so we don't want changes to the style attribute to result in extra work h ere. | 923 // so we don't want changes to the style attribute to result in extra work h ere. |
556 if (name != HTMLNames::styleAttr) | 924 if (name != HTMLNames::styleAttr) |
557 svgAttributeChanged(name); | 925 svgAttributeChanged(name); |
558 } | 926 } |
559 | 927 |
928 void SVGElement::svgAttributeChanged(const QualifiedName& attrName) | |
929 { | |
930 CSSPropertyID propId = SVGElement::cssPropertyIdForSVGAttributeName(attrName ); | |
931 if (propId > 0) { | |
932 SVGElementInstance::invalidateAllInstancesOfElement(this); | |
933 return; | |
934 } | |
935 | |
936 if (attrName == HTMLNames::classAttr) { | |
937 classAttributeChanged(classNameCurrentValue()); | |
938 SVGElementInstance::invalidateAllInstancesOfElement(this); | |
939 return; | |
940 } | |
941 | |
942 if (isIdAttributeName(attrName)) { | |
943 RenderObject* object = renderer(); | |
944 // Notify resources about id changes, this is important as we cache reso urces by id in SVGDocumentExtensions | |
945 if (object && object->isSVGResourceContainer()) | |
946 object->toRenderSVGResourceContainer()->idChanged(); | |
947 if (inDocument()) | |
948 buildPendingResourcesIfNeeded(); | |
949 SVGElementInstance::invalidateAllInstancesOfElement(this); | |
950 return; | |
951 } | |
952 } | |
953 | |
560 void SVGElement::synchronizeAnimatedSVGAttribute(const QualifiedName& name) cons t | 954 void SVGElement::synchronizeAnimatedSVGAttribute(const QualifiedName& name) cons t |
561 { | 955 { |
562 if (!elementData() || !elementData()->m_animatedSVGAttributesAreDirty) | 956 if (!elementData() || !elementData()->m_animatedSVGAttributesAreDirty) |
563 return; | 957 return; |
564 | 958 |
565 SVGElement* nonConstThis = const_cast<SVGElement*>(this); | 959 SVGElement* nonConstThis = const_cast<SVGElement*>(this); |
566 if (name == anyQName()) { | 960 if (name == anyQName()) { |
567 nonConstThis->localAttributeToPropertyMap().synchronizeProperties(nonCon stThis); | 961 nonConstThis->localAttributeToPropertyMap().synchronizeProperties(nonCon stThis); |
568 elementData()->m_animatedSVGAttributesAreDirty = false; | 962 elementData()->m_animatedSVGAttributesAreDirty = false; |
569 } else | 963 } else |
570 nonConstThis->localAttributeToPropertyMap().synchronizeProperty(nonConst This, name); | 964 nonConstThis->localAttributeToPropertyMap().synchronizeProperty(nonConst This, name); |
571 } | 965 } |
572 | 966 |
573 SVGAttributeToPropertyMap& SVGElement::localAttributeToPropertyMap() const | |
574 { | |
575 DEFINE_STATIC_LOCAL(SVGAttributeToPropertyMap, emptyMap, ()); | |
576 return emptyMap; | |
577 } | |
578 | |
579 void SVGElement::synchronizeRequiredFeatures(SVGElement* contextElement) | 967 void SVGElement::synchronizeRequiredFeatures(SVGElement* contextElement) |
580 { | 968 { |
581 ASSERT(contextElement); | 969 ASSERT(contextElement); |
582 contextElement->synchronizeRequiredFeatures(); | 970 contextElement->synchronizeRequiredFeatures(); |
583 } | 971 } |
584 | 972 |
585 void SVGElement::synchronizeRequiredExtensions(SVGElement* contextElement) | 973 void SVGElement::synchronizeRequiredExtensions(SVGElement* contextElement) |
586 { | 974 { |
587 ASSERT(contextElement); | 975 ASSERT(contextElement); |
588 contextElement->synchronizeRequiredExtensions(); | 976 contextElement->synchronizeRequiredExtensions(); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 animatableAttributes.add(SVGNames::xAttr); | 1135 animatableAttributes.add(SVGNames::xAttr); |
748 animatableAttributes.add(SVGNames::xChannelSelectorAttr); | 1136 animatableAttributes.add(SVGNames::xChannelSelectorAttr); |
749 animatableAttributes.add(SVGNames::y1Attr); | 1137 animatableAttributes.add(SVGNames::y1Attr); |
750 animatableAttributes.add(SVGNames::y2Attr); | 1138 animatableAttributes.add(SVGNames::y2Attr); |
751 animatableAttributes.add(SVGNames::yAttr); | 1139 animatableAttributes.add(SVGNames::yAttr); |
752 animatableAttributes.add(SVGNames::yChannelSelectorAttr); | 1140 animatableAttributes.add(SVGNames::yChannelSelectorAttr); |
753 animatableAttributes.add(SVGNames::zAttr); | 1141 animatableAttributes.add(SVGNames::zAttr); |
754 } | 1142 } |
755 | 1143 |
756 if (name == classAttr) | 1144 if (name == classAttr) |
757 return isSVGStyledElement(); | 1145 return true; |
758 | 1146 |
759 return animatableAttributes.contains(name); | 1147 return animatableAttributes.contains(name); |
760 } | 1148 } |
761 #endif | 1149 #endif |
762 | 1150 |
763 } | 1151 } |
OLD | NEW |