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 WebCore { 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 ScriptWrappable::init(this); 41 42 addToPropertyMap(m_x); 43 addToPropertyMap(m_y); 44 addToPropertyMap(m_width); 45 addToPropertyMap(m_height); 46 47 UseCounter::count(document, UseCounter::SVGForeignObjectElement); 48 } 49 50 DEFINE_NODE_FACTORY(SVGForeignObjectElement) 51 52 bool SVGForeignObjectElement::isSupportedAttribute(const QualifiedName& attrName) 53 { 54 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 55 if (supportedAttributes.isEmpty()) { 56 supportedAttributes.add(SVGNames::xAttr); 57 supportedAttributes.add(SVGNames::yAttr); 58 supportedAttributes.add(SVGNames::widthAttr); 59 supportedAttributes.add(SVGNames::heightAttr); 60 } 61 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 62 } 63 64 void SVGForeignObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 65 { 66 SVGParsingError parseError = NoError; 67 68 if (!isSupportedAttribute(name)) 69 SVGGraphicsElement::parseAttribute(name, value); 70 else if (name == SVGNames::xAttr) 71 m_x->setBaseValueAsString(value, parseError); 72 else if (name == SVGNames::yAttr) 73 m_y->setBaseValueAsString(value, parseError); 74 else if (name == SVGNames::widthAttr) 75 m_width->setBaseValueAsString(value, parseError); 76 else if (name == SVGNames::heightAttr) 77 m_height->setBaseValueAsString(value, parseError); 78 else 79 ASSERT_NOT_REACHED(); 80 81 reportAttributeParsingError(parseError, name, value); 82 } 83 84 bool SVGForeignObjectElement::isPresentationAttribute(const QualifiedName& name) const 85 { 86 if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) 87 return true; 88 return SVGGraphicsElement::isPresentationAttribute(name); 89 } 90 91 void SVGForeignObjectElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 92 { 93 if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) { 94 RefPtr<SVGLength> length = SVGLength::create(LengthModeOther); 95 TrackExceptionState exceptionState; 96 length->setValueAsString(value, exceptionState); 97 if (!exceptionState.hadException()) { 98 if (name == SVGNames::widthAttr) 99 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value); 100 else if (name == SVGNames::heightAttr) 101 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value); 102 } 103 } else { 104 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style); 105 } 106 } 107 108 void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) 109 { 110 if (!isSupportedAttribute(attrName)) { 111 SVGGraphicsElement::svgAttributeChanged(attrName); 112 return; 113 } 114 115 if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) { 116 invalidateSVGPresentationAttributeStyle(); 117 setNeedsStyleRecalc(LocalStyleChange); 118 } 119 120 SVGElement::InvalidationGuard invalidationGuard(this); 121 122 bool isLengthAttribute = attrName == SVGNames::xAttr 123 || attrName == SVGNames::yAttr 124 || attrName == SVGNames::widthAttr 125 || attrName == SVGNames::heightAttr; 126 127 if (isLengthAttribute) 128 updateRelativeLengthsInformation(); 129 130 if (RenderObject* renderer = this->renderer()) 131 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 132 } 133 134 RenderObject* SVGForeignObjectElement::createRenderer(RenderStyle*) 135 { 136 return new RenderSVGForeignObject(this); 137 } 138 139 bool SVGForeignObjectElement::rendererIsNeeded(const RenderStyle& style) 140 { 141 // Suppress foreignObject renderers in SVG hidden containers. 142 // (https://bugs.webkit.org/show_bug.cgi?id=87297) 143 // Note that we currently do not support foreignObject instantiation via <use>, hence it is safe 144 // to use parentElement() here. If that changes, this method should be updated to use 145 // parentOrShadowHostElement() instead. 146 Element* ancestor = parentElement(); 147 while (ancestor && ancestor->isSVGElement()) { 148 if (ancestor->renderer() && ancestor->renderer()->isSVGHiddenContainer()) 149 return false; 150 151 ancestor = ancestor->parentElement(); 152 } 153 154 return SVGGraphicsElement::rendererIsNeeded(style); 155 } 156 157 bool SVGForeignObjectElement::selfHasRelativeLengths() const 158 { 159 return m_x->currentValue()->isRelative() 160 || m_y->currentValue()->isRelative() 161 || m_width->currentValue()->isRelative() 162 || m_height->currentValue()->isRelative(); 163 } 164 165 } 166