1 /* 2 * Copyright (C) 2006 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann (at) 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 "core/svg/SVGForeignObjectElement.h" 23 24 #include "core/XLinkNames.h" 25 #include "core/frame/UseCounter.h" 26 #include "core/rendering/svg/RenderSVGForeignObject.h" 27 #include "core/rendering/svg/RenderSVGResource.h" 28 #include "core/svg/SVGLength.h" 29 #include "wtf/Assertions.h" 30 31 namespace blink { 32 33 inline SVGForeignObjectElement::SVGForeignObjectElement(Document& document) 34 : SVGGraphicsElement(SVGNames::foreignObjectTag, document) 35 , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths)) 36 , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths)) 37 , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths)) 38 , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths)) 39 { 40 addToPropertyMap(m_x); 41 addToPropertyMap(m_y); 42 addToPropertyMap(m_width); 43 addToPropertyMap(m_height); 44 45 UseCounter::count(document, UseCounter::SVGForeignObjectElement); 46 } 47 48 DEFINE_NODE_FACTORY(SVGForeignObjectElement) 49 50 bool SVGForeignObjectElement::isSupportedAttribute(const QualifiedName& attrName) 51 { 52 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 53 if (supportedAttributes.isEmpty()) { 54 supportedAttributes.add(SVGNames::xAttr); 55 supportedAttributes.add(SVGNames::yAttr); 56 supportedAttributes.add(SVGNames::widthAttr); 57 supportedAttributes.add(SVGNames::heightAttr); 58 } 59 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 60 } 61 62 void SVGForeignObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 63 { 64 parseAttributeNew(name, value); 65 } 66 67 bool SVGForeignObjectElement::isPresentationAttribute(const QualifiedName& name) const 68 { 69 if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) 70 return true; 71 return SVGGraphicsElement::isPresentationAttribute(name); 72 } 73 74 void SVGForeignObjectElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 75 { 76 if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) { 77 RefPtr<SVGLength> length = SVGLength::create(LengthModeOther); 78 TrackExceptionState exceptionState; 79 length->setValueAsString(value, exceptionState); 80 if (!exceptionState.hadException()) { 81 if (name == SVGNames::widthAttr) 82 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value); 83 else if (name == SVGNames::heightAttr) 84 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value); 85 } 86 } else { 87 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style); 88 } 89 } 90 91 void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) 92 { 93 if (!isSupportedAttribute(attrName)) { 94 SVGGraphicsElement::svgAttributeChanged(attrName); 95 return; 96 } 97 98 if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) { 99 invalidateSVGPresentationAttributeStyle(); 100 setNeedsStyleRecalc(LocalStyleChange); 101 } 102 103 SVGElement::InvalidationGuard invalidationGuard(this); 104 105 bool isLengthAttribute = attrName == SVGNames::xAttr 106 || attrName == SVGNames::yAttr 107 || attrName == SVGNames::widthAttr 108 || attrName == SVGNames::heightAttr; 109 110 if (isLengthAttribute) 111 updateRelativeLengthsInformation(); 112 113 if (RenderObject* renderer = this->renderer()) 114 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 115 } 116 117 RenderObject* SVGForeignObjectElement::createRenderer(RenderStyle*) 118 { 119 return new RenderSVGForeignObject(this); 120 } 121 122 bool SVGForeignObjectElement::rendererIsNeeded(const RenderStyle& style) 123 { 124 // Suppress foreignObject renderers in SVG hidden containers. 125 // (https://bugs.webkit.org/show_bug.cgi?id=87297) 126 // Note that we currently do not support foreignObject instantiation via <use>, hence it is safe 127 // to use parentElement() here. If that changes, this method should be updated to use 128 // parentOrShadowHostElement() instead. 129 Element* ancestor = parentElement(); 130 while (ancestor && ancestor->isSVGElement()) { 131 if (ancestor->renderer() && ancestor->renderer()->isSVGHiddenContainer()) 132 return false; 133 134 ancestor = ancestor->parentElement(); 135 } 136 137 return SVGGraphicsElement::rendererIsNeeded(style); 138 } 139 140 bool SVGForeignObjectElement::selfHasRelativeLengths() const 141 { 142 return m_x->currentValue()->isRelative() 143 || m_y->currentValue()->isRelative() 144 || m_width->currentValue()->isRelative() 145 || m_height->currentValue()->isRelative(); 146 } 147 148 } // namespace blink 149