1/* 2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 4 * Copyright (C) 2005 Alexander Kellett <lypanov@kde.org> 5 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24#include "config.h" 25#include "SVGMaskElement.h" 26 27#include "Attribute.h" 28#include "RenderSVGResourceMasker.h" 29#include "SVGElementInstance.h" 30#include "SVGNames.h" 31#include "SVGRenderSupport.h" 32#include "SVGUnitTypes.h" 33#include "StyleResolver.h" 34#include <wtf/NeverDestroyed.h> 35 36namespace WebCore { 37 38// Animated property definitions 39DEFINE_ANIMATED_ENUMERATION(SVGMaskElement, SVGNames::maskUnitsAttr, MaskUnits, maskUnits, SVGUnitTypes::SVGUnitType) 40DEFINE_ANIMATED_ENUMERATION(SVGMaskElement, SVGNames::maskContentUnitsAttr, MaskContentUnits, maskContentUnits, SVGUnitTypes::SVGUnitType) 41DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::xAttr, X, x) 42DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::yAttr, Y, y) 43DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::widthAttr, Width, width) 44DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::heightAttr, Height, height) 45DEFINE_ANIMATED_BOOLEAN(SVGMaskElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 46 47BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMaskElement) 48 REGISTER_LOCAL_ANIMATED_PROPERTY(maskUnits) 49 REGISTER_LOCAL_ANIMATED_PROPERTY(maskContentUnits) 50 REGISTER_LOCAL_ANIMATED_PROPERTY(x) 51 REGISTER_LOCAL_ANIMATED_PROPERTY(y) 52 REGISTER_LOCAL_ANIMATED_PROPERTY(width) 53 REGISTER_LOCAL_ANIMATED_PROPERTY(height) 54 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 55 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement) 56 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests) 57END_REGISTER_ANIMATED_PROPERTIES 58 59inline SVGMaskElement::SVGMaskElement(const QualifiedName& tagName, Document& document) 60 : SVGElement(tagName, document) 61 , m_maskUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) 62 , m_maskContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) 63 , m_x(LengthModeWidth, "-10%") 64 , m_y(LengthModeHeight, "-10%") 65 , m_width(LengthModeWidth, "120%") 66 , m_height(LengthModeHeight, "120%") 67{ 68 // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified. 69 // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified. 70 ASSERT(hasTagName(SVGNames::maskTag)); 71 registerAnimatedPropertiesForSVGMaskElement(); 72} 73 74PassRefPtr<SVGMaskElement> SVGMaskElement::create(const QualifiedName& tagName, Document& document) 75{ 76 return adoptRef(new SVGMaskElement(tagName, document)); 77} 78 79bool SVGMaskElement::isSupportedAttribute(const QualifiedName& attrName) 80{ 81 static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes; 82 if (supportedAttributes.get().isEmpty()) { 83 SVGTests::addSupportedAttributes(supportedAttributes); 84 SVGLangSpace::addSupportedAttributes(supportedAttributes); 85 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 86 supportedAttributes.get().add(SVGNames::maskUnitsAttr); 87 supportedAttributes.get().add(SVGNames::maskContentUnitsAttr); 88 supportedAttributes.get().add(SVGNames::xAttr); 89 supportedAttributes.get().add(SVGNames::yAttr); 90 supportedAttributes.get().add(SVGNames::widthAttr); 91 supportedAttributes.get().add(SVGNames::heightAttr); 92 } 93 return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName); 94} 95 96void SVGMaskElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 97{ 98 SVGParsingError parseError = NoError; 99 100 if (!isSupportedAttribute(name)) 101 SVGElement::parseAttribute(name, value); 102 else if (name == SVGNames::maskUnitsAttr) { 103 SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); 104 if (propertyValue > 0) 105 setMaskUnitsBaseValue(propertyValue); 106 return; 107 } else if (name == SVGNames::maskContentUnitsAttr) { 108 SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); 109 if (propertyValue > 0) 110 setMaskContentUnitsBaseValue(propertyValue); 111 return; 112 } else if (name == SVGNames::xAttr) 113 setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 114 else if (name == SVGNames::yAttr) 115 setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 116 else if (name == SVGNames::widthAttr) 117 setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 118 else if (name == SVGNames::heightAttr) 119 setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 120 else if (SVGTests::parseAttribute(name, value) 121 || SVGLangSpace::parseAttribute(name, value) 122 || SVGExternalResourcesRequired::parseAttribute(name, value)) { 123 } else 124 ASSERT_NOT_REACHED(); 125 126 reportAttributeParsingError(parseError, name, value); 127} 128 129void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) 130{ 131 if (!isSupportedAttribute(attrName)) { 132 SVGElement::svgAttributeChanged(attrName); 133 return; 134 } 135 136 SVGElementInstance::InvalidationGuard invalidationGuard(this); 137 138 if (attrName == SVGNames::xAttr 139 || attrName == SVGNames::yAttr 140 || attrName == SVGNames::widthAttr 141 || attrName == SVGNames::heightAttr) 142 updateRelativeLengthsInformation(); 143 144 if (RenderObject* object = renderer()) 145 object->setNeedsLayout(); 146} 147 148void SVGMaskElement::childrenChanged(const ChildChange& change) 149{ 150 SVGElement::childrenChanged(change); 151 152 if (change.source == ChildChangeSourceParser) 153 return; 154 155 if (RenderObject* object = renderer()) 156 object->setNeedsLayout(); 157} 158 159RenderPtr<RenderElement> SVGMaskElement::createElementRenderer(PassRef<RenderStyle> style) 160{ 161 return createRenderer<RenderSVGResourceMasker>(*this, WTF::move(style)); 162} 163 164bool SVGMaskElement::selfHasRelativeLengths() const 165{ 166 return x().isRelative() 167 || y().isRelative() 168 || width().isRelative() 169 || height().isRelative(); 170} 171 172} 173