Chromium Code Reviews| 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 |