1/* 2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@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 "SVGTests.h" 23 24#include "Attribute.h" 25#include "DOMImplementation.h" 26#include "HTMLNames.h" 27#include "Language.h" 28#include "SVGElement.h" 29#include "SVGNames.h" 30#include "SVGStringList.h" 31#include <wtf/NeverDestroyed.h> 32 33#if ENABLE(MATHML) 34#include "MathMLNames.h" 35#endif 36 37namespace WebCore { 38 39// Define custom non-animated property 'requiredFeatures'. 40const SVGPropertyInfo* SVGTests::requiredFeaturesPropertyInfo() 41{ 42 static const SVGPropertyInfo* s_propertyInfo = 0; 43 if (!s_propertyInfo) { 44 s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown, 45 PropertyIsReadWrite, 46 SVGNames::requiredFeaturesAttr, 47 SVGNames::requiredFeaturesAttr.localName(), 48 &SVGElement::synchronizeRequiredFeatures, 49 0); 50 } 51 return s_propertyInfo; 52} 53 54// Define custom non-animated property 'requiredExtensions'. 55const SVGPropertyInfo* SVGTests::requiredExtensionsPropertyInfo() 56{ 57 static const SVGPropertyInfo* s_propertyInfo = 0; 58 if (!s_propertyInfo) { 59 s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown, 60 PropertyIsReadWrite, 61 SVGNames::requiredExtensionsAttr, 62 SVGNames::requiredExtensionsAttr.localName(), 63 &SVGElement::synchronizeRequiredExtensions, 64 0); 65 } 66 return s_propertyInfo; 67} 68 69// Define custom non-animated property 'systemLanguage'. 70const SVGPropertyInfo* SVGTests::systemLanguagePropertyInfo() 71{ 72 static const SVGPropertyInfo* s_propertyInfo = 0; 73 if (!s_propertyInfo) { 74 s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown, 75 PropertyIsReadWrite, 76 SVGNames::systemLanguageAttr, 77 SVGNames::systemLanguageAttr.localName(), 78 &SVGElement::synchronizeSystemLanguage, 79 0); 80 } 81 return s_propertyInfo; 82} 83 84SVGTests::SVGTests() 85 : m_requiredFeatures(SVGNames::requiredFeaturesAttr) 86 , m_requiredExtensions(SVGNames::requiredExtensionsAttr) 87 , m_systemLanguage(SVGNames::systemLanguageAttr) 88{ 89} 90 91SVGAttributeToPropertyMap& SVGTests::attributeToPropertyMap() 92{ 93 static NeverDestroyed<SVGAttributeToPropertyMap> map; 94 if (!map.get().isEmpty()) 95 return map; 96 map.get().addProperty(requiredFeaturesPropertyInfo()); 97 map.get().addProperty(requiredExtensionsPropertyInfo()); 98 map.get().addProperty(systemLanguagePropertyInfo()); 99 return map; 100} 101 102bool SVGTests::hasExtension(const String& extension) const 103{ 104 // We recognize XHTML and MathML, as implemented in Gecko and suggested in the SVG Tiny recommendation (http://www.w3.org/TR/SVG11/struct.html#RequiredExtensionsAttribute). 105#if ENABLE(MATHML) 106 return extension == HTMLNames::xhtmlNamespaceURI || extension == MathMLNames::mathmlNamespaceURI; 107#else 108 return extension == HTMLNames::xhtmlNamespaceURI; 109#endif 110} 111 112bool SVGTests::isValid() const 113{ 114 for (auto& feature : m_requiredFeatures.value) { 115 if (feature.isEmpty() || !DOMImplementation::hasFeature(feature, String())) 116 return false; 117 } 118 119 for (auto& language : m_systemLanguage.value) { 120 if (language != defaultLanguage().substring(0, 2)) 121 return false; 122 } 123 124 for (auto& extension : m_requiredExtensions.value) { 125 if (!hasExtension(extension)) 126 return false; 127 } 128 129 return true; 130} 131 132bool SVGTests::parseAttribute(const QualifiedName& name, const AtomicString& value) 133{ 134 if (name == SVGNames::requiredFeaturesAttr) { 135 m_requiredFeatures.value.reset(value); 136 return true; 137 } 138 if (name == SVGNames::requiredExtensionsAttr) { 139 m_requiredExtensions.value.reset(value); 140 return true; 141 } 142 if (name == SVGNames::systemLanguageAttr) { 143 m_systemLanguage.value.reset(value); 144 return true; 145 } 146 147 return false; 148} 149 150bool SVGTests::isKnownAttribute(const QualifiedName& attrName) 151{ 152 return attrName == SVGNames::requiredFeaturesAttr 153 || attrName == SVGNames::requiredExtensionsAttr 154 || attrName == SVGNames::systemLanguageAttr; 155} 156 157bool SVGTests::handleAttributeChange(SVGElement* targetElement, const QualifiedName& attrName) 158{ 159 ASSERT(targetElement); 160 if (!isKnownAttribute(attrName)) 161 return false; 162 if (!targetElement->inDocument()) 163 return true; 164 165 targetElement->setNeedsStyleRecalc(ReconstructRenderTree); 166 167 return true; 168} 169 170void SVGTests::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes) 171{ 172 supportedAttributes.add(SVGNames::requiredFeaturesAttr); 173 supportedAttributes.add(SVGNames::requiredExtensionsAttr); 174 supportedAttributes.add(SVGNames::systemLanguageAttr); 175} 176 177void SVGTests::synchronizeRequiredFeatures(SVGElement* contextElement) 178{ 179 ASSERT(contextElement); 180 if (!m_requiredFeatures.shouldSynchronize) 181 return; 182 AtomicString value(m_requiredFeatures.value.valueAsString()); 183 m_requiredFeatures.synchronize(contextElement, requiredFeaturesPropertyInfo()->attributeName, value); 184} 185 186void SVGTests::synchronizeRequiredExtensions(SVGElement* contextElement) 187{ 188 ASSERT(contextElement); 189 if (!m_requiredExtensions.shouldSynchronize) 190 return; 191 AtomicString value(m_requiredExtensions.value.valueAsString()); 192 m_requiredExtensions.synchronize(contextElement, requiredExtensionsPropertyInfo()->attributeName, value); 193} 194 195void SVGTests::synchronizeSystemLanguage(SVGElement* contextElement) 196{ 197 ASSERT(contextElement); 198 if (!m_systemLanguage.shouldSynchronize) 199 return; 200 AtomicString value(m_systemLanguage.value.valueAsString()); 201 m_systemLanguage.synchronize(contextElement, systemLanguagePropertyInfo()->attributeName, value); 202} 203 204SVGStringList& SVGTests::requiredFeatures() 205{ 206 m_requiredFeatures.shouldSynchronize = true; 207 return m_requiredFeatures.value; 208} 209 210SVGStringList& SVGTests::requiredExtensions() 211{ 212 m_requiredExtensions.shouldSynchronize = true; 213 return m_requiredExtensions.value; 214} 215 216SVGStringList& SVGTests::systemLanguage() 217{ 218 m_systemLanguage.shouldSynchronize = true; 219 return m_systemLanguage.value; 220} 221 222} 223