Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann |
| 3 * <zimmermann@kde.org> | 3 * <zimmermann@kde.org> |
| 4 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 4 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
| 5 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| 6 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 6 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 7 * Copyright (C) 2012 University of Szeged | 7 * Copyright (C) 2012 University of Szeged |
| 8 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> | 8 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 62 SVGAnimatedLength::create(this, | 62 SVGAnimatedLength::create(this, |
| 63 SVGNames::widthAttr, | 63 SVGNames::widthAttr, |
| 64 SVGLength::create(SVGLengthMode::Width))), | 64 SVGLength::create(SVGLengthMode::Width))), |
| 65 m_height( | 65 m_height( |
| 66 SVGAnimatedLength::create(this, | 66 SVGAnimatedLength::create(this, |
| 67 SVGNames::heightAttr, | 67 SVGNames::heightAttr, |
| 68 SVGLength::create(SVGLengthMode::Height))), | 68 SVGLength::create(SVGLengthMode::Height))), |
| 69 m_elementIdentifierIsLocal(true), | 69 m_elementIdentifierIsLocal(true), |
| 70 m_haveFiredLoadEvent(false), | 70 m_haveFiredLoadEvent(false), |
| 71 m_needsShadowTreeRecreation(false) { | 71 m_needsShadowTreeRecreation(false) { |
| 72 ASSERT(hasCustomStyleCallbacks()); | 72 DCHECK(hasCustomStyleCallbacks()); |
| 73 | 73 |
| 74 addToPropertyMap(m_x); | 74 addToPropertyMap(m_x); |
| 75 addToPropertyMap(m_y); | 75 addToPropertyMap(m_y); |
| 76 addToPropertyMap(m_width); | 76 addToPropertyMap(m_width); |
| 77 addToPropertyMap(m_height); | 77 addToPropertyMap(m_height); |
| 78 } | 78 } |
| 79 | 79 |
| 80 SVGUseElement* SVGUseElement::create(Document& document) { | 80 SVGUseElement* SVGUseElement::create(Document& document) { |
| 81 // Always build a user agent #shadow-root for SVGUseElement. | 81 // Always build a user agent #shadow-root for SVGUseElement. |
| 82 SVGUseElement* use = new SVGUseElement(document); | 82 SVGUseElement* use = new SVGUseElement(document); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 111 } | 111 } |
| 112 #endif | 112 #endif |
| 113 | 113 |
| 114 Node::InsertionNotificationRequest SVGUseElement::insertedInto( | 114 Node::InsertionNotificationRequest SVGUseElement::insertedInto( |
| 115 ContainerNode* rootParent) { | 115 ContainerNode* rootParent) { |
| 116 // This functions exists to assure assumptions made in the code regarding | 116 // This functions exists to assure assumptions made in the code regarding |
| 117 // SVGElementInstance creation/destruction are satisfied. | 117 // SVGElementInstance creation/destruction are satisfied. |
| 118 SVGGraphicsElement::insertedInto(rootParent); | 118 SVGGraphicsElement::insertedInto(rootParent); |
| 119 if (!rootParent->isConnected()) | 119 if (!rootParent->isConnected()) |
| 120 return InsertionDone; | 120 return InsertionDone; |
| 121 ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document())); | 121 #if DCHECK_IS_ON() |
| 122 ASSERT(!hasPendingResources() || !isWellFormedDocument(&document())); | 122 DCHECK(!m_targetElementInstance || !isWellFormedDocument(&document())); |
| 123 DCHECK(!hasPendingResources() || !isWellFormedDocument(&document())); | |
| 124 #endif | |
| 123 invalidateShadowTree(); | 125 invalidateShadowTree(); |
| 124 return InsertionDone; | 126 return InsertionDone; |
| 125 } | 127 } |
| 126 | 128 |
| 127 void SVGUseElement::removedFrom(ContainerNode* rootParent) { | 129 void SVGUseElement::removedFrom(ContainerNode* rootParent) { |
| 128 SVGGraphicsElement::removedFrom(rootParent); | 130 SVGGraphicsElement::removedFrom(rootParent); |
| 129 if (rootParent->isConnected()) { | 131 if (rootParent->isConnected()) { |
| 130 clearResourceReference(); | 132 clearResourceReference(); |
| 131 cancelShadowTreeRecreation(); | 133 cancelShadowTreeRecreation(); |
| 132 } | 134 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 SVGElement::InvalidationGuard invalidationGuard(this); | 220 SVGElement::InvalidationGuard invalidationGuard(this); |
| 219 | 221 |
| 220 if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr) { | 222 if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr) { |
| 221 invalidateSVGPresentationAttributeStyle(); | 223 invalidateSVGPresentationAttributeStyle(); |
| 222 setNeedsStyleRecalc(LocalStyleChange, | 224 setNeedsStyleRecalc(LocalStyleChange, |
| 223 StyleChangeReasonForTracing::fromAttribute(attrName)); | 225 StyleChangeReasonForTracing::fromAttribute(attrName)); |
| 224 } | 226 } |
| 225 | 227 |
| 226 updateRelativeLengthsInformation(); | 228 updateRelativeLengthsInformation(); |
| 227 if (m_targetElementInstance) { | 229 if (m_targetElementInstance) { |
| 228 ASSERT(m_targetElementInstance->correspondingElement()); | 230 DCHECK(m_targetElementInstance->correspondingElement()); |
| 229 transferUseWidthAndHeightIfNeeded( | 231 transferUseWidthAndHeightIfNeeded( |
| 230 *this, *m_targetElementInstance, | 232 *this, *m_targetElementInstance, |
| 231 *m_targetElementInstance->correspondingElement()); | 233 *m_targetElementInstance->correspondingElement()); |
| 232 } | 234 } |
| 233 | 235 |
| 234 LayoutObject* object = this->layoutObject(); | 236 LayoutObject* object = this->layoutObject(); |
| 235 if (object) | 237 if (object) |
| 236 markForLayoutAndParentResourceInvalidation(object); | 238 markForLayoutAndParentResourceInvalidation(object); |
| 237 return; | 239 return; |
| 238 } | 240 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 cancelShadowTreeRecreation(); | 318 cancelShadowTreeRecreation(); |
| 317 if (!isConnected()) | 319 if (!isConnected()) |
| 318 return; | 320 return; |
| 319 Element* target = resolveTargetElement(); | 321 Element* target = resolveTargetElement(); |
| 320 // TODO(fs): Why would the Element not be "connected" at this point? | 322 // TODO(fs): Why would the Element not be "connected" at this point? |
| 321 if (target && target->isConnected() && target->isSVGElement()) { | 323 if (target && target->isConnected() && target->isSVGElement()) { |
| 322 buildShadowAndInstanceTree(toSVGElement(*target)); | 324 buildShadowAndInstanceTree(toSVGElement(*target)); |
| 323 invalidateDependentShadowTrees(); | 325 invalidateDependentShadowTrees(); |
| 324 } | 326 } |
| 325 | 327 |
| 326 ASSERT(!m_needsShadowTreeRecreation); | 328 DCHECK(!m_needsShadowTreeRecreation); |
| 327 } | 329 } |
| 328 | 330 |
| 329 String SVGUseElement::title() const { | 331 String SVGUseElement::title() const { |
| 330 // Find the first <title> child in <use> which doesn't cover shadow tree. | 332 // Find the first <title> child in <use> which doesn't cover shadow tree. |
| 331 if (Element* titleElement = Traversal<SVGTitleElement>::firstChild(*this)) | 333 if (Element* titleElement = Traversal<SVGTitleElement>::firstChild(*this)) |
| 332 return titleElement->innerText(); | 334 return titleElement->innerText(); |
| 333 | 335 |
| 334 // If there is no <title> child in <use>, we lookup first <title> child in | 336 // If there is no <title> child in <use>, we lookup first <title> child in |
| 335 // shadow tree. | 337 // shadow tree. |
| 336 if (m_targetElementInstance) { | 338 if (m_targetElementInstance) { |
| 337 if (Element* titleElement = | 339 if (Element* titleElement = |
| 338 Traversal<SVGTitleElement>::firstChild(*m_targetElementInstance)) | 340 Traversal<SVGTitleElement>::firstChild(*m_targetElementInstance)) |
| 339 return titleElement->innerText(); | 341 return titleElement->innerText(); |
| 340 } | 342 } |
| 341 // Otherwise return a null string. | 343 // Otherwise return a null string. |
| 342 return String(); | 344 return String(); |
| 343 } | 345 } |
| 344 | 346 |
| 345 static void associateCorrespondingElements(SVGElement& targetRoot, | 347 static void associateCorrespondingElements(SVGElement& targetRoot, |
| 346 SVGElement& instanceRoot) { | 348 SVGElement& instanceRoot) { |
| 347 auto targetRange = Traversal<SVGElement>::inclusiveDescendantsOf(targetRoot); | 349 auto targetRange = Traversal<SVGElement>::inclusiveDescendantsOf(targetRoot); |
| 348 auto targetIterator = targetRange.begin(); | 350 auto targetIterator = targetRange.begin(); |
| 349 for (SVGElement& instance : | 351 for (SVGElement& instance : |
| 350 Traversal<SVGElement>::inclusiveDescendantsOf(instanceRoot)) { | 352 Traversal<SVGElement>::inclusiveDescendantsOf(instanceRoot)) { |
| 351 ASSERT(!instance.correspondingElement()); | 353 DCHECK(!instance.correspondingElement()); |
| 352 instance.setCorrespondingElement(&*targetIterator); | 354 instance.setCorrespondingElement(&*targetIterator); |
| 353 ++targetIterator; | 355 ++targetIterator; |
| 354 } | 356 } |
| 355 ASSERT(!(targetIterator != targetRange.end())); | 357 DCHECK(!(targetIterator != targetRange.end())); |
|
tkent
2017/03/14 22:33:14
Use DCHECK_EQ if possible.
mrunal
2017/03/14 23:52:14
It throws an error,
../../base/logging.h:703:26: e
| |
| 356 } | 358 } |
| 357 | 359 |
| 358 // We don't walk the target tree element-by-element, and clone each element, | 360 // We don't walk the target tree element-by-element, and clone each element, |
| 359 // but instead use cloneNode(deep=true). This is an optimization for the common | 361 // but instead use cloneNode(deep=true). This is an optimization for the common |
| 360 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>). | 362 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>). |
| 361 // Though if there are disallowed elements in the subtree, we have to remove | 363 // Though if there are disallowed elements in the subtree, we have to remove |
| 362 // them. For instance: <use> on <g> containing <foreignObject> (indirect | 364 // them. For instance: <use> on <g> containing <foreignObject> (indirect |
| 363 // case). | 365 // case). |
| 364 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) { | 366 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) { |
| 365 ASSERT(!subtree.isConnected()); | 367 DCHECK(!subtree.isConnected()); |
| 366 Element* element = ElementTraversal::firstWithin(subtree); | 368 Element* element = ElementTraversal::firstWithin(subtree); |
| 367 while (element) { | 369 while (element) { |
| 368 if (isDisallowedElement(*element)) { | 370 if (isDisallowedElement(*element)) { |
| 369 Element* next = | 371 Element* next = |
| 370 ElementTraversal::nextSkippingChildren(*element, &subtree); | 372 ElementTraversal::nextSkippingChildren(*element, &subtree); |
| 371 // The subtree is not in document so this won't generate events that could | 373 // The subtree is not in document so this won't generate events that could |
| 372 // mutate the tree. | 374 // mutate the tree. |
| 373 element->parentNode()->removeChild(element); | 375 element->parentNode()->removeChild(element); |
| 374 element = next; | 376 element = next; |
| 375 } else { | 377 } else { |
| 376 element = ElementTraversal::next(*element, &subtree); | 378 element = ElementTraversal::next(*element, &subtree); |
| 377 } | 379 } |
| 378 } | 380 } |
| 379 } | 381 } |
| 380 | 382 |
| 381 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, | 383 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, |
| 382 ContainerNode& destinationRoot) { | 384 ContainerNode& destinationRoot) { |
| 383 for (Node* child = sourceRoot.firstChild(); child;) { | 385 for (Node* child = sourceRoot.firstChild(); child;) { |
| 384 Node* nextChild = child->nextSibling(); | 386 Node* nextChild = child->nextSibling(); |
| 385 destinationRoot.appendChild(child); | 387 destinationRoot.appendChild(child); |
| 386 child = nextChild; | 388 child = nextChild; |
| 387 } | 389 } |
| 388 } | 390 } |
| 389 | 391 |
| 390 Element* SVGUseElement::createInstanceTree(SVGElement& targetRoot) const { | 392 Element* SVGUseElement::createInstanceTree(SVGElement& targetRoot) const { |
| 391 Element* instanceRoot = targetRoot.cloneElementWithChildren(); | 393 Element* instanceRoot = targetRoot.cloneElementWithChildren(); |
| 392 ASSERT(instanceRoot->isSVGElement()); | 394 DCHECK(instanceRoot->isSVGElement()); |
| 393 if (isSVGSymbolElement(targetRoot)) { | 395 if (isSVGSymbolElement(targetRoot)) { |
| 394 // Spec: The referenced 'symbol' and its contents are deep-cloned into | 396 // Spec: The referenced 'symbol' and its contents are deep-cloned into |
| 395 // the generated tree, with the exception that the 'symbol' is replaced | 397 // the generated tree, with the exception that the 'symbol' is replaced |
| 396 // by an 'svg'. This generated 'svg' will always have explicit values | 398 // by an 'svg'. This generated 'svg' will always have explicit values |
| 397 // for attributes width and height. If attributes width and/or height | 399 // for attributes width and height. If attributes width and/or height |
| 398 // are provided on the 'use' element, then these attributes will be | 400 // are provided on the 'use' element, then these attributes will be |
| 399 // transferred to the generated 'svg'. If attributes width and/or | 401 // transferred to the generated 'svg'. If attributes width and/or |
| 400 // height are not specified, the generated 'svg' element will use | 402 // height are not specified, the generated 'svg' element will use |
| 401 // values of 100% for these attributes. | 403 // values of 100% for these attributes. |
| 402 SVGSVGElement* svgElement = SVGSVGElement::create(targetRoot.document()); | 404 SVGSVGElement* svgElement = SVGSVGElement::create(targetRoot.document()); |
| 403 // Transfer all data (attributes, etc.) from the <symbol> to the new | 405 // Transfer all data (attributes, etc.) from the <symbol> to the new |
| 404 // <svg> element. | 406 // <svg> element. |
| 405 svgElement->cloneDataFromElement(*instanceRoot); | 407 svgElement->cloneDataFromElement(*instanceRoot); |
| 406 // Move already cloned elements to the new <svg> element. | 408 // Move already cloned elements to the new <svg> element. |
| 407 moveChildrenToReplacementElement(*instanceRoot, *svgElement); | 409 moveChildrenToReplacementElement(*instanceRoot, *svgElement); |
| 408 instanceRoot = svgElement; | 410 instanceRoot = svgElement; |
| 409 } | 411 } |
| 410 transferUseWidthAndHeightIfNeeded(*this, toSVGElement(*instanceRoot), | 412 transferUseWidthAndHeightIfNeeded(*this, toSVGElement(*instanceRoot), |
| 411 targetRoot); | 413 targetRoot); |
| 412 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); | 414 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); |
| 413 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); | 415 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); |
| 414 return instanceRoot; | 416 return instanceRoot; |
| 415 } | 417 } |
| 416 | 418 |
| 417 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) { | 419 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) { |
| 418 ASSERT(!m_targetElementInstance); | 420 DCHECK(!m_targetElementInstance); |
| 419 ASSERT(!m_needsShadowTreeRecreation); | 421 DCHECK(!m_needsShadowTreeRecreation); |
| 420 | 422 |
| 421 // <use> creates a "user agent" shadow root. Do not build the shadow/instance | 423 // <use> creates a "user agent" shadow root. Do not build the shadow/instance |
| 422 // tree for <use> elements living in a user agent shadow tree because they | 424 // tree for <use> elements living in a user agent shadow tree because they |
| 423 // will get expanded in a second pass -- see expandUseElementsInShadowTree(). | 425 // will get expanded in a second pass -- see expandUseElementsInShadowTree(). |
| 424 if (inUseShadowTree()) | 426 if (inUseShadowTree()) |
| 425 return; | 427 return; |
| 426 | 428 |
| 427 // Do not allow self-referencing. | 429 // Do not allow self-referencing. |
| 428 if (&target == this || isDisallowedElement(target)) | 430 if (&target == this || isDisallowedElement(target)) |
| 429 return; | 431 return; |
| 430 | 432 |
| 431 // Set up root SVG element in shadow tree. | 433 // Set up root SVG element in shadow tree. |
| 432 // Clone the target subtree into the shadow tree, not handling <use> and | 434 // Clone the target subtree into the shadow tree, not handling <use> and |
| 433 // <symbol> yet. | 435 // <symbol> yet. |
| 434 Element* instanceRoot = createInstanceTree(target); | 436 Element* instanceRoot = createInstanceTree(target); |
| 435 m_targetElementInstance = toSVGElement(instanceRoot); | 437 m_targetElementInstance = toSVGElement(instanceRoot); |
| 436 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); | 438 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
| 437 shadowTreeRootElement->appendChild(instanceRoot); | 439 shadowTreeRootElement->appendChild(instanceRoot); |
| 438 | 440 |
| 439 addReferencesToFirstDegreeNestedUseElements(target); | 441 addReferencesToFirstDegreeNestedUseElements(target); |
| 440 | 442 |
| 441 if (instanceTreeIsLoading()) | 443 if (instanceTreeIsLoading()) |
| 442 return; | 444 return; |
| 443 | 445 |
| 444 // Assure shadow tree building was successful. | 446 // Assure shadow tree building was successful. |
| 445 ASSERT(m_targetElementInstance); | 447 DCHECK(m_targetElementInstance); |
| 446 ASSERT(m_targetElementInstance->correspondingUseElement() == this); | 448 DCHECK_EQ(m_targetElementInstance->correspondingUseElement(), this); |
| 447 ASSERT(m_targetElementInstance->correspondingElement() == &target); | 449 DCHECK_EQ(m_targetElementInstance->correspondingElement(), &target); |
| 448 | 450 |
| 449 // Expand all <use> elements in the shadow tree. | 451 // Expand all <use> elements in the shadow tree. |
| 450 // Expand means: replace the actual <use> element by what it references. | 452 // Expand means: replace the actual <use> element by what it references. |
| 451 if (!expandUseElementsInShadowTree()) { | 453 if (!expandUseElementsInShadowTree()) { |
| 452 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); | 454 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); |
| 453 clearResourceReference(); | 455 clearResourceReference(); |
| 454 return; | 456 return; |
| 455 } | 457 } |
| 456 | 458 |
| 457 // If the instance root was a <use>, it could have been replaced now, so | 459 // If the instance root was a <use>, it could have been replaced now, so |
| 458 // reset |m_targetElementInstance|. | 460 // reset |m_targetElementInstance|. |
| 459 m_targetElementInstance = | 461 m_targetElementInstance = |
| 460 toSVGElementOrDie(shadowTreeRootElement->firstChild()); | 462 toSVGElementOrDie(shadowTreeRootElement->firstChild()); |
| 461 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement); | 463 DCHECK_EQ(m_targetElementInstance->parentNode(), shadowTreeRootElement); |
| 462 | 464 |
| 463 // Update relative length information. | 465 // Update relative length information. |
| 464 updateRelativeLengthsInformation(); | 466 updateRelativeLengthsInformation(); |
| 465 } | 467 } |
| 466 | 468 |
| 467 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) { | 469 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) { |
| 468 return new LayoutSVGTransformableContainer(this); | 470 return new LayoutSVGTransformableContainer(this); |
| 469 } | 471 } |
| 470 | 472 |
| 471 static bool isDirectReference(const SVGElement& element) { | 473 static bool isDirectReference(const SVGElement& element) { |
| 472 return isSVGPathElement(element) || isSVGRectElement(element) || | 474 return isSVGPathElement(element) || isSVGRectElement(element) || |
| 473 isSVGCircleElement(element) || isSVGEllipseElement(element) || | 475 isSVGCircleElement(element) || isSVGEllipseElement(element) || |
| 474 isSVGPolygonElement(element) || isSVGPolylineElement(element) || | 476 isSVGPolygonElement(element) || isSVGPolylineElement(element) || |
| 475 isSVGTextElement(element); | 477 isSVGTextElement(element); |
| 476 } | 478 } |
| 477 | 479 |
| 478 void SVGUseElement::toClipPath(Path& path) const { | 480 void SVGUseElement::toClipPath(Path& path) const { |
| 479 ASSERT(path.isEmpty()); | 481 DCHECK(path.isEmpty()); |
| 480 | 482 |
| 481 const SVGGraphicsElement* element = visibleTargetGraphicsElementForClipping(); | 483 const SVGGraphicsElement* element = visibleTargetGraphicsElementForClipping(); |
| 482 | 484 |
| 483 if (!element) | 485 if (!element) |
| 484 return; | 486 return; |
| 485 | 487 |
| 486 if (element->isSVGGeometryElement()) { | 488 if (element->isSVGGeometryElement()) { |
| 487 toSVGGeometryElement(*element).toClipPath(path); | 489 toSVGGeometryElement(*element).toClipPath(path); |
| 488 // FIXME: Avoid manual resolution of x/y here. Its potentially harmful. | 490 // FIXME: Avoid manual resolution of x/y here. Its potentially harmful. |
| 489 SVGLengthContext lengthContext(this); | 491 SVGLengthContext lengthContext(this); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 // Why expand the <use> elements in the shadow tree here, and not just | 581 // Why expand the <use> elements in the shadow tree here, and not just |
| 580 // do this directly in buildShadowTree, if we encounter a <use> element? | 582 // do this directly in buildShadowTree, if we encounter a <use> element? |
| 581 // | 583 // |
| 582 // Short answer: Because we may miss to expand some elements. For example, if | 584 // Short answer: Because we may miss to expand some elements. For example, if |
| 583 // a <symbol> contains <use> tags, we'd miss them. So once we're done with | 585 // a <symbol> contains <use> tags, we'd miss them. So once we're done with |
| 584 // setting up the actual shadow tree (after the special case modification for | 586 // setting up the actual shadow tree (after the special case modification for |
| 585 // svg/symbol) we have to walk it completely and expand all <use> elements. | 587 // svg/symbol) we have to walk it completely and expand all <use> elements. |
| 586 ShadowRoot* shadowRoot = userAgentShadowRoot(); | 588 ShadowRoot* shadowRoot = userAgentShadowRoot(); |
| 587 for (SVGUseElement* use = Traversal<SVGUseElement>::firstWithin(*shadowRoot); | 589 for (SVGUseElement* use = Traversal<SVGUseElement>::firstWithin(*shadowRoot); |
| 588 use;) { | 590 use;) { |
| 589 ASSERT(!use->resourceIsStillLoading()); | 591 DCHECK(!use->resourceIsStillLoading()); |
| 590 | 592 |
| 591 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement()); | 593 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement()); |
| 592 SVGElement* target = nullptr; | 594 SVGElement* target = nullptr; |
| 593 if (hasCycleUseReferencing(originalUse, *use, target)) | 595 if (hasCycleUseReferencing(originalUse, *use, target)) |
| 594 return false; | 596 return false; |
| 595 | 597 |
| 596 if (target && isDisallowedElement(*target)) | 598 if (target && isDisallowedElement(*target)) |
| 597 return false; | 599 return false; |
| 598 // Don't ASSERT(target) here, it may be "pending", too. | 600 // Don't DCHECK(target) here, it may be "pending", too. |
| 599 // Setup sub-shadow tree root node | 601 // Setup sub-shadow tree root node |
| 600 SVGGElement* cloneParent = SVGGElement::create(originalUse.document()); | 602 SVGGElement* cloneParent = SVGGElement::create(originalUse.document()); |
| 601 // Transfer all data (attributes, etc.) from <use> to the new <g> element. | 603 // Transfer all data (attributes, etc.) from <use> to the new <g> element. |
| 602 cloneParent->cloneDataFromElement(*use); | 604 cloneParent->cloneDataFromElement(*use); |
| 603 cloneParent->setCorrespondingElement(&originalUse); | 605 cloneParent->setCorrespondingElement(&originalUse); |
| 604 | 606 |
| 605 removeAttributesFromReplacementElement(*cloneParent); | 607 removeAttributesFromReplacementElement(*cloneParent); |
| 606 | 608 |
| 607 // Move already cloned elements to the new <g> element. | 609 // Move already cloned elements to the new <g> element. |
| 608 moveChildrenToReplacementElement(*use, *cloneParent); | 610 moveChildrenToReplacementElement(*use, *cloneParent); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 629 } | 631 } |
| 630 | 632 |
| 631 void SVGUseElement::invalidateDependentShadowTrees() { | 633 void SVGUseElement::invalidateDependentShadowTrees() { |
| 632 // Recursively invalidate dependent <use> shadow trees | 634 // Recursively invalidate dependent <use> shadow trees |
| 633 const HeapHashSet<WeakMember<SVGElement>>& rawInstances = | 635 const HeapHashSet<WeakMember<SVGElement>>& rawInstances = |
| 634 instancesForElement(); | 636 instancesForElement(); |
| 635 HeapVector<Member<SVGElement>> instances; | 637 HeapVector<Member<SVGElement>> instances; |
| 636 instances.appendRange(rawInstances.begin(), rawInstances.end()); | 638 instances.appendRange(rawInstances.begin(), rawInstances.end()); |
| 637 for (auto& instance : instances) { | 639 for (auto& instance : instances) { |
| 638 if (SVGUseElement* element = instance->correspondingUseElement()) { | 640 if (SVGUseElement* element = instance->correspondingUseElement()) { |
| 639 ASSERT(element->isConnected()); | 641 DCHECK(element->isConnected()); |
| 640 element->invalidateShadowTree(); | 642 element->invalidateShadowTree(); |
| 641 } | 643 } |
| 642 } | 644 } |
| 643 } | 645 } |
| 644 | 646 |
| 645 bool SVGUseElement::selfHasRelativeLengths() const { | 647 bool SVGUseElement::selfHasRelativeLengths() const { |
| 646 if (m_x->currentValue()->isRelative() || m_y->currentValue()->isRelative() || | 648 if (m_x->currentValue()->isRelative() || m_y->currentValue()->isRelative() || |
| 647 m_width->currentValue()->isRelative() || | 649 m_width->currentValue()->isRelative() || |
| 648 m_height->currentValue()->isRelative()) | 650 m_height->currentValue()->isRelative()) |
| 649 return true; | 651 return true; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 671 // correct without additional work. That will not work out ATM without | 673 // correct without additional work. That will not work out ATM without |
| 672 // additional quirks. The problem stems from including the additional | 674 // additional quirks. The problem stems from including the additional |
| 673 // translation directly on the LayoutObject corresponding to the | 675 // translation directly on the LayoutObject corresponding to the |
| 674 // SVGUseElement. | 676 // SVGUseElement. |
| 675 FloatRect bbox = transformableContainer.objectBoundingBox(); | 677 FloatRect bbox = transformableContainer.objectBoundingBox(); |
| 676 bbox.move(transformableContainer.additionalTranslation()); | 678 bbox.move(transformableContainer.additionalTranslation()); |
| 677 return bbox; | 679 return bbox; |
| 678 } | 680 } |
| 679 | 681 |
| 680 void SVGUseElement::dispatchPendingEvent() { | 682 void SVGUseElement::dispatchPendingEvent() { |
| 681 ASSERT(isStructurallyExternal() && m_haveFiredLoadEvent); | 683 DCHECK(isStructurallyExternal() && m_haveFiredLoadEvent); |
|
tkent
2017/03/14 22:33:14
Split it to two DCHECKs
DCHECK((isStructurallyEx
mrunal
2017/03/14 23:52:14
Done.
| |
| 682 dispatchEvent(Event::create(EventTypeNames::load)); | 684 dispatchEvent(Event::create(EventTypeNames::load)); |
| 683 } | 685 } |
| 684 | 686 |
| 685 void SVGUseElement::notifyFinished(Resource* resource) { | 687 void SVGUseElement::notifyFinished(Resource* resource) { |
| 686 ASSERT(m_resource == resource); | 688 DCHECK_EQ(m_resource, resource); |
| 687 if (!isConnected()) | 689 if (!isConnected()) |
| 688 return; | 690 return; |
| 689 | 691 |
| 690 invalidateShadowTree(); | 692 invalidateShadowTree(); |
| 691 if (!resourceIsValid()) { | 693 if (!resourceIsValid()) { |
| 692 dispatchEvent(Event::create(EventTypeNames::error)); | 694 dispatchEvent(Event::create(EventTypeNames::error)); |
| 693 } else if (!resource->wasCanceled()) { | 695 } else if (!resource->wasCanceled()) { |
| 694 if (m_haveFiredLoadEvent) | 696 if (m_haveFiredLoadEvent) |
| 695 return; | 697 return; |
| 696 if (!isStructurallyExternal()) | 698 if (!isStructurallyExternal()) |
| 697 return; | 699 return; |
| 698 ASSERT(!m_haveFiredLoadEvent); | 700 DCHECK(!m_haveFiredLoadEvent); |
| 699 m_haveFiredLoadEvent = true; | 701 m_haveFiredLoadEvent = true; |
| 700 TaskRunnerHelper::get(TaskType::DOMManipulation, &document()) | 702 TaskRunnerHelper::get(TaskType::DOMManipulation, &document()) |
| 701 ->postTask(BLINK_FROM_HERE, | 703 ->postTask(BLINK_FROM_HERE, |
| 702 WTF::bind(&SVGUseElement::dispatchPendingEvent, | 704 WTF::bind(&SVGUseElement::dispatchPendingEvent, |
| 703 wrapPersistent(this))); | 705 wrapPersistent(this))); |
| 704 } | 706 } |
| 705 } | 707 } |
| 706 | 708 |
| 707 bool SVGUseElement::resourceIsStillLoading() const { | 709 bool SVGUseElement::resourceIsStillLoading() const { |
| 708 return m_resource && m_resource->isLoading(); | 710 return m_resource && m_resource->isLoading(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 728 | 730 |
| 729 if (m_resource) | 731 if (m_resource) |
| 730 m_resource->removeClient(this); | 732 m_resource->removeClient(this); |
| 731 | 733 |
| 732 m_resource = resource; | 734 m_resource = resource; |
| 733 if (m_resource) | 735 if (m_resource) |
| 734 m_resource->addClient(this); | 736 m_resource->addClient(this); |
| 735 } | 737 } |
| 736 | 738 |
| 737 } // namespace blink | 739 } // namespace blink |
| OLD | NEW |