1/* 2 * Copyright (C) 2006 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21#include "config.h" 22#include "SVGForeignObjectElement.h" 23 24#include "Attribute.h" 25#include "CSSPropertyNames.h" 26#include "RenderSVGForeignObject.h" 27#include "RenderSVGResource.h" 28#include "SVGElementInstance.h" 29#include "SVGLength.h" 30#include "SVGNames.h" 31#include "XLinkNames.h" 32#include <wtf/Assertions.h> 33#include <wtf/NeverDestroyed.h> 34 35namespace WebCore { 36 37// Animated property definitions 38DEFINE_ANIMATED_LENGTH(SVGForeignObjectElement, SVGNames::xAttr, X, x) 39DEFINE_ANIMATED_LENGTH(SVGForeignObjectElement, SVGNames::yAttr, Y, y) 40DEFINE_ANIMATED_LENGTH(SVGForeignObjectElement, SVGNames::widthAttr, Width, width) 41DEFINE_ANIMATED_LENGTH(SVGForeignObjectElement, SVGNames::heightAttr, Height, height) 42DEFINE_ANIMATED_STRING(SVGForeignObjectElement, XLinkNames::hrefAttr, Href, href) 43DEFINE_ANIMATED_BOOLEAN(SVGForeignObjectElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 44 45BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGForeignObjectElement) 46 REGISTER_LOCAL_ANIMATED_PROPERTY(x) 47 REGISTER_LOCAL_ANIMATED_PROPERTY(y) 48 REGISTER_LOCAL_ANIMATED_PROPERTY(width) 49 REGISTER_LOCAL_ANIMATED_PROPERTY(height) 50 REGISTER_LOCAL_ANIMATED_PROPERTY(href) 51 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 52 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement) 53END_REGISTER_ANIMATED_PROPERTIES 54 55inline SVGForeignObjectElement::SVGForeignObjectElement(const QualifiedName& tagName, Document& document) 56 : SVGGraphicsElement(tagName, document) 57 , m_x(LengthModeWidth) 58 , m_y(LengthModeHeight) 59 , m_width(LengthModeWidth) 60 , m_height(LengthModeHeight) 61{ 62 ASSERT(hasTagName(SVGNames::foreignObjectTag)); 63 registerAnimatedPropertiesForSVGForeignObjectElement(); 64} 65 66PassRefPtr<SVGForeignObjectElement> SVGForeignObjectElement::create(const QualifiedName& tagName, Document& document) 67{ 68 return adoptRef(new SVGForeignObjectElement(tagName, document)); 69} 70 71bool SVGForeignObjectElement::isSupportedAttribute(const QualifiedName& attrName) 72{ 73 static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes; 74 if (supportedAttributes.get().isEmpty()) { 75 SVGLangSpace::addSupportedAttributes(supportedAttributes); 76 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 77 supportedAttributes.get().add(SVGNames::xAttr); 78 supportedAttributes.get().add(SVGNames::yAttr); 79 supportedAttributes.get().add(SVGNames::widthAttr); 80 supportedAttributes.get().add(SVGNames::heightAttr); 81 } 82 return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName); 83} 84 85void SVGForeignObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 86{ 87 SVGParsingError parseError = NoError; 88 89 if (!isSupportedAttribute(name)) 90 SVGGraphicsElement::parseAttribute(name, value); 91 else if (name == SVGNames::xAttr) 92 setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 93 else if (name == SVGNames::yAttr) 94 setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 95 else if (name == SVGNames::widthAttr) 96 setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 97 else if (name == SVGNames::heightAttr) 98 setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 99 else if (SVGLangSpace::parseAttribute(name, value) 100 || SVGExternalResourcesRequired::parseAttribute(name, value)) { 101 } else 102 ASSERT_NOT_REACHED(); 103 104 reportAttributeParsingError(parseError, name, value); 105} 106 107void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) 108{ 109 if (!isSupportedAttribute(attrName)) { 110 SVGGraphicsElement::svgAttributeChanged(attrName); 111 return; 112 } 113 114 SVGElementInstance::InvalidationGuard invalidationGuard(this); 115 116 bool isLengthAttribute = attrName == SVGNames::xAttr 117 || attrName == SVGNames::yAttr 118 || attrName == SVGNames::widthAttr 119 || attrName == SVGNames::heightAttr; 120 121 if (isLengthAttribute) 122 updateRelativeLengthsInformation(); 123 124 if (auto renderer = this->renderer()) 125 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer); 126} 127 128RenderPtr<RenderElement> SVGForeignObjectElement::createElementRenderer(PassRef<RenderStyle> style) 129{ 130 return createRenderer<RenderSVGForeignObject>(*this, WTF::move(style)); 131} 132 133bool SVGForeignObjectElement::childShouldCreateRenderer(const Node& child) const 134{ 135 // Disallow arbitary SVG content. Only allow proper <svg xmlns="svgNS"> subdocuments. 136 if (child.isSVGElement()) 137 return child.hasTagName(SVGNames::svgTag); 138 139 // Skip over SVG rules which disallow non-SVG kids 140 return StyledElement::childShouldCreateRenderer(child); 141} 142 143bool SVGForeignObjectElement::rendererIsNeeded(const RenderStyle& style) 144{ 145 // Suppress foreignObject renderers in SVG hidden containers. 146 // (https://bugs.webkit.org/show_bug.cgi?id=87297) 147 // Note that we currently do not support foreignObject instantiation via <use>, hence it is safe 148 // to use parentElement() here. If that changes, this method should be updated to use 149 // parentOrShadowHostElement() instead. 150 Element* ancestor = parentElement(); 151 while (ancestor && ancestor->isSVGElement()) { 152 if (ancestor->renderer() && ancestor->renderer()->isSVGHiddenContainer()) 153 return false; 154 155 ancestor = ancestor->parentElement(); 156 } 157 158 return SVGGraphicsElement::rendererIsNeeded(style); 159} 160 161bool SVGForeignObjectElement::selfHasRelativeLengths() const 162{ 163 return x().isRelative() 164 || y().isRelative() 165 || width().isRelative() 166 || height().isRelative(); 167} 168 169} 170