1 /* 2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2005 Alexander Kellett <lypanov (at) kde.org> 5 * Copyright (C) 2009 Dirk Schulze <krit (at) 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 26 #include "core/svg/SVGMaskElement.h" 27 28 #include "core/rendering/svg/RenderSVGResourceMasker.h" 29 #include "core/svg/SVGElementInstance.h" 30 31 namespace WebCore { 32 33 // Animated property definitions 34 DEFINE_ANIMATED_ENUMERATION(SVGMaskElement, SVGNames::maskUnitsAttr, MaskUnits, maskUnits, SVGUnitTypes::SVGUnitType) 35 DEFINE_ANIMATED_ENUMERATION(SVGMaskElement, SVGNames::maskContentUnitsAttr, MaskContentUnits, maskContentUnits, SVGUnitTypes::SVGUnitType) 36 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::xAttr, X, x) 37 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::yAttr, Y, y) 38 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::widthAttr, Width, width) 39 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::heightAttr, Height, height) 40 DEFINE_ANIMATED_BOOLEAN(SVGMaskElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 41 42 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMaskElement) 43 REGISTER_LOCAL_ANIMATED_PROPERTY(maskUnits) 44 REGISTER_LOCAL_ANIMATED_PROPERTY(maskContentUnits) 45 REGISTER_LOCAL_ANIMATED_PROPERTY(x) 46 REGISTER_LOCAL_ANIMATED_PROPERTY(y) 47 REGISTER_LOCAL_ANIMATED_PROPERTY(width) 48 REGISTER_LOCAL_ANIMATED_PROPERTY(height) 49 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 50 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement) 51 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests) 52 END_REGISTER_ANIMATED_PROPERTIES 53 54 inline SVGMaskElement::SVGMaskElement(Document& document) 55 : SVGElement(SVGNames::maskTag, document) 56 , m_maskUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) 57 , m_maskContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) 58 , m_x(LengthModeWidth, "-10%") 59 , m_y(LengthModeHeight, "-10%") 60 , m_width(LengthModeWidth, "120%") 61 , m_height(LengthModeHeight, "120%") 62 { 63 // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified. 64 // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified. 65 ScriptWrappable::init(this); 66 registerAnimatedPropertiesForSVGMaskElement(); 67 } 68 69 PassRefPtr<SVGMaskElement> SVGMaskElement::create(Document& document) 70 { 71 return adoptRef(new SVGMaskElement(document)); 72 } 73 74 bool SVGMaskElement::isSupportedAttribute(const QualifiedName& attrName) 75 { 76 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 77 if (supportedAttributes.isEmpty()) { 78 SVGTests::addSupportedAttributes(supportedAttributes); 79 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 80 supportedAttributes.add(SVGNames::maskUnitsAttr); 81 supportedAttributes.add(SVGNames::maskContentUnitsAttr); 82 supportedAttributes.add(SVGNames::xAttr); 83 supportedAttributes.add(SVGNames::yAttr); 84 supportedAttributes.add(SVGNames::widthAttr); 85 supportedAttributes.add(SVGNames::heightAttr); 86 } 87 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 88 } 89 90 void SVGMaskElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 91 { 92 SVGParsingError parseError = NoError; 93 94 if (!isSupportedAttribute(name)) 95 SVGElement::parseAttribute(name, value); 96 else if (name == SVGNames::maskUnitsAttr) { 97 SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); 98 if (propertyValue > 0) 99 setMaskUnitsBaseValue(propertyValue); 100 return; 101 } else if (name == SVGNames::maskContentUnitsAttr) { 102 SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); 103 if (propertyValue > 0) 104 setMaskContentUnitsBaseValue(propertyValue); 105 return; 106 } else if (name == SVGNames::xAttr) 107 setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 108 else if (name == SVGNames::yAttr) 109 setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 110 else if (name == SVGNames::widthAttr) 111 setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 112 else if (name == SVGNames::heightAttr) 113 setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 114 else if (SVGTests::parseAttribute(name, value) 115 || SVGExternalResourcesRequired::parseAttribute(name, value)) { 116 } else 117 ASSERT_NOT_REACHED(); 118 119 reportAttributeParsingError(parseError, name, value); 120 } 121 122 void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) 123 { 124 if (!isSupportedAttribute(attrName)) { 125 SVGElement::svgAttributeChanged(attrName); 126 return; 127 } 128 129 SVGElementInstance::InvalidationGuard invalidationGuard(this); 130 131 if (attrName == SVGNames::xAttr 132 || attrName == SVGNames::yAttr 133 || attrName == SVGNames::widthAttr 134 || attrName == SVGNames::heightAttr) 135 updateRelativeLengthsInformation(); 136 137 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer()); 138 if (renderer) 139 renderer->invalidateCacheAndMarkForLayout(); 140 } 141 142 void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 143 { 144 SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 145 146 if (changedByParser) 147 return; 148 149 if (RenderObject* object = renderer()) 150 object->setNeedsLayout(); 151 } 152 153 RenderObject* SVGMaskElement::createRenderer(RenderStyle*) 154 { 155 return new RenderSVGResourceMasker(this); 156 } 157 158 bool SVGMaskElement::selfHasRelativeLengths() const 159 { 160 return xCurrentValue().isRelative() 161 || yCurrentValue().isRelative() 162 || widthCurrentValue().isRelative() 163 || heightCurrentValue().isRelative(); 164 } 165 166 } 167