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 namespace WebCore { 00048 00049 using namespace SVGNames; 00050 00051 static HashSet<const SVGStyledElement*>* gElementsWithInstanceUpdatesBlocked = 0; 00052 00053 SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* doc) 00054 : SVGElement(tagName, doc) 00055 { 00056 } 00057 00058 SVGStyledElement::~SVGStyledElement() 00059 { 00060 // SVGResource::removeClient(this); 00061 } 00062 00063 ANIMATED_PROPERTY_DEFINITIONS(SVGStyledElement, String, String, string, ClassName, className, HTMLNames::classAttr, m_className) 00064 00065 bool SVGStyledElement::rendererIsNeeded(RenderStyle* style) 00066 { 00067 // http://www.w3.org/TR/SVG/extend.html#PrivateData 00068 // Prevent anything other than SVG renderers from appearing in our render tree 00069 // Spec: SVG allows inclusion of elements from foreign namespaces anywhere 00070 // with the SVG content. In general, the SVG user agent will include the unknown 00071 // elements in the DOM but will otherwise ignore unknown elements. 00072 if (!parentNode() || parentNode()->isSVGElement()) 00073 return StyledElement::rendererIsNeeded(style); 00074 00075 return false; 00076 } 00077 00078 static void mapAttributeToCSSProperty(HashMap<DOMStringImpl*, int>* propertyNameToIdMap, const QualifiedName& attrName) 00079 { 00080 /*int propertyId = cssPropertyID(attrName.localName());*/ 00081 QString propName = attrName.localName().string(); 00082 int propertyId = getPropertyID(propName.toLatin1(), propName.length()); 00083 ASSERT(propertyId > 0); 00084 propertyNameToIdMap->set(attrName.localName().implementation(), propertyId); 00085 } 00086 00087 int SVGStyledElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName) 00088 { 00089 if (!attrName.namespaceURI().isEmpty()/*khtml fix, was isNull()*/) 00090 return 0; 00091 00092 static HashMap<DOMStringImpl*, int>* propertyNameToIdMap = 0; 00093 if (!propertyNameToIdMap) { 00094 propertyNameToIdMap = new HashMap<DOMStringImpl*, int>; 00095 // This is a list of all base CSS and SVG CSS properties which are exposed as SVG XML attributes 00096 /*mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr); 00097 mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr);*/ 00098 mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr); 00099 mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr); 00100 mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr); 00101 /*mapAttributeToCSSProperty(propertyNameToIdMap, colorAttr); 00102 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr); 00103 mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filtersAttr); 00104 mapAttributeToCSSProperty(propertyNameToIdMap, color_profileAttr); 00105 mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr); 00106 mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr); 00107 mapAttributeToCSSProperty(propertyNameToIdMap, directionAttr); 00108 mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr); 00109 mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr); 00110 mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr);*/ 00111 mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr); 00112 mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr); 00113 mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr); 00114 /*mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr); 00115 mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr); 00116 mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr);*/ 00117 mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr); 00118 mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr); 00119 //mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr); 00120 mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr); 00121 mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr); 00122 mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr); 00123 /*mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizontalAttr); 00124 mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_verticalAttr); 00125 mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr); 00126 mapAttributeToCSSProperty(propertyNameToIdMap, kerningAttr); 00127 mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr); 00128 mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr); 00129 mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr); 00130 mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr); 00131 mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr); 00132 mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr); 00133 mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr); 00134 mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr); 00135 mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr); 00136 mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr);*/ 00137 mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr); 00138 mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr); 00139 mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr); 00140 /*mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr); 00141 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr); 00142 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr); 00143 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr); 00144 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr);*/ 00145 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr); 00146 mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr); 00147 /*mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr); 00148 mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr); 00149 mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr); 00150 mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr); 00151 mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr); 00152 mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr); 00153 mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr);*/ 00154 } 00155 return propertyNameToIdMap->get(attrName.localName().implementation()); 00156 } 00157 00158 /*bool SVGStyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const 00159 { 00160 if (SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName) > 0) { 00161 result = eSVG; 00162 return false; 00163 } 00164 return SVGElement::mapToEntry(attrName, result); 00165 }*/ 00166 00167 void SVGStyledElement::parseMappedAttribute(MappedAttribute* attr) 00168 { 00169 // NOTE: Any subclass which overrides parseMappedAttribute for a property handled by 00170 // cssPropertyIdForSVGAttributeName will also have to override mapToEntry to disable the default eSVG mapping 00171 kDebug() << "parse:" << attr->localName() << attr->value() << "id=" << attr->id() << endl; 00172 int id = attr->id(); 00173 if (id == ATTR_STYLE) { 00174 kDebug() << "handle style" << endl; 00175 if (inlineStyleDecls()) { 00176 inlineStyleDecls()->clear(); 00177 } else { 00178 createInlineDecl(); 00179 } 00180 inlineStyleDecls()->setProperty(attr->value()); 00181 setChanged(); 00182 return; 00183 } 00184 int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name()); 00185 kDebug() << "propId" << propId << endl; 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 SVGElement::childrenChanged(); 00245 /*SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 00246 if (document()->parsing()) 00247 return; 00248 00249 SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); 00250 if (!extensions) 00251 return; 00252 00253 // TODO: Fix bug http://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily) 00254 00255 // In case we're referenced by a <use> element, we have element instances registered 00256 // to us in the SVGDocumentExtensions. If childrenChanged() is called, we need 00257 // to recursively update all children including ourselves. 00258 updateElementInstance(extensions);*/ 00259 } 00260 00261 void SVGStyledElement::updateElementInstance(SVGDocumentExtensions* extensions) const 00262 { 00263 /*if (gElementsWithInstanceUpdatesBlocked && gElementsWithInstanceUpdatesBlocked->contains(this)) 00264 return; 00265 00266 SVGStyledElement* nonConstThis = const_cast<SVGStyledElement*>(this); 00267 HashSet<SVGElementInstance*>* set = extensions->instancesForElement(nonConstThis); 00268 if (!set || set->isEmpty()) 00269 return; 00270 00271 // We need to be careful here, as the instancesForElement 00272 // hash set may be modified after we call updateInstance! 00273 HashSet<SVGElementInstance*> localCopy; 00274 00275 // First create a local copy of the hashset 00276 HashSet<SVGElementInstance*>::const_iterator it1 = set->begin(); 00277 const HashSet<SVGElementInstance*>::const_iterator end1 = set->end(); 00278 00279 for (; it1 != end1; ++it1) 00280 localCopy.add(*it1); 00281 00282 // Actually nofify instances to update 00283 HashSet<SVGElementInstance*>::const_iterator it2 = localCopy.begin(); 00284 const HashSet<SVGElementInstance*>::const_iterator end2 = localCopy.end(); 00285 00286 for (; it2 != end2; ++it2) 00287 (*it2)->updateInstance(nonConstThis);*/ 00288 } 00289 00290 RenderStyle* SVGStyledElement::resolveStyle(RenderStyle* parentStyle) 00291 { 00292 if (renderer()) { 00293 RenderStyle* renderStyle = renderer()->style(); 00294 renderStyle->ref(); 00295 return renderStyle; 00296 } 00297 00298 return document()->styleSelector()->styleForElement(this/*, parentStyle*/); 00299 } 00300 00301 PassRefPtr<CSSValue> SVGStyledElement::getPresentationAttribute(const String& name) 00302 { 00303 /*MappedAttribute* cssSVGAttr = mappedAttributes()->getAttributeItem(name); 00304 if (!cssSVGAttr || !cssSVGAttr->style()) 00305 return 0; 00306 return cssSVGAttr->style()->getPropertyCSSValue(name);*/ 00307 Q_ASSERT(false); 00308 return new CSSPrimitiveValueImpl(0); 00309 } 00310 00311 void SVGStyledElement::detach() 00312 { 00313 /*SVGResource::removeClient(this);*/ 00314 SVGElement::detach(); 00315 } 00316 00317 void SVGStyledElement::setInstanceUpdatesBlocked(bool blockUpdates) 00318 { 00319 if (blockUpdates) { 00320 if (!gElementsWithInstanceUpdatesBlocked) 00321 gElementsWithInstanceUpdatesBlocked = new HashSet<const SVGStyledElement*>; 00322 gElementsWithInstanceUpdatesBlocked->add(this); 00323 } else { 00324 ASSERT(gElementsWithInstanceUpdatesBlocked); 00325 ASSERT(gElementsWithInstanceUpdatesBlocked->contains(this)); 00326 gElementsWithInstanceUpdatesBlocked->remove(this); 00327 } 00328 } 00329 00330 } 00331 00332 #endif // ENABLE(SVG)