File indexing completed on 2024-04-28 15:24:41
0001 /* 0002 Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 0003 2004, 2005, 2007 Rob Buis <buis@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "wtf/Platform.h" 0022 0023 #if ENABLE(SVG) 0024 #include "SVGStyledElement.h" 0025 0026 /*#include "Attr.h" 0027 #include "CSSParser.h" 0028 #include "CSSStyleSelector.h" 0029 #include "CString.h"*/ 0030 #include "cssstyleselector.h" 0031 #include "Document.h" 0032 /*#include "HTMLNames.h"*/ 0033 #include "PlatformString.h" 0034 /*#include "SVGElementInstance.h"*/ 0035 #include "SVGNames.h" 0036 #include "RenderObject.h" 0037 #include "SVGRenderStyle.h" 0038 /*#include "SVGResource.h"*/ 0039 #include "SVGSVGElement.h" 0040 #include <wtf/Assertions.h> 0041 0042 // khtml 0043 #include "css_base.h" 0044 0045 namespace WebCore 0046 { 0047 0048 using namespace SVGNames; 0049 using namespace DOM; 0050 0051 static HashSet<const SVGStyledElement *> *gElementsWithInstanceUpdatesBlocked = nullptr; 0052 0053 SVGStyledElement::SVGStyledElement(const QualifiedName &tagName, Document *doc) 0054 : SVGElement(tagName, doc) 0055 { 0056 } 0057 0058 SVGStyledElement::~SVGStyledElement() 0059 { 0060 // SVGResource::removeClient(this); 0061 } 0062 0063 ANIMATED_PROPERTY_DEFINITIONS(SVGStyledElement, String, String, string, ClassName, className, HTMLNames::classAttr, m_className) 0064 0065 bool SVGStyledElement::rendererIsNeeded(RenderStyle *style) 0066 { 0067 // https://www.w3.org/TR/SVG/extend.html#PrivateData 0068 // Prevent anything other than SVG renderers from appearing in our render tree 0069 // Spec: SVG allows inclusion of elements from foreign namespaces anywhere 0070 // with the SVG content. In general, the SVG user agent will include the unknown 0071 // elements in the DOM but will otherwise ignore unknown elements. 0072 if (!parentNode() || parentNode()->isSVGElement()) { 0073 return StyledElement::rendererIsNeeded(style); 0074 } 0075 0076 return false; 0077 } 0078 0079 static void mapAttributeToCSSProperty(HashMap<DOMStringImpl *, int> *propertyNameToIdMap, const QualifiedName &attrName) 0080 { 0081 /*int propertyId = cssPropertyID(attrName.localName());*/ 0082 QString propName = attrName.localName().string(); 0083 int propertyId = DOM::getPropertyID(propName.toLatin1(), propName.length()); 0084 ASSERT(propertyId > 0); 0085 propertyNameToIdMap->set(attrName.localName().implementation(), propertyId); 0086 } 0087 0088 int SVGStyledElement::cssPropertyIdForSVGAttributeName(const QualifiedName &attrName) 0089 { 0090 if (!attrName.namespaceURI().isEmpty()/*khtml fix, was isNull()*/) { 0091 return 0; 0092 } 0093 0094 // ### I think this is better redone as a switch. 0095 static HashMap<DOMStringImpl *, int> *propertyNameToIdMap = nullptr; 0096 if (!propertyNameToIdMap) { 0097 propertyNameToIdMap = new HashMap<DOMStringImpl *, int>; 0098 // This is a list of all base CSS and SVG CSS properties which are exposed as SVG XML attributes 0099 mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr); 0100 mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr); 0101 mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr); 0102 mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr); 0103 mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr); 0104 mapAttributeToCSSProperty(propertyNameToIdMap, colorAttr); 0105 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr); 0106 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filtersAttr); 0107 mapAttributeToCSSProperty(propertyNameToIdMap, color_profileAttr); 0108 mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr); 0109 mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr); 0110 mapAttributeToCSSProperty(propertyNameToIdMap, directionAttr); 0111 mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr); 0112 mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr); 0113 mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr); 0114 mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr); 0115 mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr); 0116 mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr); 0117 mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr); 0118 mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr); 0119 mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr); 0120 mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr); 0121 mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr); 0122 mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr); 0123 mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr); 0124 mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr); 0125 mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr); 0126 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizontalAttr); 0127 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_verticalAttr); 0128 mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr); 0129 mapAttributeToCSSProperty(propertyNameToIdMap, kerningAttr); 0130 mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr); 0131 mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr); 0132 mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr); 0133 mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr); 0134 mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr); 0135 mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr); 0136 mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr); 0137 mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr); 0138 mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr); 0139 mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr); 0140 mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr); 0141 mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr); 0142 mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr); 0143 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr); 0144 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr); 0145 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr); 0146 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr); 0147 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr); 0148 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr); 0149 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr); 0150 mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr); 0151 mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr); 0152 mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr); 0153 mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr); 0154 mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr); 0155 mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr); 0156 mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr); 0157 } 0158 return propertyNameToIdMap->get(attrName.localName().implementation()); 0159 } 0160 0161 /*bool SVGStyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const 0162 { 0163 if (SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName) > 0) { 0164 result = eSVG; 0165 return false; 0166 } 0167 return SVGElement::mapToEntry(attrName, result); 0168 }*/ 0169 0170 void SVGStyledElement::parseMappedAttribute(MappedAttribute *attr) 0171 { 0172 // NOTE: Any subclass which overrides parseMappedAttribute for a property handled by 0173 // cssPropertyIdForSVGAttributeName will also have to override mapToEntry to disable the default eSVG mapping 0174 int id = attr->id(); 0175 if (id == ATTR_STYLE) { 0176 if (inlineStyleDecls()) { 0177 inlineStyleDecls()->clear(); 0178 } else { 0179 createInlineDecl(); 0180 } 0181 inlineStyleDecls()->setProperty(attr->value()); 0182 setChanged(); 0183 return; 0184 } 0185 int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name()); 0186 if (propId > 0) { 0187 addCSSProperty(attr, propId, attr->value()); 0188 setChanged(); 0189 return; 0190 } 0191 0192 // id and class are handled by StyledElement 0193 SVGElement::parseMappedAttribute(attr); 0194 } 0195 0196 bool SVGStyledElement::isKnownAttribute(const QualifiedName &attrName) 0197 { 0198 // Recognize all style related SVG CSS properties 0199 int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName); 0200 if (propId > 0) { 0201 return true; 0202 } 0203 return (attrName.id() == ATTR_ID || attrName.id() == ATTR_STYLE); 0204 /*return (attrName == HTMLNames::idAttr || attrName == HTMLNames::styleAttr); */ 0205 } 0206 0207 void SVGStyledElement::svgAttributeChanged(const QualifiedName &attrName) 0208 { 0209 SVGElement::svgAttributeChanged(attrName); 0210 0211 // If we're the child of a resource element, be sure to invalidate it. 0212 invalidateResourcesInAncestorChain(); 0213 0214 SVGDocumentExtensions *extensions = document()->accessSVGExtensions(); 0215 if (!extensions) { 0216 return; 0217 } 0218 0219 // TODO: Fix bug https://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily) 0220 0221 // In case we're referenced by a <use> element, we have element instances registered 0222 // to us in the SVGDocumentExtensions. If notifyAttributeChange() is called, we need 0223 // to recursively update all children including ourselves. 0224 updateElementInstance(extensions); 0225 } 0226 0227 void SVGStyledElement::invalidateResourcesInAncestorChain() const 0228 { 0229 Node *node = parentNode(); 0230 while (node) { 0231 if (!node->isSVGElement()) { 0232 break; 0233 } 0234 0235 SVGElement *element = static_cast<SVGElement *>(node); 0236 if (SVGStyledElement *styledElement = static_cast<SVGStyledElement *>(element->isStyled() ? element : nullptr)) { 0237 /*if (SVGResource* resource = styledElement->canvasResource()) 0238 resource->invalidate();*/ 0239 } 0240 0241 node = node->parentNode(); 0242 } 0243 } 0244 0245 void SVGStyledElement::childrenChanged(bool changedByParser, Node *beforeChange, Node *afterChange, int childCountDelta) 0246 { 0247 Q_UNUSED(changedByParser); 0248 Q_UNUSED(beforeChange); 0249 Q_UNUSED(afterChange); 0250 Q_UNUSED(childCountDelta); 0251 SVGElement::childrenChanged(); 0252 /*SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 0253 if (document()->parsing()) 0254 return; 0255 0256 SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); 0257 if (!extensions) 0258 return; 0259 0260 // TODO: Fix bug https://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily) 0261 0262 // In case we're referenced by a <use> element, we have element instances registered 0263 // to us in the SVGDocumentExtensions. If childrenChanged() is called, we need 0264 // to recursively update all children including ourselves. 0265 updateElementInstance(extensions);*/ 0266 } 0267 0268 void SVGStyledElement::updateElementInstance(SVGDocumentExtensions *extensions) const 0269 { 0270 Q_UNUSED(extensions); 0271 /*if (gElementsWithInstanceUpdatesBlocked && gElementsWithInstanceUpdatesBlocked->contains(this)) 0272 return; 0273 0274 SVGStyledElement* nonConstThis = const_cast<SVGStyledElement*>(this); 0275 HashSet<SVGElementInstance*>* set = extensions->instancesForElement(nonConstThis); 0276 if (!set || set->isEmpty()) 0277 return; 0278 0279 // We need to be careful here, as the instancesForElement 0280 // hash set may be modified after we call updateInstance! 0281 HashSet<SVGElementInstance*> localCopy; 0282 0283 // First create a local copy of the hashset 0284 HashSet<SVGElementInstance*>::const_iterator it1 = set->begin(); 0285 const HashSet<SVGElementInstance*>::const_iterator end1 = set->end(); 0286 0287 for (; it1 != end1; ++it1) 0288 localCopy.add(*it1); 0289 0290 // Actually nofify instances to update 0291 HashSet<SVGElementInstance*>::const_iterator it2 = localCopy.begin(); 0292 const HashSet<SVGElementInstance*>::const_iterator end2 = localCopy.end(); 0293 0294 for (; it2 != end2; ++it2) 0295 (*it2)->updateInstance(nonConstThis);*/ 0296 } 0297 0298 RenderStyle *SVGStyledElement::resolveStyle(RenderStyle *parentStyle) 0299 { 0300 Q_UNUSED(parentStyle); 0301 if (renderer()) { 0302 RenderStyle *renderStyle = renderer()->style(); 0303 renderStyle->ref(); 0304 return renderStyle; 0305 } 0306 0307 return document()->styleSelector()->styleForElement(this/*, parentStyle*/); 0308 } 0309 0310 PassRefPtr<DOM::CSSValueImpl> SVGStyledElement::getPresentationAttribute(const String &name) 0311 { 0312 Q_UNUSED(name); 0313 /*MappedAttribute* cssSVGAttr = mappedAttributes()->getAttributeItem(name); 0314 if (!cssSVGAttr || !cssSVGAttr->style()) 0315 return 0; 0316 return cssSVGAttr->style()->getPropertyCSSValue(name);*/ 0317 Q_ASSERT(false); 0318 return new CSSPrimitiveValueImpl(0); 0319 } 0320 0321 void SVGStyledElement::detach() 0322 { 0323 /*SVGResource::removeClient(this);*/ 0324 SVGElement::detach(); 0325 } 0326 0327 void SVGStyledElement::setInstanceUpdatesBlocked(bool blockUpdates) 0328 { 0329 if (blockUpdates) { 0330 if (!gElementsWithInstanceUpdatesBlocked) { 0331 gElementsWithInstanceUpdatesBlocked = new HashSet<const SVGStyledElement *>; 0332 } 0333 gElementsWithInstanceUpdatesBlocked->add(this); 0334 } else { 0335 ASSERT(gElementsWithInstanceUpdatesBlocked); 0336 ASSERT(gElementsWithInstanceUpdatesBlocked->contains(this)); 0337 gElementsWithInstanceUpdatesBlocked->remove(this); 0338 } 0339 } 0340 0341 } 0342 0343 #endif // ENABLE(SVG)