2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Rob Buis <buis@kde.org>
4 * Copyright (C) 2007 Apple Inc. All rights reserved.
5 * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #include "SVGSVGElement.h"
26 #include "AffineTransform.h"
27 #include "Attribute.h"
28 #include "CSSHelper.h"
30 #include "ElementIterator.h"
31 #include "EventListener.h"
32 #include "EventNames.h"
33 #include "FloatConversion.h"
34 #include "FloatRect.h"
36 #include "FrameSelection.h"
37 #include "FrameTree.h"
38 #include "FrameView.h"
39 #include "HTMLNames.h"
40 #include "RenderObject.h"
41 #include "RenderSVGResource.h"
42 #include "RenderSVGModelObject.h"
43 #include "RenderSVGRoot.h"
44 #include "RenderSVGViewportContainer.h"
45 #include "RenderView.h"
46 #include "RenderWidget.h"
47 #include "SMILTimeContainer.h"
49 #include "SVGElementInstance.h"
50 #include "SVGFitToViewBox.h"
52 #include "SVGPreserveAspectRatio.h"
53 #include "SVGTransform.h"
54 #include "SVGTransformList.h"
55 #include "SVGViewElement.h"
56 #include "SVGViewSpec.h"
57 #include "SVGZoomEvent.h"
58 #include "StaticNodeList.h"
59 #include <wtf/StdLibExtras.h>
63 // Animated property definitions
64 DEFINE_ANIMATED_LENGTH(SVGSVGElement, SVGNames::xAttr, X, x)
65 DEFINE_ANIMATED_LENGTH(SVGSVGElement, SVGNames::yAttr, Y, y)
66 DEFINE_ANIMATED_LENGTH(SVGSVGElement, SVGNames::widthAttr, Width, width)
67 DEFINE_ANIMATED_LENGTH(SVGSVGElement, SVGNames::heightAttr, Height, height)
68 DEFINE_ANIMATED_BOOLEAN(SVGSVGElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
69 DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGSVGElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio)
70 DEFINE_ANIMATED_RECT(SVGSVGElement, SVGNames::viewBoxAttr, ViewBox, viewBox)
72 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGSVGElement)
73 REGISTER_LOCAL_ANIMATED_PROPERTY(x)
74 REGISTER_LOCAL_ANIMATED_PROPERTY(y)
75 REGISTER_LOCAL_ANIMATED_PROPERTY(width)
76 REGISTER_LOCAL_ANIMATED_PROPERTY(height)
77 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
78 REGISTER_LOCAL_ANIMATED_PROPERTY(viewBox)
79 REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio)
80 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
81 END_REGISTER_ANIMATED_PROPERTIES
83 inline SVGSVGElement::SVGSVGElement(const QualifiedName& tagName, Document& document)
84 : SVGGraphicsElement(tagName, document)
85 , m_x(LengthModeWidth)
86 , m_y(LengthModeHeight)
87 , m_width(LengthModeWidth, "100%")
88 , m_height(LengthModeHeight, "100%")
89 , m_useCurrentView(false)
90 , m_zoomAndPan(SVGZoomAndPanMagnify)
91 , m_timeContainer(SMILTimeContainer::create(this))
93 ASSERT(hasTagName(SVGNames::svgTag));
94 registerAnimatedPropertiesForSVGSVGElement();
95 document.registerForPageCacheSuspensionCallbacks(this);
98 PassRefPtr<SVGSVGElement> SVGSVGElement::create(const QualifiedName& tagName, Document& document)
100 return adoptRef(new SVGSVGElement(tagName, document));
103 SVGSVGElement::~SVGSVGElement()
106 m_viewSpec->resetContextElement();
107 document().unregisterForPageCacheSuspensionCallbacks(this);
108 // There are cases where removedFromDocument() is not called.
109 // see ContainerNode::removeAllChildren, called by its destructor.
110 document().accessSVGExtensions().removeTimeContainer(this);
113 void SVGSVGElement::didMoveToNewDocument(Document* oldDocument)
116 oldDocument->unregisterForPageCacheSuspensionCallbacks(this);
117 document().registerForPageCacheSuspensionCallbacks(this);
118 SVGGraphicsElement::didMoveToNewDocument(oldDocument);
121 const AtomicString& SVGSVGElement::contentScriptType() const
123 DEPRECATED_DEFINE_STATIC_LOCAL(const AtomicString, defaultValue, ("text/ecmascript", AtomicString::ConstructFromLiteral));
124 const AtomicString& n = fastGetAttribute(SVGNames::contentScriptTypeAttr);
125 return n.isNull() ? defaultValue : n;
128 void SVGSVGElement::setContentScriptType(const AtomicString& type)
130 setAttribute(SVGNames::contentScriptTypeAttr, type);
133 const AtomicString& SVGSVGElement::contentStyleType() const
135 DEPRECATED_DEFINE_STATIC_LOCAL(const AtomicString, defaultValue, ("text/css", AtomicString::ConstructFromLiteral));
136 const AtomicString& n = fastGetAttribute(SVGNames::contentStyleTypeAttr);
137 return n.isNull() ? defaultValue : n;
140 void SVGSVGElement::setContentStyleType(const AtomicString& type)
142 setAttribute(SVGNames::contentStyleTypeAttr, type);
145 FloatRect SVGSVGElement::viewport() const
147 // FIXME: This method doesn't follow the spec and is basically untested. Parent documents are not considered here.
148 // As we have no test coverage for this, we're going to disable it completly for now.
152 float SVGSVGElement::pixelUnitToMillimeterX() const
154 // 2.54 / cssPixelsPerInch gives CM.
155 return (2.54f / cssPixelsPerInch) * 10.0f;
158 float SVGSVGElement::pixelUnitToMillimeterY() const
160 // 2.54 / cssPixelsPerInch gives CM.
161 return (2.54f / cssPixelsPerInch) * 10.0f;
164 float SVGSVGElement::screenPixelToMillimeterX() const
166 return pixelUnitToMillimeterX();
169 float SVGSVGElement::screenPixelToMillimeterY() const
171 return pixelUnitToMillimeterY();
174 SVGViewSpec* SVGSVGElement::currentView()
177 m_viewSpec = SVGViewSpec::create(this);
178 return m_viewSpec.get();
181 float SVGSVGElement::currentScale() const
183 if (!inDocument() || !isOutermostSVGSVGElement())
186 Frame* frame = document().frame();
190 // The behaviour of currentScale() is undefined, when we're dealing with non-standalone SVG documents.
191 // If the svg is embedded, the scaling is handled by the host renderer, so when asking from inside
192 // the SVG document, a scale value of 1 seems reasonable, as it doesn't know anything about the parent scale.
193 return frame->tree().parent() ? 1 : frame->pageZoomFactor();
196 void SVGSVGElement::setCurrentScale(float scale)
198 if (!inDocument() || !isOutermostSVGSVGElement())
201 Frame* frame = document().frame();
205 // The behaviour of setCurrentScale() is undefined, when we're dealing with non-standalone SVG documents.
206 // We choose the ignore this call, it's pretty useless to support calling setCurrentScale() from within
207 // an embedded SVG document, for the same reasons as in currentScale() - needs resolution by SVG WG.
208 if (frame->tree().parent())
211 frame->setPageZoomFactor(scale);
214 void SVGSVGElement::setCurrentTranslate(const FloatPoint& translation)
216 m_translation = translation;
217 updateCurrentTranslate();
220 void SVGSVGElement::updateCurrentTranslate()
222 if (RenderObject* object = renderer())
223 object->setNeedsLayout();
225 if (parentNode() == &document() && document().renderView())
226 document().renderView()->repaint();
229 void SVGSVGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
231 SVGParsingError parseError = NoError;
233 if (!nearestViewportElement()) {
234 bool setListener = true;
236 // Only handle events if we're the outermost <svg> element
237 if (name == HTMLNames::onunloadAttr)
238 document().setWindowAttributeEventListener(eventNames().unloadEvent, name, value);
239 else if (name == HTMLNames::onresizeAttr)
240 document().setWindowAttributeEventListener(eventNames().resizeEvent, name, value);
241 else if (name == HTMLNames::onscrollAttr)
242 document().setWindowAttributeEventListener(eventNames().scrollEvent, name, value);
243 else if (name == SVGNames::onzoomAttr)
244 document().setWindowAttributeEventListener(eventNames().zoomEvent, name, value);
252 if (name == HTMLNames::onabortAttr)
253 document().setWindowAttributeEventListener(eventNames().abortEvent, name, value);
254 else if (name == HTMLNames::onerrorAttr)
255 document().setWindowAttributeEventListener(eventNames().errorEvent, name, value);
256 else if (name == SVGNames::xAttr)
257 setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
258 else if (name == SVGNames::yAttr)
259 setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
260 else if (name == SVGNames::widthAttr)
261 setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
262 else if (name == SVGNames::heightAttr)
263 setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
264 else if (SVGLangSpace::parseAttribute(name, value)
265 || SVGExternalResourcesRequired::parseAttribute(name, value)
266 || SVGFitToViewBox::parseAttribute(this, name, value)
267 || SVGZoomAndPan::parseAttribute(this, name, value)) {
269 SVGGraphicsElement::parseAttribute(name, value);
271 reportAttributeParsingError(parseError, name, value);
274 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
276 bool updateRelativeLengthsOrViewBox = false;
277 if (attrName == SVGNames::widthAttr
278 || attrName == SVGNames::heightAttr
279 || attrName == SVGNames::xAttr
280 || attrName == SVGNames::yAttr) {
281 invalidateSVGPresentationAttributeStyle();
282 updateRelativeLengthsOrViewBox = true;
285 if (SVGFitToViewBox::isKnownAttribute(attrName)) {
286 updateRelativeLengthsOrViewBox = true;
287 if (RenderObject* object = renderer())
288 object->setNeedsTransformUpdate();
291 SVGElementInstance::InvalidationGuard invalidationGuard(this);
293 if (updateRelativeLengthsOrViewBox
294 || SVGLangSpace::isKnownAttribute(attrName)
295 || SVGExternalResourcesRequired::isKnownAttribute(attrName)
296 || SVGZoomAndPan::isKnownAttribute(attrName)) {
297 if (auto renderer = this->renderer())
298 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
302 SVGGraphicsElement::svgAttributeChanged(attrName);
305 unsigned SVGSVGElement::suspendRedraw(unsigned /* maxWaitMilliseconds */)
307 // FIXME: Implement me (see bug 11275)
311 void SVGSVGElement::unsuspendRedraw(unsigned /* suspendHandleId */)
313 // FIXME: Implement me (see bug 11275)
316 void SVGSVGElement::unsuspendRedrawAll()
318 // FIXME: Implement me (see bug 11275)
321 void SVGSVGElement::forceRedraw()
323 // FIXME: Implement me (see bug 11275)
326 PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const FloatRect& rect, SVGElement* referenceElement, CollectIntersectionOrEnclosure collect) const
328 Vector<Ref<Element>> elements;
330 for (auto& svgElement : descendantsOfType<SVGElement>(*(referenceElement ? referenceElement : this))) {
331 if (collect == CollectIntersectionList) {
332 if (RenderSVGModelObject::checkIntersection(svgElement.renderer(), rect))
333 elements.append(const_cast<SVGElement&>(svgElement));
335 if (RenderSVGModelObject::checkEnclosure(svgElement.renderer(), rect))
336 elements.append(const_cast<SVGElement&>(svgElement));
340 return StaticElementList::adopt(elements);
343 PassRefPtr<NodeList> SVGSVGElement::getIntersectionList(const FloatRect& rect, SVGElement* referenceElement) const
345 return collectIntersectionOrEnclosureList(rect, referenceElement, CollectIntersectionList);
348 PassRefPtr<NodeList> SVGSVGElement::getEnclosureList(const FloatRect& rect, SVGElement* referenceElement) const
350 return collectIntersectionOrEnclosureList(rect, referenceElement, CollectEnclosureList);
353 bool SVGSVGElement::checkIntersection(const SVGElement* element, const FloatRect& rect) const
357 return RenderSVGModelObject::checkIntersection(element->renderer(), rect);
360 bool SVGSVGElement::checkEnclosure(const SVGElement* element, const FloatRect& rect) const
364 return RenderSVGModelObject::checkEnclosure(element->renderer(), rect);
367 void SVGSVGElement::deselectAll()
369 if (Frame* frame = document().frame())
370 frame->selection().clear();
373 float SVGSVGElement::createSVGNumber()
378 SVGLength SVGSVGElement::createSVGLength()
383 SVGAngle SVGSVGElement::createSVGAngle()
388 SVGPoint SVGSVGElement::createSVGPoint()
393 SVGMatrix SVGSVGElement::createSVGMatrix()
398 FloatRect SVGSVGElement::createSVGRect()
403 SVGTransform SVGSVGElement::createSVGTransform()
405 return SVGTransform(SVGTransform::SVG_TRANSFORM_MATRIX);
408 SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const SVGMatrix& matrix)
410 return SVGTransform(static_cast<const AffineTransform&>(matrix));
413 AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const
415 AffineTransform viewBoxTransform;
416 if (!hasEmptyViewBox()) {
417 FloatSize size = currentViewportSize();
418 viewBoxTransform = viewBoxToViewTransform(size.width(), size.height());
421 AffineTransform transform;
422 if (!isOutermostSVGSVGElement()) {
423 SVGLengthContext lengthContext(this);
424 transform.translate(x().value(lengthContext), y().value(lengthContext));
425 } else if (mode == SVGLocatable::ScreenScope) {
426 if (RenderObject* renderer = this->renderer()) {
428 float zoomFactor = 1;
430 // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
431 // to map an element from SVG viewport coordinates to CSS box coordinates.
432 // RenderSVGRoot's localToAbsolute method expects CSS box coordinates.
433 // We also need to adjust for the zoom level factored into CSS coordinates (bug #96361).
434 if (renderer->isSVGRoot()) {
435 location = toRenderSVGRoot(renderer)->localToBorderBoxTransform().mapPoint(location);
436 zoomFactor = 1 / renderer->style().effectiveZoom();
439 // Translate in our CSS parent coordinate space
440 // FIXME: This doesn't work correctly with CSS transforms.
441 location = renderer->localToAbsolute(location, UseTransforms);
442 location.scale(zoomFactor, zoomFactor);
444 // Be careful here! localToBorderBoxTransform() included the x/y offset coming from the viewBoxToViewTransform(),
445 // so we have to subtract it here (original cause of bug #27183)
446 transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f());
448 // Respect scroll offset.
449 if (FrameView* view = document().view()) {
450 LayoutSize scrollOffset = view->scrollOffset();
451 scrollOffset.scale(zoomFactor);
452 transform.translate(-scrollOffset.width(), -scrollOffset.height());
457 return transform.multiply(viewBoxTransform);
460 bool SVGSVGElement::rendererIsNeeded(const RenderStyle& style)
464 // FIXME: We should respect display: none on the documentElement svg element
465 // but many things in FrameView and SVGImage depend on the RenderSVGRoot when
466 // they should instead depend on the RenderView.
467 // https://bugs.webkit.org/show_bug.cgi?id=103493
468 if (document().documentElement() == this)
470 return StyledElement::rendererIsNeeded(style);
473 RenderPtr<RenderElement> SVGSVGElement::createElementRenderer(PassRef<RenderStyle> style)
475 if (isOutermostSVGSVGElement())
476 return createRenderer<RenderSVGRoot>(*this, WTF::move(style));
478 return createRenderer<RenderSVGViewportContainer>(*this, WTF::move(style));
481 Node::InsertionNotificationRequest SVGSVGElement::insertedInto(ContainerNode& rootParent)
483 if (rootParent.inDocument()) {
484 document().accessSVGExtensions().addTimeContainer(this);
486 // Animations are started at the end of document parsing and after firing the load event,
487 // but if we miss that train (deferred programmatic element insertion for example) we need
488 // to initialize the time container here.
489 if (!document().parsing() && !document().processingLoadEvent() && document().loadEventFinished() && !timeContainer()->isStarted())
490 timeContainer()->begin();
492 return SVGGraphicsElement::insertedInto(rootParent);
495 void SVGSVGElement::removedFrom(ContainerNode& rootParent)
497 if (rootParent.inDocument())
498 document().accessSVGExtensions().removeTimeContainer(this);
499 SVGGraphicsElement::removedFrom(rootParent);
502 void SVGSVGElement::pauseAnimations()
504 if (!m_timeContainer->isPaused())
505 m_timeContainer->pause();
508 void SVGSVGElement::unpauseAnimations()
510 if (m_timeContainer->isPaused())
511 m_timeContainer->resume();
514 bool SVGSVGElement::animationsPaused() const
516 return m_timeContainer->isPaused();
519 float SVGSVGElement::getCurrentTime() const
521 return narrowPrecisionToFloat(m_timeContainer->elapsed().value());
524 void SVGSVGElement::setCurrentTime(float seconds)
526 if (std::isnan(seconds))
528 seconds = std::max(seconds, 0.0f);
529 m_timeContainer->setElapsed(seconds);
532 bool SVGSVGElement::selfHasRelativeLengths() const
534 return x().isRelative()
536 || width().isRelative()
537 || height().isRelative()
538 || hasAttribute(SVGNames::viewBoxAttr);
541 FloatRect SVGSVGElement::currentViewBoxRect() const
543 if (m_useCurrentView)
544 return m_viewSpec ? m_viewSpec->viewBox() : FloatRect();
546 FloatRect useViewBox = viewBox();
547 if (!useViewBox.isEmpty())
549 if (!renderer() || !renderer()->isSVGRoot())
551 if (!toRenderSVGRoot(renderer())->isEmbeddedThroughSVGImage())
554 Length intrinsicWidth = this->intrinsicWidth();
555 Length intrinsicHeight = this->intrinsicHeight();
556 if (!intrinsicWidth.isFixed() || !intrinsicHeight.isFixed())
559 // If no viewBox is specified but non-relative width/height values, then we
560 // should always synthesize a viewBox if we're embedded through a SVGImage.
561 return FloatRect(FloatPoint(), FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0)));
564 FloatSize SVGSVGElement::currentViewportSize() const
566 if (hasIntrinsicWidth() && hasIntrinsicHeight()) {
567 Length intrinsicWidth = this->intrinsicWidth();
568 Length intrinsicHeight = this->intrinsicHeight();
569 return FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0));
575 if (renderer()->isSVGRoot()) {
576 LayoutRect contentBoxRect = toRenderSVGRoot(renderer())->contentBoxRect();
577 return FloatSize(contentBoxRect.width() / renderer()->style().effectiveZoom(), contentBoxRect.height() / renderer()->style().effectiveZoom());
580 FloatRect viewportRect = toRenderSVGViewportContainer(renderer())->viewport();
581 return FloatSize(viewportRect.width(), viewportRect.height());
584 bool SVGSVGElement::hasIntrinsicWidth() const
586 return width().unitType() != LengthTypePercentage;
589 bool SVGSVGElement::hasIntrinsicHeight() const
591 return height().unitType() != LengthTypePercentage;
594 Length SVGSVGElement::intrinsicWidth() const
596 if (width().unitType() == LengthTypePercentage)
597 return Length(0, Fixed);
599 SVGLengthContext lengthContext(this);
600 return Length(width().value(lengthContext), Fixed);
603 Length SVGSVGElement::intrinsicHeight() const
605 if (height().unitType() == LengthTypePercentage)
606 return Length(0, Fixed);
608 SVGLengthContext lengthContext(this);
609 return Length(height().value(lengthContext), Fixed);
612 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const
614 if (!m_useCurrentView || !m_viewSpec)
615 return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), preserveAspectRatio(), viewWidth, viewHeight);
617 AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), m_viewSpec->preserveAspectRatio(), viewWidth, viewHeight);
618 const SVGTransformList& transformList = m_viewSpec->transformBaseValue();
619 if (transformList.isEmpty())
622 AffineTransform transform;
623 if (transformList.concatenate(transform))
629 void SVGSVGElement::setupInitialView(const String& fragmentIdentifier, Element* anchorNode)
631 auto renderer = this->renderer();
632 SVGViewSpec* view = m_viewSpec.get();
636 bool hadUseCurrentView = m_useCurrentView;
637 m_useCurrentView = false;
639 if (fragmentIdentifier.startsWith("xpointer(")) {
640 // FIXME: XPointer references are ignored (https://bugs.webkit.org/show_bug.cgi?id=17491)
641 if (renderer && hadUseCurrentView)
642 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
646 if (fragmentIdentifier.startsWith("svgView(")) {
648 view = currentView(); // Create the SVGViewSpec.
650 if (view->parseViewSpec(fragmentIdentifier))
651 m_useCurrentView = true;
655 if (renderer && (hadUseCurrentView || m_useCurrentView))
656 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
660 // Spec: If the SVG fragment identifier addresses a ‘view’ element within an SVG document (e.g., MyDrawing.svg#MyView
661 // or MyDrawing.svg#xpointer(id('MyView'))) then the closest ancestor ‘svg’ element is displayed in the viewport.
662 // Any view specification attributes included on the given ‘view’ element override the corresponding view specification
663 // attributes on the closest ancestor ‘svg’ element.
664 if (anchorNode && isSVGViewElement(anchorNode)) {
665 SVGViewElement& viewElement = downcast<SVGViewElement>(*anchorNode);
666 SVGElement* element = SVGLocatable::nearestViewportElement(&viewElement);
667 if (isSVGSVGElement(element)) {
668 SVGSVGElement& svg = downcast<SVGSVGElement>(*element);
669 svg.inheritViewAttributes(&viewElement);
671 if (RenderElement* renderer = svg.renderer())
672 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
677 // FIXME: We need to decide which <svg> to focus on, and zoom to it.
678 // FIXME: We need to actually "highlight" the viewTarget(s).
681 void SVGSVGElement::inheritViewAttributes(SVGViewElement* viewElement)
683 SVGViewSpec* view = currentView();
684 m_useCurrentView = true;
686 if (viewElement->hasAttribute(SVGNames::viewBoxAttr))
687 view->setViewBoxBaseValue(viewElement->viewBox());
689 view->setViewBoxBaseValue(viewBox());
691 if (viewElement->hasAttribute(SVGNames::preserveAspectRatioAttr))
692 view->setPreserveAspectRatioBaseValue(viewElement->preserveAspectRatioBaseValue());
694 view->setPreserveAspectRatioBaseValue(preserveAspectRatioBaseValue());
696 if (viewElement->hasAttribute(SVGNames::zoomAndPanAttr))
697 view->setZoomAndPanBaseValue(viewElement->zoomAndPan());
699 view->setZoomAndPanBaseValue(zoomAndPan());
702 void SVGSVGElement::documentWillSuspendForPageCache()
707 void SVGSVGElement::documentDidResumeFromPageCache()
712 // getElementById on SVGSVGElement is restricted to only the child subtree defined by the <svg> element.
713 // See http://www.w3.org/TR/SVG11/struct.html#InterfaceSVGSVGElement
714 Element* SVGSVGElement::getElementById(const String& id)
716 Element* element = treeScope().getElementById(id);
717 if (element && element->isDescendantOf(this))
720 // FIXME: This should use treeScope().getAllElementsById.
721 // Fall back to traversing our subtree. Duplicate ids are allowed, the first found will
723 for (auto& element : descendantsOfType<Element>(*this)) {
724 if (element.getIdAttribute() == id)