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 |
| 3 * <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org> | 4 * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org> |
4 * Copyright (C) 2008 Apple Inc. All rights reserved. | 5 * Copyright (C) 2008 Apple Inc. All rights reserved. |
5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> | 6 * Copyright (C) 2008 Alp Toker <alp@atoker.com> |
6 * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> | 7 * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> |
7 * | 8 * |
8 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 11 * License as published by the Free Software Foundation; either |
11 * version 2 of the License, or (at your option) any later version. | 12 * version 2 of the License, or (at your option) any later version. |
12 * | 13 * |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 | 94 |
94 short SVGElement::tabIndex() const { | 95 short SVGElement::tabIndex() const { |
95 if (supportsFocus()) | 96 if (supportsFocus()) |
96 return Element::tabIndex(); | 97 return Element::tabIndex(); |
97 return -1; | 98 return -1; |
98 } | 99 } |
99 | 100 |
100 void SVGElement::willRecalcStyle(StyleRecalcChange change) { | 101 void SVGElement::willRecalcStyle(StyleRecalcChange change) { |
101 if (!hasSVGRareData()) | 102 if (!hasSVGRareData()) |
102 return; | 103 return; |
103 // If the style changes because of a regular property change (not induced by S
MIL animations themselves) | 104 // If the style changes because of a regular property change (not induced by |
104 // reset the "computed style without SMIL style properties", so the base value
change gets reflected. | 105 // SMIL animations themselves) reset the "computed style without SMIL style |
| 106 // properties", so the base value change gets reflected. |
105 if (change > NoChange || needsStyleRecalc()) | 107 if (change > NoChange || needsStyleRecalc()) |
106 svgRareData()->setNeedsOverrideComputedStyleUpdate(); | 108 svgRareData()->setNeedsOverrideComputedStyleUpdate(); |
107 } | 109 } |
108 | 110 |
109 void SVGElement::buildPendingResourcesIfNeeded() { | 111 void SVGElement::buildPendingResourcesIfNeeded() { |
110 Document& document = this->document(); | 112 Document& document = this->document(); |
111 if (!needsPendingResourceHandling() || !isConnected() || inUseShadowTree()) | 113 if (!needsPendingResourceHandling() || !isConnected() || inUseShadowTree()) |
112 return; | 114 return; |
113 | 115 |
114 SVGDocumentExtensions& extensions = document.accessSVGExtensions(); | 116 SVGDocumentExtensions& extensions = document.accessSVGExtensions(); |
115 AtomicString resourceId = getIdAttribute(); | 117 AtomicString resourceId = getIdAttribute(); |
116 if (!extensions.hasPendingResource(resourceId)) | 118 if (!extensions.hasPendingResource(resourceId)) |
117 return; | 119 return; |
118 | 120 |
119 // Mark pending resources as pending for removal. | 121 // Mark pending resources as pending for removal. |
120 extensions.markPendingResourcesForRemoval(resourceId); | 122 extensions.markPendingResourcesForRemoval(resourceId); |
121 | 123 |
122 // Rebuild pending resources for each client of a pending resource that is bei
ng removed. | 124 // Rebuild pending resources for each client of a pending resource that is |
| 125 // being removed. |
123 while ( | 126 while ( |
124 Element* clientElement = | 127 Element* clientElement = |
125 extensions.removeElementFromPendingResourcesForRemoval(resourceId)) { | 128 extensions.removeElementFromPendingResourcesForRemoval(resourceId)) { |
126 ASSERT(clientElement->hasPendingResources()); | 129 ASSERT(clientElement->hasPendingResources()); |
127 if (clientElement->hasPendingResources()) { | 130 if (clientElement->hasPendingResources()) { |
128 // FIXME: Ideally we'd always resolve pending resources async instead of i
nside | 131 // FIXME: Ideally we'd always resolve pending resources async instead of |
129 // insertedInto and svgAttributeChanged. For now we only do it for <use> s
ince | 132 // inside insertedInto and svgAttributeChanged. For now we only do it for |
130 // that would stamp out DOM. | 133 // <use> since that would stamp out DOM. |
131 if (isSVGUseElement(clientElement)) | 134 if (isSVGUseElement(clientElement)) |
132 toSVGUseElement(clientElement)->invalidateShadowTree(); | 135 toSVGUseElement(clientElement)->invalidateShadowTree(); |
133 else | 136 else |
134 clientElement->buildPendingResource(); | 137 clientElement->buildPendingResource(); |
135 extensions.clearHasPendingResourcesIfPossible(clientElement); | 138 extensions.clearHasPendingResourcesIfPossible(clientElement); |
136 } | 139 } |
137 } | 140 } |
138 } | 141 } |
139 | 142 |
140 SVGElementRareData* SVGElement::ensureSVGRareData() { | 143 SVGElementRareData* SVGElement::ensureSVGRareData() { |
141 if (hasSVGRareData()) | 144 if (hasSVGRareData()) |
142 return svgRareData(); | 145 return svgRareData(); |
143 | 146 |
144 m_SVGRareData = new SVGElementRareData(this); | 147 m_SVGRareData = new SVGElementRareData(this); |
145 return m_SVGRareData.get(); | 148 return m_SVGRareData.get(); |
146 } | 149 } |
147 | 150 |
148 bool SVGElement::isOutermostSVGSVGElement() const { | 151 bool SVGElement::isOutermostSVGSVGElement() const { |
149 if (!isSVGSVGElement(*this)) | 152 if (!isSVGSVGElement(*this)) |
150 return false; | 153 return false; |
151 | 154 |
152 // Element may not be in the document, pretend we're outermost for viewport(),
getCTM(), etc. | 155 // Element may not be in the document, pretend we're outermost for viewport(), |
| 156 // getCTM(), etc. |
153 if (!parentNode()) | 157 if (!parentNode()) |
154 return true; | 158 return true; |
155 | 159 |
156 // We act like an outermost SVG element, if we're a direct child of a <foreign
Object> element. | 160 // We act like an outermost SVG element, if we're a direct child of a |
| 161 // <foreignObject> element. |
157 if (isSVGForeignObjectElement(*parentNode())) | 162 if (isSVGForeignObjectElement(*parentNode())) |
158 return true; | 163 return true; |
159 | 164 |
160 // If we're living in a shadow tree, we're a <svg> element that got created as
replacement | 165 // If we're living in a shadow tree, we're a <svg> element that got created as |
161 // for a <symbol> element or a cloned <svg> element in the referenced tree. In
that case | 166 // replacement for a <symbol> element or a cloned <svg> element in the |
162 // we're always an inner <svg> element. | 167 // referenced tree. In that case we're always an inner <svg> element. |
163 if (inUseShadowTree() && parentOrShadowHostElement() && | 168 if (inUseShadowTree() && parentOrShadowHostElement() && |
164 parentOrShadowHostElement()->isSVGElement()) | 169 parentOrShadowHostElement()->isSVGElement()) |
165 return false; | 170 return false; |
166 | 171 |
167 // This is true whenever this is the outermost SVG, even if there are HTML ele
ments outside it | 172 // This is true whenever this is the outermost SVG, even if there are HTML |
| 173 // elements outside it |
168 return !parentNode()->isSVGElement(); | 174 return !parentNode()->isSVGElement(); |
169 } | 175 } |
170 | 176 |
171 void SVGElement::reportAttributeParsingError(SVGParsingError error, | 177 void SVGElement::reportAttributeParsingError(SVGParsingError error, |
172 const QualifiedName& name, | 178 const QualifiedName& name, |
173 const AtomicString& value) { | 179 const AtomicString& value) { |
174 if (error == SVGParseStatus::NoError) | 180 if (error == SVGParseStatus::NoError) |
175 return; | 181 return; |
176 // Don't report any errors on attribute removal. | 182 // Don't report any errors on attribute removal. |
177 if (value.isNull()) | 183 if (value.isNull()) |
178 return; | 184 return; |
179 document().accessSVGExtensions().reportError( | 185 document().accessSVGExtensions().reportError( |
180 error.format(tagName(), name, value)); | 186 error.format(tagName(), name, value)); |
181 } | 187 } |
182 | 188 |
183 String SVGElement::title() const { | 189 String SVGElement::title() const { |
184 // According to spec, we should not return titles when hovering over root <svg
> elements (those | 190 // According to spec, we should not return titles when hovering over root |
185 // <title> elements are the title of the document, not a tooltip) so we instan
tly return. | 191 // <svg> elements (those <title> elements are the title of the document, not a |
| 192 // tooltip) so we instantly return. |
186 if (isOutermostSVGSVGElement()) | 193 if (isOutermostSVGSVGElement()) |
187 return String(); | 194 return String(); |
188 | 195 |
189 if (inUseShadowTree()) { | 196 if (inUseShadowTree()) { |
190 String useTitle(ownerShadowHost()->title()); | 197 String useTitle(ownerShadowHost()->title()); |
191 if (!useTitle.isEmpty()) | 198 if (!useTitle.isEmpty()) |
192 return useTitle; | 199 return useTitle; |
193 } | 200 } |
194 | 201 |
195 // If we aren't an instance in a <use> or the <use> title was not found, then
find the first | 202 // If we aren't an instance in a <use> or the <use> title was not found, then |
196 // <title> child of this element. | 203 // find the first <title> child of this element. |
197 // If a title child was found, return the text contents. | 204 // If a title child was found, return the text contents. |
198 if (Element* titleElement = Traversal<SVGTitleElement>::firstChild(*this)) | 205 if (Element* titleElement = Traversal<SVGTitleElement>::firstChild(*this)) |
199 return titleElement->innerText(); | 206 return titleElement->innerText(); |
200 | 207 |
201 // Otherwise return a null/empty string. | 208 // Otherwise return a null/empty string. |
202 return String(); | 209 return String(); |
203 } | 210 } |
204 | 211 |
205 bool SVGElement::instanceUpdatesBlocked() const { | 212 bool SVGElement::instanceUpdatesBlocked() const { |
206 return hasSVGRareData() && svgRareData()->instanceUpdatesBlocked(); | 213 return hasSVGRareData() && svgRareData()->instanceUpdatesBlocked(); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 | 301 |
295 void SVGElement::clearAnimatedAttribute(const QualifiedName& attribute) { | 302 void SVGElement::clearAnimatedAttribute(const QualifiedName& attribute) { |
296 forSelfAndInstances(this, [&attribute](SVGElement* element) { | 303 forSelfAndInstances(this, [&attribute](SVGElement* element) { |
297 if (SVGAnimatedPropertyBase* animatedProperty = | 304 if (SVGAnimatedPropertyBase* animatedProperty = |
298 element->propertyFromAttribute(attribute)) | 305 element->propertyFromAttribute(attribute)) |
299 animatedProperty->animationEnded(); | 306 animatedProperty->animationEnded(); |
300 }); | 307 }); |
301 } | 308 } |
302 | 309 |
303 AffineTransform SVGElement::localCoordinateSpaceTransform(CTMScope) const { | 310 AffineTransform SVGElement::localCoordinateSpaceTransform(CTMScope) const { |
304 // To be overriden by SVGGraphicsElement (or as special case SVGTextElement an
d SVGPatternElement) | 311 // To be overriden by SVGGraphicsElement (or as special case SVGTextElement |
| 312 // and SVGPatternElement) |
305 return AffineTransform(); | 313 return AffineTransform(); |
306 } | 314 } |
307 | 315 |
308 Node::InsertionNotificationRequest SVGElement::insertedInto( | 316 Node::InsertionNotificationRequest SVGElement::insertedInto( |
309 ContainerNode* rootParent) { | 317 ContainerNode* rootParent) { |
310 Element::insertedInto(rootParent); | 318 Element::insertedInto(rootParent); |
311 updateRelativeLengthsInformation(); | 319 updateRelativeLengthsInformation(); |
312 buildPendingResourcesIfNeeded(); | 320 buildPendingResourcesIfNeeded(); |
313 return InsertionDone; | 321 return InsertionDone; |
314 } | 322 } |
315 | 323 |
316 void SVGElement::removedFrom(ContainerNode* rootParent) { | 324 void SVGElement::removedFrom(ContainerNode* rootParent) { |
317 bool wasInDocument = rootParent->isConnected(); | 325 bool wasInDocument = rootParent->isConnected(); |
318 | 326 |
319 if (wasInDocument && hasRelativeLengths()) { | 327 if (wasInDocument && hasRelativeLengths()) { |
320 // The root of the subtree being removed should take itself out from its par
ent's relative | 328 // The root of the subtree being removed should take itself out from its |
321 // length set. For the other nodes in the subtree we don't need to do anythi
ng: they will | 329 // parent's relative length set. For the other nodes in the subtree we don't |
322 // get their own removedFrom() notification and just clear their sets. | 330 // need to do anything: they will get their own removedFrom() notification |
| 331 // and just clear their sets. |
323 if (rootParent->isSVGElement() && !parentNode()) { | 332 if (rootParent->isSVGElement() && !parentNode()) { |
324 ASSERT(toSVGElement(rootParent) | 333 ASSERT(toSVGElement(rootParent) |
325 ->m_elementsWithRelativeLengths.contains(this)); | 334 ->m_elementsWithRelativeLengths.contains(this)); |
326 toSVGElement(rootParent)->updateRelativeLengthsInformation(false, this); | 335 toSVGElement(rootParent)->updateRelativeLengthsInformation(false, this); |
327 } | 336 } |
328 | 337 |
329 m_elementsWithRelativeLengths.clear(); | 338 m_elementsWithRelativeLengths.clear(); |
330 } | 339 } |
331 | 340 |
332 ASSERT_WITH_SECURITY_IMPLICATION( | 341 ASSERT_WITH_SECURITY_IMPLICATION( |
(...skipping 19 matching lines...) Expand all Loading... |
352 } | 361 } |
353 | 362 |
354 CSSPropertyID SVGElement::cssPropertyIdForSVGAttributeName( | 363 CSSPropertyID SVGElement::cssPropertyIdForSVGAttributeName( |
355 const QualifiedName& attrName) { | 364 const QualifiedName& attrName) { |
356 if (!attrName.namespaceURI().isNull()) | 365 if (!attrName.namespaceURI().isNull()) |
357 return CSSPropertyInvalid; | 366 return CSSPropertyInvalid; |
358 | 367 |
359 static HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap = 0; | 368 static HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap = 0; |
360 if (!propertyNameToIdMap) { | 369 if (!propertyNameToIdMap) { |
361 propertyNameToIdMap = new HashMap<StringImpl*, CSSPropertyID>; | 370 propertyNameToIdMap = new HashMap<StringImpl*, CSSPropertyID>; |
362 // This is a list of all base CSS and SVG CSS properties which are exposed a
s SVG XML attributes | 371 // This is a list of all base CSS and SVG CSS properties which are exposed |
| 372 // as SVG XML attributes |
363 const QualifiedName* const attrNames[] = { | 373 const QualifiedName* const attrNames[] = { |
364 &alignment_baselineAttr, | 374 &alignment_baselineAttr, |
365 &baseline_shiftAttr, | 375 &baseline_shiftAttr, |
366 &buffered_renderingAttr, | 376 &buffered_renderingAttr, |
367 &clipAttr, | 377 &clipAttr, |
368 &clip_pathAttr, | 378 &clip_pathAttr, |
369 &clip_ruleAttr, | 379 &clip_ruleAttr, |
370 &SVGNames::colorAttr, | 380 &SVGNames::colorAttr, |
371 &color_interpolationAttr, | 381 &color_interpolationAttr, |
372 &color_interpolation_filtersAttr, | 382 &color_interpolation_filtersAttr, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 } | 437 } |
428 } | 438 } |
429 | 439 |
430 return propertyNameToIdMap->get(attrName.localName().impl()); | 440 return propertyNameToIdMap->get(attrName.localName().impl()); |
431 } | 441 } |
432 | 442 |
433 void SVGElement::updateRelativeLengthsInformation(bool clientHasRelativeLengths, | 443 void SVGElement::updateRelativeLengthsInformation(bool clientHasRelativeLengths, |
434 SVGElement* clientElement) { | 444 SVGElement* clientElement) { |
435 ASSERT(clientElement); | 445 ASSERT(clientElement); |
436 | 446 |
437 // If we're not yet in a document, this function will be called again from ins
ertedInto(). Do nothing now. | 447 // If we're not yet in a document, this function will be called again from |
| 448 // insertedInto(). Do nothing now. |
438 if (!isConnected()) | 449 if (!isConnected()) |
439 return; | 450 return; |
440 | 451 |
441 // An element wants to notify us that its own relative lengths state changed. | 452 // An element wants to notify us that its own relative lengths state changed. |
442 // Register it in the relative length map, and register us in the parent relat
ive length map. | 453 // Register it in the relative length map, and register us in the parent |
443 // Register the parent in the grandparents map, etc. Repeat procedure until th
e root of the SVG tree. | 454 // relative length map. Register the parent in the grandparents map, etc. |
| 455 // Repeat procedure until the root of the SVG tree. |
444 for (Node& currentNode : NodeTraversal::inclusiveAncestorsOf(*this)) { | 456 for (Node& currentNode : NodeTraversal::inclusiveAncestorsOf(*this)) { |
445 if (!currentNode.isSVGElement()) | 457 if (!currentNode.isSVGElement()) |
446 break; | 458 break; |
447 SVGElement& currentElement = toSVGElement(currentNode); | 459 SVGElement& currentElement = toSVGElement(currentNode); |
448 ASSERT(!currentElement.m_inRelativeLengthClientsInvalidation); | 460 ASSERT(!currentElement.m_inRelativeLengthClientsInvalidation); |
449 | 461 |
450 bool hadRelativeLengths = currentElement.hasRelativeLengths(); | 462 bool hadRelativeLengths = currentElement.hasRelativeLengths(); |
451 if (clientHasRelativeLengths) | 463 if (clientHasRelativeLengths) |
452 currentElement.m_elementsWithRelativeLengths.add(clientElement); | 464 currentElement.m_elementsWithRelativeLengths.add(clientElement); |
453 else | 465 else |
454 currentElement.m_elementsWithRelativeLengths.remove(clientElement); | 466 currentElement.m_elementsWithRelativeLengths.remove(clientElement); |
455 | 467 |
456 // If the relative length state hasn't changed, we can stop propagating the
notification. | 468 // If the relative length state hasn't changed, we can stop propagating the |
| 469 // notification. |
457 if (hadRelativeLengths == currentElement.hasRelativeLengths()) | 470 if (hadRelativeLengths == currentElement.hasRelativeLengths()) |
458 return; | 471 return; |
459 | 472 |
460 clientElement = ¤tElement; | 473 clientElement = ¤tElement; |
461 clientHasRelativeLengths = clientElement->hasRelativeLengths(); | 474 clientHasRelativeLengths = clientElement->hasRelativeLengths(); |
462 } | 475 } |
463 | 476 |
464 // Register root SVG elements for top level viewport change notifications. | 477 // Register root SVG elements for top level viewport change notifications. |
465 if (isSVGSVGElement(*clientElement)) { | 478 if (isSVGSVGElement(*clientElement)) { |
466 SVGDocumentExtensions& svgExtensions = accessDocumentSVGExtensions(); | 479 SVGDocumentExtensions& svgExtensions = accessDocumentSVGExtensions(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 if (isSVGSVGElement(*n)) | 518 if (isSVGSVGElement(*n)) |
506 return toSVGSVGElement(n); | 519 return toSVGSVGElement(n); |
507 | 520 |
508 n = n->parentOrShadowHostNode(); | 521 n = n->parentOrShadowHostNode(); |
509 } | 522 } |
510 | 523 |
511 return nullptr; | 524 return nullptr; |
512 } | 525 } |
513 | 526 |
514 SVGElement* SVGElement::viewportElement() const { | 527 SVGElement* SVGElement::viewportElement() const { |
515 // This function needs shadow tree support - as LayoutSVGContainer uses this f
unction | 528 // This function needs shadow tree support - as LayoutSVGContainer uses this |
516 // to determine the "overflow" property. <use> on <symbol> wouldn't work other
whise. | 529 // function to determine the "overflow" property. <use> on <symbol> wouldn't |
| 530 // work otherwhise. |
517 ContainerNode* n = parentOrShadowHostNode(); | 531 ContainerNode* n = parentOrShadowHostNode(); |
518 while (n) { | 532 while (n) { |
519 if (isSVGSVGElement(*n) || isSVGImageElement(*n) || isSVGSymbolElement(*n)) | 533 if (isSVGSVGElement(*n) || isSVGImageElement(*n) || isSVGSymbolElement(*n)) |
520 return toSVGElement(n); | 534 return toSVGElement(n); |
521 | 535 |
522 n = n->parentOrShadowHostNode(); | 536 n = n->parentOrShadowHostNode(); |
523 } | 537 } |
524 | 538 |
525 return nullptr; | 539 return nullptr; |
526 } | 540 } |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 bool SVGElement::sendSVGLoadEventIfPossible() { | 836 bool SVGElement::sendSVGLoadEventIfPossible() { |
823 if (!haveLoadedRequiredResources()) | 837 if (!haveLoadedRequiredResources()) |
824 return false; | 838 return false; |
825 if ((isStructurallyExternal() || isSVGSVGElement(*this)) && | 839 if ((isStructurallyExternal() || isSVGSVGElement(*this)) && |
826 hasLoadListener(this)) | 840 hasLoadListener(this)) |
827 dispatchEvent(Event::create(EventTypeNames::load)); | 841 dispatchEvent(Event::create(EventTypeNames::load)); |
828 return true; | 842 return true; |
829 } | 843 } |
830 | 844 |
831 void SVGElement::sendSVGLoadEventToSelfAndAncestorChainIfPossible() { | 845 void SVGElement::sendSVGLoadEventToSelfAndAncestorChainIfPossible() { |
832 // Let Document::implicitClose() dispatch the 'load' to the outermost SVG root
. | 846 // Let Document::implicitClose() dispatch the 'load' to the outermost SVG |
| 847 // root. |
833 if (isOutermostSVGSVGElement()) | 848 if (isOutermostSVGSVGElement()) |
834 return; | 849 return; |
835 | 850 |
836 // Save the next parent to dispatch to in case dispatching the event mutates t
he tree. | 851 // Save the next parent to dispatch to in case dispatching the event mutates |
| 852 // the tree. |
837 Element* parent = parentOrShadowHostElement(); | 853 Element* parent = parentOrShadowHostElement(); |
838 if (!sendSVGLoadEventIfPossible()) | 854 if (!sendSVGLoadEventIfPossible()) |
839 return; | 855 return; |
840 | 856 |
841 // If document/window 'load' has been sent already, then only deliver to | 857 // If document/window 'load' has been sent already, then only deliver to |
842 // the element in question. | 858 // the element in question. |
843 if (document().loadEventFinished()) | 859 if (document().loadEventFinished()) |
844 return; | 860 return; |
845 | 861 |
846 if (!parent || !parent->isSVGElement()) | 862 if (!parent || !parent->isSVGElement()) |
847 return; | 863 return; |
848 | 864 |
849 toSVGElement(parent)->sendSVGLoadEventToSelfAndAncestorChainIfPossible(); | 865 toSVGElement(parent)->sendSVGLoadEventToSelfAndAncestorChainIfPossible(); |
850 } | 866 } |
851 | 867 |
852 void SVGElement::attributeChanged(const QualifiedName& name, | 868 void SVGElement::attributeChanged(const QualifiedName& name, |
853 const AtomicString& oldValue, | 869 const AtomicString& oldValue, |
854 const AtomicString& newValue, | 870 const AtomicString& newValue, |
855 AttributeModificationReason) { | 871 AttributeModificationReason) { |
856 Element::attributeChanged(name, oldValue, newValue); | 872 Element::attributeChanged(name, oldValue, newValue); |
857 | 873 |
858 if (name == HTMLNames::idAttr) | 874 if (name == HTMLNames::idAttr) |
859 rebuildAllIncomingReferences(); | 875 rebuildAllIncomingReferences(); |
860 | 876 |
861 // Changes to the style attribute are processed lazily (see Element::getAttrib
ute() and related methods), | 877 // Changes to the style attribute are processed lazily (see |
862 // so we don't want changes to the style attribute to result in extra work her
e. | 878 // Element::getAttribute() and related methods), so we don't want changes to |
| 879 // the style attribute to result in extra work here. |
863 if (name == HTMLNames::styleAttr) | 880 if (name == HTMLNames::styleAttr) |
864 return; | 881 return; |
865 | 882 |
866 svgAttributeBaseValChanged(name); | 883 svgAttributeBaseValChanged(name); |
867 } | 884 } |
868 | 885 |
869 void SVGElement::svgAttributeChanged(const QualifiedName& attrName) { | 886 void SVGElement::svgAttributeChanged(const QualifiedName& attrName) { |
870 CSSPropertyID propId = SVGElement::cssPropertyIdForSVGAttributeName(attrName); | 887 CSSPropertyID propId = SVGElement::cssPropertyIdForSVGAttributeName(attrName); |
871 if (propId > 0) { | 888 if (propId > 0) { |
872 invalidateInstances(); | 889 invalidateInstances(); |
873 return; | 890 return; |
874 } | 891 } |
875 | 892 |
876 if (attrName == HTMLNames::classAttr) { | 893 if (attrName == HTMLNames::classAttr) { |
877 classAttributeChanged(AtomicString(m_className->currentValue()->value())); | 894 classAttributeChanged(AtomicString(m_className->currentValue()->value())); |
878 invalidateInstances(); | 895 invalidateInstances(); |
879 return; | 896 return; |
880 } | 897 } |
881 | 898 |
882 if (attrName == HTMLNames::idAttr) { | 899 if (attrName == HTMLNames::idAttr) { |
883 LayoutObject* object = layoutObject(); | 900 LayoutObject* object = layoutObject(); |
884 // Notify resources about id changes, this is important as we cache resource
s by id in SVGDocumentExtensions | 901 // Notify resources about id changes, this is important as we cache |
| 902 // resources by id in SVGDocumentExtensions |
885 if (object && object->isSVGResourceContainer()) | 903 if (object && object->isSVGResourceContainer()) |
886 toLayoutSVGResourceContainer(object)->idChanged(); | 904 toLayoutSVGResourceContainer(object)->idChanged(); |
887 if (isConnected()) | 905 if (isConnected()) |
888 buildPendingResourcesIfNeeded(); | 906 buildPendingResourcesIfNeeded(); |
889 invalidateInstances(); | 907 invalidateInstances(); |
890 return; | 908 return; |
891 } | 909 } |
892 } | 910 } |
893 | 911 |
894 void SVGElement::svgAttributeBaseValChanged(const QualifiedName& attribute) { | 912 void SVGElement::svgAttributeBaseValChanged(const QualifiedName& attribute) { |
895 svgAttributeChanged(attribute); | 913 svgAttributeChanged(attribute); |
896 | 914 |
897 if (!hasSVGRareData() || svgRareData()->webAnimatedAttributes().isEmpty()) | 915 if (!hasSVGRareData() || svgRareData()->webAnimatedAttributes().isEmpty()) |
898 return; | 916 return; |
899 | 917 |
900 // TODO(alancutter): Only mark attributes as dirty if their animation depends
on the underlying value. | 918 // TODO(alancutter): Only mark attributes as dirty if their animation depends |
| 919 // on the underlying value. |
901 svgRareData()->setWebAnimatedAttributesDirty(true); | 920 svgRareData()->setWebAnimatedAttributesDirty(true); |
902 elementData()->m_animatedSVGAttributesAreDirty = true; | 921 elementData()->m_animatedSVGAttributesAreDirty = true; |
903 } | 922 } |
904 | 923 |
905 void SVGElement::ensureAttributeAnimValUpdated() { | 924 void SVGElement::ensureAttributeAnimValUpdated() { |
906 if (!RuntimeEnabledFeatures::webAnimationsSVGEnabled()) | 925 if (!RuntimeEnabledFeatures::webAnimationsSVGEnabled()) |
907 return; | 926 return; |
908 | 927 |
909 if ((hasSVGRareData() && svgRareData()->webAnimatedAttributesDirty()) || | 928 if ((hasSVGRareData() && svgRareData()->webAnimatedAttributesDirty()) || |
910 (elementAnimations() && | 929 (elementAnimations() && |
911 DocumentAnimations::needsAnimationTimingUpdate(document()))) { | 930 DocumentAnimations::needsAnimationTimingUpdate(document()))) { |
912 DocumentAnimations::updateAnimationTimingIfNeeded(document()); | 931 DocumentAnimations::updateAnimationTimingIfNeeded(document()); |
913 applyActiveWebAnimations(); | 932 applyActiveWebAnimations(); |
914 } | 933 } |
915 } | 934 } |
916 | 935 |
917 void SVGElement::synchronizeAnimatedSVGAttribute( | 936 void SVGElement::synchronizeAnimatedSVGAttribute( |
918 const QualifiedName& name) const { | 937 const QualifiedName& name) const { |
919 if (!elementData() || !elementData()->m_animatedSVGAttributesAreDirty) | 938 if (!elementData() || !elementData()->m_animatedSVGAttributesAreDirty) |
920 return; | 939 return; |
921 | 940 |
922 // We const_cast here because we have deferred baseVal mutation animation upda
tes to this point in time. | 941 // We const_cast here because we have deferred baseVal mutation animation |
| 942 // updates to this point in time. |
923 const_cast<SVGElement*>(this)->ensureAttributeAnimValUpdated(); | 943 const_cast<SVGElement*>(this)->ensureAttributeAnimValUpdated(); |
924 | 944 |
925 if (name == anyQName()) { | 945 if (name == anyQName()) { |
926 AttributeToPropertyMap::const_iterator::ValuesIterator it = | 946 AttributeToPropertyMap::const_iterator::ValuesIterator it = |
927 m_attributeToPropertyMap.values().begin(); | 947 m_attributeToPropertyMap.values().begin(); |
928 AttributeToPropertyMap::const_iterator::ValuesIterator end = | 948 AttributeToPropertyMap::const_iterator::ValuesIterator end = |
929 m_attributeToPropertyMap.values().end(); | 949 m_attributeToPropertyMap.values().end(); |
930 for (; it != end; ++it) { | 950 for (; it != end; ++it) { |
931 if ((*it)->needsSynchronizeAttribute()) | 951 if ((*it)->needsSynchronizeAttribute()) |
932 (*it)->synchronizeAttribute(); | 952 (*it)->synchronizeAttribute(); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 return; | 1185 return; |
1166 | 1186 |
1167 const SVGElementSet& incomingReferences = svgRareData()->incomingReferences(); | 1187 const SVGElementSet& incomingReferences = svgRareData()->incomingReferences(); |
1168 | 1188 |
1169 // Iterate on a snapshot as |incomingReferences| may be altered inside loop. | 1189 // Iterate on a snapshot as |incomingReferences| may be altered inside loop. |
1170 HeapVector<Member<SVGElement>> incomingReferencesSnapshot; | 1190 HeapVector<Member<SVGElement>> incomingReferencesSnapshot; |
1171 copyToVector(incomingReferences, incomingReferencesSnapshot); | 1191 copyToVector(incomingReferences, incomingReferencesSnapshot); |
1172 | 1192 |
1173 // Force rebuilding the |sourceElement| so it knows about this change. | 1193 // Force rebuilding the |sourceElement| so it knows about this change. |
1174 for (SVGElement* sourceElement : incomingReferencesSnapshot) { | 1194 for (SVGElement* sourceElement : incomingReferencesSnapshot) { |
1175 // Before rebuilding |sourceElement| ensure it was not removed from under us
. | 1195 // Before rebuilding |sourceElement| ensure it was not removed from under |
| 1196 // us. |
1176 if (incomingReferences.contains(sourceElement)) | 1197 if (incomingReferences.contains(sourceElement)) |
1177 sourceElement->svgAttributeChanged(SVGNames::hrefAttr); | 1198 sourceElement->svgAttributeChanged(SVGNames::hrefAttr); |
1178 } | 1199 } |
1179 } | 1200 } |
1180 | 1201 |
1181 void SVGElement::removeAllIncomingReferences() { | 1202 void SVGElement::removeAllIncomingReferences() { |
1182 if (!hasSVGRareData()) | 1203 if (!hasSVGRareData()) |
1183 return; | 1204 return; |
1184 | 1205 |
1185 SVGElementSet& incomingReferences = svgRareData()->incomingReferences(); | 1206 SVGElementSet& incomingReferences = svgRareData()->incomingReferences(); |
(...skipping 23 matching lines...) Expand all Loading... |
1209 visitor->trace(m_className); | 1230 visitor->trace(m_className); |
1210 Element::trace(visitor); | 1231 Element::trace(visitor); |
1211 } | 1232 } |
1212 | 1233 |
1213 const AtomicString& SVGElement::eventParameterName() { | 1234 const AtomicString& SVGElement::eventParameterName() { |
1214 DEFINE_STATIC_LOCAL(const AtomicString, evtString, ("evt")); | 1235 DEFINE_STATIC_LOCAL(const AtomicString, evtString, ("evt")); |
1215 return evtString; | 1236 return evtString; |
1216 } | 1237 } |
1217 | 1238 |
1218 } // namespace blink | 1239 } // namespace blink |
OLD | NEW |