KHTML
SVGStyledElement.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 00003 2004, 2005, 2007 Rob Buis <buis@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "config.h" 00022 #include "wtf/Platform.h" 00023 00024 #if ENABLE(SVG) 00025 #include "SVGStyledElement.h" 00026 00027 /*#include "Attr.h" 00028 #include "CSSParser.h" 00029 #include "CSSStyleSelector.h" 00030 #include "CString.h"*/ 00031 #include "cssstyleselector.h" 00032 #include "Document.h" 00033 /*#include "HTMLNames.h"*/ 00034 #include "PlatformString.h" 00035 #include "SVGElement.h" 00036 /*#include "SVGElementInstance.h"*/ 00037 #include "SVGNames.h" 00038 #include "RenderObject.h" 00039 #include "SVGRenderStyle.h" 00040 /*#include "SVGResource.h"*/ 00041 #include "SVGSVGElement.h" 00042 #include <wtf/Assertions.h> 00043 00044 // khtml 00045 #include "css_base.h" 00046 00047 00048 namespace WebCore { 00049 00050 using namespace SVGNames; 00051 using namespace DOM; 00052 00053 static HashSet<const SVGStyledElement*>* gElementsWithInstanceUpdatesBlocked = 0; 00054 00055 SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* doc) 00056 : SVGElement(tagName, doc) 00057 { 00058 } 00059 00060 SVGStyledElement::~SVGStyledElement() 00061 { 00062 // SVGResource::removeClient(this); 00063 } 00064 00065 ANIMATED_PROPERTY_DEFINITIONS(SVGStyledElement, String, String, string, ClassName, className, HTMLNames::classAttr, m_className) 00066 00067 bool SVGStyledElement::rendererIsNeeded(RenderStyle* style) 00068 { 00069 // http://www.w3.org/TR/SVG/extend.html#PrivateData 00070 // Prevent anything other than SVG renderers from appearing in our render tree 00071 // Spec: SVG allows inclusion of elements from foreign namespaces anywhere 00072 // with the SVG content. In general, the SVG user agent will include the unknown 00073 // elements in the DOM but will otherwise ignore unknown elements. 00074 if (!parentNode() || parentNode()->isSVGElement()) 00075 return StyledElement::rendererIsNeeded(style); 00076 00077 return false; 00078 } 00079 00080 static void mapAttributeToCSSProperty(HashMap<DOMStringImpl*, int>* propertyNameToIdMap, const QualifiedName& attrName) 00081 { 00082 /*int propertyId = cssPropertyID(attrName.localName());*/ 00083 QString propName = attrName.localName().string(); 00084 int propertyId = DOM::getPropertyID(propName.toLatin1(), propName.length()); 00085 ASSERT(propertyId > 0); 00086 propertyNameToIdMap->set(attrName.localName().implementation(), propertyId); 00087 } 00088 00089 int SVGStyledElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName) 00090 { 00091 if (!attrName.namespaceURI().isEmpty()/*khtml fix, was isNull()*/) 00092 return 0; 00093 00094 // ### I think this is better redone as a switch. 00095 static HashMap<DOMStringImpl*, int>* propertyNameToIdMap = 0; 00096 if (!propertyNameToIdMap) { 00097 propertyNameToIdMap = new HashMap<DOMStringImpl*, int>; 00098 // This is a list of all base CSS and SVG CSS properties which are exposed as SVG XML attributes 00099 mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr); 00100 mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr); 00101 mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr); 00102 mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr); 00103 mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr); 00104 mapAttributeToCSSProperty(propertyNameToIdMap, colorAttr); 00105 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr); 00106 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filtersAttr); 00107 mapAttributeToCSSProperty(propertyNameToIdMap, color_profileAttr); 00108 mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr); 00109 mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr); 00110 mapAttributeToCSSProperty(propertyNameToIdMap, directionAttr); 00111 mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr); 00112 mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr); 00113 mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr); 00114 mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr); 00115 mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr); 00116 mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr); 00117 mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr); 00118 mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr); 00119 mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr); 00120 mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr); 00121 mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr); 00122 mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr); 00123 mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr); 00124 mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr); 00125 mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr); 00126 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizontalAttr); 00127 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_verticalAttr); 00128 mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr); 00129 mapAttributeToCSSProperty(propertyNameToIdMap, kerningAttr); 00130 mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr); 00131 mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr); 00132 mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr); 00133 mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr); 00134 mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr); 00135 mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr); 00136 mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr); 00137 mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr); 00138 mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr); 00139 mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr); 00140 mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr); 00141 mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr); 00142 mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr); 00143 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr); 00144 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr); 00145 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr); 00146 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr); 00147 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr); 00148 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr); 00149 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr); 00150 mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr); 00151 mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr); 00152 mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr); 00153 mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr); 00154 mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr); 00155 mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr); 00156 mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr); 00157 } 00158 return propertyNameToIdMap->get(attrName.localName().implementation()); 00159 } 00160 00161 /*bool SVGStyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const 00162 { 00163 if (SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName) > 0) { 00164 result = eSVG; 00165 return false; 00166 } 00167 return SVGElement::mapToEntry(attrName, result); 00168 }*/ 00169 00170 void SVGStyledElement::parseMappedAttribute(MappedAttribute* attr) 00171 { 00172 // NOTE: Any subclass which overrides parseMappedAttribute for a property handled by 00173 // cssPropertyIdForSVGAttributeName will also have to override mapToEntry to disable the default eSVG mapping 00174 int id = attr->id(); 00175 if (id == ATTR_STYLE) { 00176 if (inlineStyleDecls()) { 00177 inlineStyleDecls()->clear(); 00178 } else { 00179 createInlineDecl(); 00180 } 00181 inlineStyleDecls()->setProperty(attr->value()); 00182 setChanged(); 00183 return; 00184 } 00185 int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name()); 00186 if (propId > 0) { 00187 addCSSProperty(attr, propId, attr->value()); 00188 setChanged(); 00189 return; 00190 } 00191 00192 // id and class are handled by StyledElement 00193 SVGElement::parseMappedAttribute(attr); 00194 } 00195 00196 bool SVGStyledElement::isKnownAttribute(const QualifiedName& attrName) 00197 { 00198 // Recognize all style related SVG CSS properties 00199 int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName); 00200 if (propId > 0) 00201 return true; 00202 return (attrName.id() == ATTR_ID || attrName.id() == ATTR_STYLE); 00203 /*return (attrName == HTMLNames::idAttr || attrName == HTMLNames::styleAttr); */ 00204 } 00205 00206 void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName) 00207 { 00208 SVGElement::svgAttributeChanged(attrName); 00209 00210 // If we're the child of a resource element, be sure to invalidate it. 00211 invalidateResourcesInAncestorChain(); 00212 00213 SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); 00214 if (!extensions) 00215 return; 00216 00217 // TODO: Fix bug http://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily) 00218 00219 // In case we're referenced by a <use> element, we have element instances registered 00220 // to us in the SVGDocumentExtensions. If notifyAttributeChange() is called, we need 00221 // to recursively update all children including ourselves. 00222 updateElementInstance(extensions); 00223 } 00224 00225 void SVGStyledElement::invalidateResourcesInAncestorChain() const 00226 { 00227 Node* node = parentNode(); 00228 while (node) { 00229 if (!node->isSVGElement()) 00230 break; 00231 00232 SVGElement* element = static_cast<SVGElement*>(node); 00233 if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) { 00234 /*if (SVGResource* resource = styledElement->canvasResource()) 00235 resource->invalidate();*/ 00236 } 00237 00238 node = node->parentNode(); 00239 } 00240 } 00241 00242 void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 00243 { 00244 Q_UNUSED(changedByParser); 00245 Q_UNUSED(beforeChange); 00246 Q_UNUSED(afterChange); 00247 Q_UNUSED(childCountDelta); 00248 SVGElement::childrenChanged(); 00249 /*SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 00250 if (document()->parsing()) 00251 return; 00252 00253 SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); 00254 if (!extensions) 00255 return; 00256 00257 // TODO: Fix bug http://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily) 00258 00259 // In case we're referenced by a <use> element, we have element instances registered 00260 // to us in the SVGDocumentExtensions. If childrenChanged() is called, we need 00261 // to recursively update all children including ourselves. 00262 updateElementInstance(extensions);*/ 00263 } 00264 00265 void SVGStyledElement::updateElementInstance(SVGDocumentExtensions* extensions) const 00266 { 00267 Q_UNUSED(extensions); 00268 /*if (gElementsWithInstanceUpdatesBlocked && gElementsWithInstanceUpdatesBlocked->contains(this)) 00269 return; 00270 00271 SVGStyledElement* nonConstThis = const_cast<SVGStyledElement*>(this); 00272 HashSet<SVGElementInstance*>* set = extensions->instancesForElement(nonConstThis); 00273 if (!set || set->isEmpty()) 00274 return; 00275 00276 // We need to be careful here, as the instancesForElement 00277 // hash set may be modified after we call updateInstance! 00278 HashSet<SVGElementInstance*> localCopy; 00279 00280 // First create a local copy of the hashset 00281 HashSet<SVGElementInstance*>::const_iterator it1 = set->begin(); 00282 const HashSet<SVGElementInstance*>::const_iterator end1 = set->end(); 00283 00284 for (; it1 != end1; ++it1) 00285 localCopy.add(*it1); 00286 00287 // Actually nofify instances to update 00288 HashSet<SVGElementInstance*>::const_iterator it2 = localCopy.begin(); 00289 const HashSet<SVGElementInstance*>::const_iterator end2 = localCopy.end(); 00290 00291 for (; it2 != end2; ++it2) 00292 (*it2)->updateInstance(nonConstThis);*/ 00293 } 00294 00295 RenderStyle* SVGStyledElement::resolveStyle(RenderStyle* parentStyle) 00296 { 00297 Q_UNUSED(parentStyle); 00298 if (renderer()) { 00299 RenderStyle* renderStyle = renderer()->style(); 00300 renderStyle->ref(); 00301 return renderStyle; 00302 } 00303 00304 return document()->styleSelector()->styleForElement(this/*, parentStyle*/); 00305 } 00306 00307 PassRefPtr<DOM::CSSValueImpl> SVGStyledElement::getPresentationAttribute(const String& name) 00308 { 00309 Q_UNUSED(name); 00310 /*MappedAttribute* cssSVGAttr = mappedAttributes()->getAttributeItem(name); 00311 if (!cssSVGAttr || !cssSVGAttr->style()) 00312 return 0; 00313 return cssSVGAttr->style()->getPropertyCSSValue(name);*/ 00314 Q_ASSERT(false); 00315 return new CSSPrimitiveValueImpl(0); 00316 } 00317 00318 void SVGStyledElement::detach() 00319 { 00320 /*SVGResource::removeClient(this);*/ 00321 SVGElement::detach(); 00322 } 00323 00324 void SVGStyledElement::setInstanceUpdatesBlocked(bool blockUpdates) 00325 { 00326 if (blockUpdates) { 00327 if (!gElementsWithInstanceUpdatesBlocked) 00328 gElementsWithInstanceUpdatesBlocked = new HashSet<const SVGStyledElement*>; 00329 gElementsWithInstanceUpdatesBlocked->add(this); 00330 } else { 00331 ASSERT(gElementsWithInstanceUpdatesBlocked); 00332 ASSERT(gElementsWithInstanceUpdatesBlocked->contains(this)); 00333 gElementsWithInstanceUpdatesBlocked->remove(this); 00334 } 00335 } 00336 00337 } 00338 00339 #endif // ENABLE(SVG)
KDE 4.6 API Reference