OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann |
| 3 * <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 4 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 6 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
6 * Copyright (C) 2012 University of Szeged | 7 * Copyright (C) 2012 University of Szeged |
7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> | 8 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> |
8 * | 9 * |
9 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 11 * modify it under the terms of the GNU Library General Public |
11 * License as published by the Free Software Foundation; either | 12 * License as published by the Free Software Foundation; either |
12 * version 2 of the License, or (at your option) any later version. | 13 * version 2 of the License, or (at your option) any later version. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 #if ENABLE(ASSERT) | 105 #if ENABLE(ASSERT) |
105 static inline bool isWellFormedDocument(Document* document) { | 106 static inline bool isWellFormedDocument(Document* document) { |
106 if (document->isXMLDocument()) | 107 if (document->isXMLDocument()) |
107 return static_cast<XMLDocumentParser*>(document->parser())->wellFormed(); | 108 return static_cast<XMLDocumentParser*>(document->parser())->wellFormed(); |
108 return true; | 109 return true; |
109 } | 110 } |
110 #endif | 111 #endif |
111 | 112 |
112 Node::InsertionNotificationRequest SVGUseElement::insertedInto( | 113 Node::InsertionNotificationRequest SVGUseElement::insertedInto( |
113 ContainerNode* rootParent) { | 114 ContainerNode* rootParent) { |
114 // This functions exists to assure assumptions made in the code regarding SVGE
lementInstance creation/destruction are satisfied. | 115 // This functions exists to assure assumptions made in the code regarding |
| 116 // SVGElementInstance creation/destruction are satisfied. |
115 SVGGraphicsElement::insertedInto(rootParent); | 117 SVGGraphicsElement::insertedInto(rootParent); |
116 if (!rootParent->isConnected()) | 118 if (!rootParent->isConnected()) |
117 return InsertionDone; | 119 return InsertionDone; |
118 ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document())); | 120 ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document())); |
119 ASSERT(!hasPendingResources() || !isWellFormedDocument(&document())); | 121 ASSERT(!hasPendingResources() || !isWellFormedDocument(&document())); |
120 invalidateShadowTree(); | 122 invalidateShadowTree(); |
121 return InsertionDone; | 123 return InsertionDone; |
122 } | 124 } |
123 | 125 |
124 void SVGUseElement::removedFrom(ContainerNode* rootParent) { | 126 void SVGUseElement::removedFrom(ContainerNode* rootParent) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 SVGElement::InvalidationGuard invalidationGuard(this); | 253 SVGElement::InvalidationGuard invalidationGuard(this); |
252 updateTargetReference(); | 254 updateTargetReference(); |
253 invalidateShadowTree(); | 255 invalidateShadowTree(); |
254 return; | 256 return; |
255 } | 257 } |
256 | 258 |
257 SVGGraphicsElement::svgAttributeChanged(attrName); | 259 SVGGraphicsElement::svgAttributeChanged(attrName); |
258 } | 260 } |
259 | 261 |
260 static bool isDisallowedElement(const Element& element) { | 262 static bool isDisallowedElement(const Element& element) { |
261 // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is potenti
ally a template object that can be re-used | 263 // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is |
262 // (i.e., "instanced") in the SVG document via a 'use' element." | 264 // potentially a template object that can be re-used (i.e., "instanced") in |
263 // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'pat
h', 'polygon', 'polyline', 'rect', 'text' | 265 // the SVG document via a 'use' element." "Graphics Element" is defined as |
264 // Excluded are anything that is used by reference or that only make sense to
appear once in a document. | 266 // 'circle', 'ellipse', 'image', 'line', 'path', 'polygon', 'polyline', |
| 267 // 'rect', 'text' Excluded are anything that is used by reference or that only |
| 268 // make sense to appear once in a document. |
265 if (!element.isSVGElement()) | 269 if (!element.isSVGElement()) |
266 return true; | 270 return true; |
267 | 271 |
268 DEFINE_STATIC_LOCAL( | 272 DEFINE_STATIC_LOCAL( |
269 HashSet<QualifiedName>, allowedElementTags, | 273 HashSet<QualifiedName>, allowedElementTags, |
270 ({ | 274 ({ |
271 SVGNames::aTag, SVGNames::circleTag, SVGNames::descTag, | 275 SVGNames::aTag, SVGNames::circleTag, SVGNames::descTag, |
272 SVGNames::ellipseTag, SVGNames::gTag, SVGNames::imageTag, | 276 SVGNames::ellipseTag, SVGNames::gTag, SVGNames::imageTag, |
273 SVGNames::lineTag, SVGNames::metadataTag, SVGNames::pathTag, | 277 SVGNames::lineTag, SVGNames::metadataTag, SVGNames::pathTag, |
274 SVGNames::polygonTag, SVGNames::polylineTag, SVGNames::rectTag, | 278 SVGNames::polygonTag, SVGNames::polylineTag, SVGNames::rectTag, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 // Though if there are disallowed elements in the subtree, we have to remove | 369 // Though if there are disallowed elements in the subtree, we have to remove |
366 // them. For instance: <use> on <g> containing <foreignObject> (indirect | 370 // them. For instance: <use> on <g> containing <foreignObject> (indirect |
367 // case). | 371 // case). |
368 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) { | 372 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) { |
369 ASSERT(!subtree.isConnected()); | 373 ASSERT(!subtree.isConnected()); |
370 Element* element = ElementTraversal::firstWithin(subtree); | 374 Element* element = ElementTraversal::firstWithin(subtree); |
371 while (element) { | 375 while (element) { |
372 if (isDisallowedElement(*element)) { | 376 if (isDisallowedElement(*element)) { |
373 Element* next = | 377 Element* next = |
374 ElementTraversal::nextSkippingChildren(*element, &subtree); | 378 ElementTraversal::nextSkippingChildren(*element, &subtree); |
375 // The subtree is not in document so this won't generate events that could
mutate the tree. | 379 // The subtree is not in document so this won't generate events that could |
| 380 // mutate the tree. |
376 element->parentNode()->removeChild(element); | 381 element->parentNode()->removeChild(element); |
377 element = next; | 382 element = next; |
378 } else { | 383 } else { |
379 element = ElementTraversal::next(*element, &subtree); | 384 element = ElementTraversal::next(*element, &subtree); |
380 } | 385 } |
381 } | 386 } |
382 } | 387 } |
383 | 388 |
384 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, | 389 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, |
385 ContainerNode& destinationRoot) { | 390 ContainerNode& destinationRoot) { |
(...skipping 28 matching lines...) Expand all Loading... |
414 targetRoot); | 419 targetRoot); |
415 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); | 420 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); |
416 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); | 421 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); |
417 return instanceRoot; | 422 return instanceRoot; |
418 } | 423 } |
419 | 424 |
420 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) { | 425 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) { |
421 ASSERT(!m_targetElementInstance); | 426 ASSERT(!m_targetElementInstance); |
422 ASSERT(!m_needsShadowTreeRecreation); | 427 ASSERT(!m_needsShadowTreeRecreation); |
423 | 428 |
424 // <use> creates a "user agent" shadow root. Do not build the shadow/instance
tree for <use> | 429 // <use> creates a "user agent" shadow root. Do not build the shadow/instance |
425 // elements living in a user agent shadow tree because they will get expanded
in a second | 430 // tree for <use> elements living in a user agent shadow tree because they |
426 // pass -- see expandUseElementsInShadowTree(). | 431 // will get expanded in a second pass -- see expandUseElementsInShadowTree(). |
427 if (inUseShadowTree()) | 432 if (inUseShadowTree()) |
428 return; | 433 return; |
429 | 434 |
430 // Do not allow self-referencing. | 435 // Do not allow self-referencing. |
431 if (&target == this || isDisallowedElement(target)) | 436 if (&target == this || isDisallowedElement(target)) |
432 return; | 437 return; |
433 | 438 |
434 // Set up root SVG element in shadow tree. | 439 // Set up root SVG element in shadow tree. |
435 // Clone the target subtree into the shadow tree, not handling <use> and <symb
ol> yet. | 440 // Clone the target subtree into the shadow tree, not handling <use> and |
| 441 // <symbol> yet. |
436 Element* instanceRoot = createInstanceTree(target); | 442 Element* instanceRoot = createInstanceTree(target); |
437 m_targetElementInstance = toSVGElement(instanceRoot); | 443 m_targetElementInstance = toSVGElement(instanceRoot); |
438 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); | 444 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
439 shadowTreeRootElement->appendChild(instanceRoot); | 445 shadowTreeRootElement->appendChild(instanceRoot); |
440 | 446 |
441 addReferencesToFirstDegreeNestedUseElements(target); | 447 addReferencesToFirstDegreeNestedUseElements(target); |
442 | 448 |
443 if (instanceTreeIsLoading()) | 449 if (instanceTreeIsLoading()) |
444 return; | 450 return; |
445 | 451 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 if (!element.isSVGGraphicsElement()) | 510 if (!element.isSVGGraphicsElement()) |
505 return nullptr; | 511 return nullptr; |
506 | 512 |
507 if (!element.layoutObject()) | 513 if (!element.layoutObject()) |
508 return nullptr; | 514 return nullptr; |
509 | 515 |
510 const ComputedStyle* style = element.layoutObject()->style(); | 516 const ComputedStyle* style = element.layoutObject()->style(); |
511 if (!style || style->visibility() != EVisibility::Visible) | 517 if (!style || style->visibility() != EVisibility::Visible) |
512 return nullptr; | 518 return nullptr; |
513 | 519 |
514 // Spec: "If a <use> element is a child of a clipPath element, it must directl
y | 520 // Spec: "If a <use> element is a child of a clipPath element, it must |
515 // reference <path>, <text> or basic shapes elements. Indirect references are
an | 521 // directly reference <path>, <text> or basic shapes elements. Indirect |
516 // error and the clipPath element must be ignored." | 522 // references are an error and the clipPath element must be ignored." |
517 // http://dev.w3.org/fxtf/css-masking-1/#the-clip-path | 523 // http://dev.w3.org/fxtf/css-masking-1/#the-clip-path |
518 if (!isDirectReference(element)) { | 524 if (!isDirectReference(element)) { |
519 // Spec: Indirect references are an error (14.3.5) | 525 // Spec: Indirect references are an error (14.3.5) |
520 return nullptr; | 526 return nullptr; |
521 } | 527 } |
522 | 528 |
523 return &toSVGGraphicsElement(element); | 529 return &toSVGGraphicsElement(element); |
524 } | 530 } |
525 | 531 |
526 void SVGUseElement::addReferencesToFirstDegreeNestedUseElements( | 532 void SVGUseElement::addReferencesToFirstDegreeNestedUseElements( |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 replacementElement.removeAttribute(SVGNames::widthAttr); | 585 replacementElement.removeAttribute(SVGNames::widthAttr); |
580 replacementElement.removeAttribute(SVGNames::heightAttr); | 586 replacementElement.removeAttribute(SVGNames::heightAttr); |
581 replacementElement.removeAttribute(SVGNames::hrefAttr); | 587 replacementElement.removeAttribute(SVGNames::hrefAttr); |
582 replacementElement.removeAttribute(XLinkNames::hrefAttr); | 588 replacementElement.removeAttribute(XLinkNames::hrefAttr); |
583 } | 589 } |
584 | 590 |
585 bool SVGUseElement::expandUseElementsInShadowTree() { | 591 bool SVGUseElement::expandUseElementsInShadowTree() { |
586 // Why expand the <use> elements in the shadow tree here, and not just | 592 // Why expand the <use> elements in the shadow tree here, and not just |
587 // do this directly in buildShadowTree, if we encounter a <use> element? | 593 // do this directly in buildShadowTree, if we encounter a <use> element? |
588 // | 594 // |
589 // Short answer: Because we may miss to expand some elements. For example, if
a <symbol> | 595 // Short answer: Because we may miss to expand some elements. For example, if |
590 // contains <use> tags, we'd miss them. So once we're done with setting up the | 596 // a <symbol> contains <use> tags, we'd miss them. So once we're done with |
591 // actual shadow tree (after the special case modification for svg/symbol) we
have | 597 // setting up the actual shadow tree (after the special case modification for |
592 // to walk it completely and expand all <use> elements. | 598 // svg/symbol) we have to walk it completely and expand all <use> elements. |
593 ShadowRoot* shadowRoot = userAgentShadowRoot(); | 599 ShadowRoot* shadowRoot = userAgentShadowRoot(); |
594 for (SVGUseElement* use = Traversal<SVGUseElement>::firstWithin(*shadowRoot); | 600 for (SVGUseElement* use = Traversal<SVGUseElement>::firstWithin(*shadowRoot); |
595 use;) { | 601 use;) { |
596 ASSERT(!use->resourceIsStillLoading()); | 602 ASSERT(!use->resourceIsStillLoading()); |
597 | 603 |
598 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement()); | 604 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement()); |
599 SVGElement* target = nullptr; | 605 SVGElement* target = nullptr; |
600 if (hasCycleUseReferencing(originalUse, *use, target)) | 606 if (hasCycleUseReferencing(originalUse, *use, target)) |
601 return false; | 607 return false; |
602 | 608 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 | 741 |
736 if (m_resource) | 742 if (m_resource) |
737 m_resource->removeClient(this); | 743 m_resource->removeClient(this); |
738 | 744 |
739 m_resource = resource; | 745 m_resource = resource; |
740 if (m_resource) | 746 if (m_resource) |
741 m_resource->addClient(this); | 747 m_resource->addClient(this); |
742 } | 748 } |
743 | 749 |
744 } // namespace blink | 750 } // namespace blink |
OLD | NEW |