| 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, 2007 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
| 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| 5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 6 * Copyright (C) 2012 University of Szeged | 6 * Copyright (C) 2012 University of Szeged |
| 7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> | 7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); | 373 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); |
| 374 // The subtree is not in document so this won't generate events that
could mutate the tree. | 374 // The subtree is not in document so this won't generate events that
could mutate the tree. |
| 375 element->parentNode()->removeChild(element); | 375 element->parentNode()->removeChild(element); |
| 376 element = next; | 376 element = next; |
| 377 } else { | 377 } else { |
| 378 element = ElementTraversal::next(*element, &subtree); | 378 element = ElementTraversal::next(*element, &subtree); |
| 379 } | 379 } |
| 380 } | 380 } |
| 381 } | 381 } |
| 382 | 382 |
| 383 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe
rNode& destinationRoot) |
| 384 { |
| 385 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) { |
| 386 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); |
| 387 destinationRoot.appendChild(child); |
| 388 child = nextChild.release(); |
| 389 } |
| 390 } |
| 391 |
| 383 PassRefPtrWillBeRawPtr<Element> SVGUseElement::createInstanceTree(SVGElement& ta
rgetRoot) const | 392 PassRefPtrWillBeRawPtr<Element> SVGUseElement::createInstanceTree(SVGElement& ta
rgetRoot) const |
| 384 { | 393 { |
| 385 RefPtrWillBeRawPtr<Element> instanceRoot = targetRoot.cloneElementWithChildr
en(); | 394 RefPtrWillBeRawPtr<Element> instanceRoot = targetRoot.cloneElementWithChildr
en(); |
| 386 ASSERT(instanceRoot->isSVGElement()); | 395 ASSERT(instanceRoot->isSVGElement()); |
| 396 if (isSVGSymbolElement(targetRoot)) { |
| 397 // Spec: The referenced 'symbol' and its contents are deep-cloned into |
| 398 // the generated tree, with the exception that the 'symbol' is replaced |
| 399 // by an 'svg'. This generated 'svg' will always have explicit values |
| 400 // for attributes width and height. If attributes width and/or height |
| 401 // are provided on the 'use' element, then these attributes will be |
| 402 // transferred to the generated 'svg'. If attributes width and/or |
| 403 // height are not specified, the generated 'svg' element will use |
| 404 // values of 100% for these attributes. |
| 405 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(tar
getRoot.document()); |
| 406 // Transfer all data (attributes, etc.) from the <symbol> to the new |
| 407 // <svg> element. |
| 408 svgElement->cloneDataFromElement(*instanceRoot); |
| 409 // Move already cloned elements to the new <svg> element. |
| 410 moveChildrenToReplacementElement(*instanceRoot, *svgElement); |
| 411 instanceRoot = svgElement.release(); |
| 412 } |
| 413 transferUseWidthAndHeightIfNeeded(*this, toSVGElement(*instanceRoot), target
Root); |
| 387 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); | 414 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); |
| 388 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); | 415 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); |
| 389 return instanceRoot.release(); | 416 return instanceRoot.release(); |
| 390 } | 417 } |
| 391 | 418 |
| 392 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) | 419 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) |
| 393 { | 420 { |
| 394 ASSERT(!m_targetElementInstance); | 421 ASSERT(!m_targetElementInstance); |
| 395 ASSERT(!m_needsShadowTreeRecreation); | 422 ASSERT(!m_needsShadowTreeRecreation); |
| 396 | 423 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 423 ASSERT(m_targetElementInstance->correspondingUseElement() == this); | 450 ASSERT(m_targetElementInstance->correspondingUseElement() == this); |
| 424 ASSERT(m_targetElementInstance->correspondingElement() == &target); | 451 ASSERT(m_targetElementInstance->correspondingElement() == &target); |
| 425 | 452 |
| 426 // Expand all <use> elements in the shadow tree. | 453 // Expand all <use> elements in the shadow tree. |
| 427 // Expand means: replace the actual <use> element by what it references. | 454 // Expand means: replace the actual <use> element by what it references. |
| 428 if (!expandUseElementsInShadowTree()) { | 455 if (!expandUseElementsInShadowTree()) { |
| 429 clearShadowTree(); | 456 clearShadowTree(); |
| 430 return; | 457 return; |
| 431 } | 458 } |
| 432 | 459 |
| 433 // Expand all <symbol> elements in the shadow tree. | 460 // If the instance root was a <use>, it could have been replaced now, so |
| 434 // Expand means: replace the actual <symbol> element by the <svg> element. | 461 // reset |m_targetElementInstance|. |
| 435 expandSymbolElementsInShadowTree(); | 462 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); |
| 463 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement); |
| 436 | 464 |
| 437 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); | |
| 438 transferUseWidthAndHeightIfNeeded(*this, *m_targetElementInstance, *m_target
ElementInstance->correspondingElement()); | |
| 439 cloneNonMarkupEventListeners(); | 465 cloneNonMarkupEventListeners(); |
| 440 | 466 |
| 441 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement); | |
| 442 | |
| 443 // Update relative length information. | 467 // Update relative length information. |
| 444 updateRelativeLengthsInformation(); | 468 updateRelativeLengthsInformation(); |
| 445 } | 469 } |
| 446 | 470 |
| 447 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) | 471 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) |
| 448 { | 472 { |
| 449 return new LayoutSVGTransformableContainer(this); | 473 return new LayoutSVGTransformableContainer(this); |
| 450 } | 474 } |
| 451 | 475 |
| 452 static bool isDirectReference(const SVGElement& element) | 476 static bool isDirectReference(const SVGElement& element) |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 while (instance && instance->isSVGElement()) { | 567 while (instance && instance->isSVGElement()) { |
| 544 SVGElement* element = toSVGElement(instance); | 568 SVGElement* element = toSVGElement(instance); |
| 545 if (element->hasID() && element->getIdAttribute() == targetId && element
->document() == newTarget->document()) | 569 if (element->hasID() && element->getIdAttribute() == targetId && element
->document() == newTarget->document()) |
| 546 return true; | 570 return true; |
| 547 | 571 |
| 548 instance = instance->parentNode(); | 572 instance = instance->parentNode(); |
| 549 } | 573 } |
| 550 return false; | 574 return false; |
| 551 } | 575 } |
| 552 | 576 |
| 553 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe
rNode& destinationRoot) | |
| 554 { | |
| 555 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) { | |
| 556 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); | |
| 557 destinationRoot.appendChild(child); | |
| 558 child = nextChild.release(); | |
| 559 } | |
| 560 } | |
| 561 | |
| 562 // Spec: In the generated content, the 'use' will be replaced by 'g', where all | 577 // Spec: In the generated content, the 'use' will be replaced by 'g', where all |
| 563 // attributes from the 'use' element except for x, y, width, height and | 578 // attributes from the 'use' element except for x, y, width, height and |
| 564 // xlink:href are transferred to the generated 'g' element. | 579 // xlink:href are transferred to the generated 'g' element. |
| 565 static void removeAttributesFromReplacementElement(SVGElement& replacementElemen
t) | 580 static void removeAttributesFromReplacementElement(SVGElement& replacementElemen
t) |
| 566 { | 581 { |
| 567 replacementElement.removeAttribute(SVGNames::xAttr); | 582 replacementElement.removeAttribute(SVGNames::xAttr); |
| 568 replacementElement.removeAttribute(SVGNames::yAttr); | 583 replacementElement.removeAttribute(SVGNames::yAttr); |
| 569 replacementElement.removeAttribute(SVGNames::widthAttr); | 584 replacementElement.removeAttribute(SVGNames::widthAttr); |
| 570 replacementElement.removeAttribute(SVGNames::heightAttr); | 585 replacementElement.removeAttribute(SVGNames::heightAttr); |
| 571 replacementElement.removeAttribute(SVGNames::hrefAttr); | 586 replacementElement.removeAttribute(SVGNames::hrefAttr); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 597 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(origin
alUse.document()); | 612 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(origin
alUse.document()); |
| 598 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen
t. | 613 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen
t. |
| 599 cloneParent->cloneDataFromElement(*use); | 614 cloneParent->cloneDataFromElement(*use); |
| 600 cloneParent->setCorrespondingElement(&originalUse); | 615 cloneParent->setCorrespondingElement(&originalUse); |
| 601 | 616 |
| 602 removeAttributesFromReplacementElement(*cloneParent); | 617 removeAttributesFromReplacementElement(*cloneParent); |
| 603 | 618 |
| 604 // Move already cloned elements to the new <g> element. | 619 // Move already cloned elements to the new <g> element. |
| 605 moveChildrenToReplacementElement(*use, *cloneParent); | 620 moveChildrenToReplacementElement(*use, *cloneParent); |
| 606 | 621 |
| 607 if (target) { | 622 if (target) |
| 608 RefPtrWillBeRawPtr<Element> instanceRoot = use->createInstanceTree(*
target); | 623 cloneParent->appendChild(use->createInstanceTree(*target)); |
| 609 transferUseWidthAndHeightIfNeeded(*use, toSVGElement(*instanceRoot),
*target); | |
| 610 cloneParent->appendChild(instanceRoot.release()); | |
| 611 } | |
| 612 | 624 |
| 613 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); | 625 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); |
| 614 | 626 |
| 615 // Replace <use> with referenced content. | 627 // Replace <use> with referenced content. |
| 616 use->parentNode()->replaceChild(cloneParent.release(), use); | 628 use->parentNode()->replaceChild(cloneParent.release(), use); |
| 617 | 629 |
| 618 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); | 630 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); |
| 619 } | 631 } |
| 620 return true; | 632 return true; |
| 621 } | 633 } |
| 622 | 634 |
| 623 void SVGUseElement::expandSymbolElementsInShadowTree() | |
| 624 { | |
| 625 ShadowRoot* shadowRoot = userAgentShadowRoot(); | |
| 626 for (RefPtrWillBeRawPtr<SVGSymbolElement> symbol = Traversal<SVGSymbolElemen
t>::firstWithin(*shadowRoot); symbol; ) { | |
| 627 // Spec: The referenced 'symbol' and its contents are deep-cloned into t
he generated tree, | |
| 628 // with the exception that the 'symbol' is replaced by an 'svg'. This ge
nerated 'svg' will | |
| 629 // always have explicit values for attributes width and height. If attri
butes width and/or | |
| 630 // height are provided on the 'use' element, then these attributes will
be transferred to | |
| 631 // the generated 'svg'. If attributes width and/or height are not specif
ied, the generated | |
| 632 // 'svg' element will use values of 100% for these attributes. | |
| 633 SVGElement& originalSymbol = *symbol->correspondingElement(); | |
| 634 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(ori
ginalSymbol.document()); | |
| 635 // Transfer all data (attributes, etc.) from <symbol> to the new <svg> e
lement. | |
| 636 svgElement->cloneDataFromElement(*symbol); | |
| 637 svgElement->setCorrespondingElement(&originalSymbol); | |
| 638 | |
| 639 // Move already cloned elements to the new <svg> element. | |
| 640 moveChildrenToReplacementElement(*symbol, *svgElement); | |
| 641 | |
| 642 RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get()); | |
| 643 | |
| 644 // Replace <symbol> with <svg>. | |
| 645 symbol->parentNode()->replaceChild(svgElement.release(), symbol); | |
| 646 | |
| 647 symbol = Traversal<SVGSymbolElement>::next(*replacingElement, shadowRoot
); | |
| 648 } | |
| 649 } | |
| 650 | |
| 651 void SVGUseElement::invalidateShadowTree() | 635 void SVGUseElement::invalidateShadowTree() |
| 652 { | 636 { |
| 653 if (!inActiveDocument() || m_needsShadowTreeRecreation) | 637 if (!inActiveDocument() || m_needsShadowTreeRecreation) |
| 654 return; | 638 return; |
| 655 clearInstanceRoot(); | 639 clearInstanceRoot(); |
| 656 scheduleShadowTreeRecreation(); | 640 scheduleShadowTreeRecreation(); |
| 657 invalidateDependentShadowTrees(); | 641 invalidateDependentShadowTrees(); |
| 658 } | 642 } |
| 659 | 643 |
| 660 void SVGUseElement::invalidateDependentShadowTrees() | 644 void SVGUseElement::invalidateDependentShadowTrees() |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 | 748 |
| 765 if (m_resource) | 749 if (m_resource) |
| 766 m_resource->removeClient(this); | 750 m_resource->removeClient(this); |
| 767 | 751 |
| 768 m_resource = resource; | 752 m_resource = resource; |
| 769 if (m_resource) | 753 if (m_resource) |
| 770 m_resource->addClient(this); | 754 m_resource->addClient(this); |
| 771 } | 755 } |
| 772 | 756 |
| 773 } // namespace blink | 757 } // namespace blink |
| OLD | NEW |