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 |