1/* 2 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 3 2004, 2005, 2010 Rob Buis <buis@kde.org> 4 Copyright (C) Research In Motion Limited 2010. All rights reserved. 5 6 Based on khtml code by: 7 Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) 8 Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) 9 Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org) 10 Copyright (C) 2002 Apple Inc. 11 12 This library is free software; you can redistribute it and/or 13 modify it under the terms of the GNU Library General Public 14 License as published by the Free Software Foundation; either 15 version 2 of the License, or (at your option) any later version. 16 17 This library is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Library General Public License for more details. 21 22 You should have received a copy of the GNU Library General Public License 23 along with this library; see the file COPYING.LIB. If not, write to 24 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25 Boston, MA 02110-1301, USA. 26*/ 27 28#include "config.h" 29#include "SVGRenderStyle.h" 30 31#include "CSSPrimitiveValue.h" 32#include "CSSValueList.h" 33#include "IntRect.h" 34#include "NodeRenderStyle.h" 35#include "SVGElement.h" 36#include <wtf/NeverDestroyed.h> 37 38namespace WebCore { 39 40static const SVGRenderStyle& defaultSVGStyle() 41{ 42 static NeverDestroyed<DataRef<SVGRenderStyle>> style(SVGRenderStyle::createDefaultStyle()); 43 return *style.get().get(); 44} 45 46PassRef<SVGRenderStyle> SVGRenderStyle::createDefaultStyle() 47{ 48 return adoptRef(*new SVGRenderStyle(CreateDefault)); 49} 50 51SVGRenderStyle::SVGRenderStyle() 52 : fill(defaultSVGStyle().fill) 53 , stroke(defaultSVGStyle().stroke) 54 , text(defaultSVGStyle().text) 55 , inheritedResources(defaultSVGStyle().inheritedResources) 56 , stops(defaultSVGStyle().stops) 57 , misc(defaultSVGStyle().misc) 58 , shadowSVG(defaultSVGStyle().shadowSVG) 59 , resources(defaultSVGStyle().resources) 60{ 61 setBitDefaults(); 62} 63 64SVGRenderStyle::SVGRenderStyle(CreateDefaultType) 65 : fill(StyleFillData::create()) 66 , stroke(StyleStrokeData::create()) 67 , text(StyleTextData::create()) 68 , inheritedResources(StyleInheritedResourceData::create()) 69 , stops(StyleStopData::create()) 70 , misc(StyleMiscData::create()) 71 , shadowSVG(StyleShadowSVGData::create()) 72 , resources(StyleResourceData::create()) 73{ 74 setBitDefaults(); 75} 76 77inline SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other) 78 : RefCounted<SVGRenderStyle>() 79 , svg_inherited_flags(other.svg_inherited_flags) 80 , svg_noninherited_flags(other.svg_noninherited_flags) 81 , fill(other.fill) 82 , stroke(other.stroke) 83 , text(other.text) 84 , inheritedResources(other.inheritedResources) 85 , stops(other.stops) 86 , misc(other.misc) 87 , shadowSVG(other.shadowSVG) 88 , resources(other.resources) 89{ 90} 91 92PassRef<SVGRenderStyle> SVGRenderStyle::copy() const 93{ 94 return adoptRef(*new SVGRenderStyle(*this)); 95} 96 97SVGRenderStyle::~SVGRenderStyle() 98{ 99} 100 101bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const 102{ 103 return fill == other.fill 104 && stroke == other.stroke 105 && text == other.text 106 && stops == other.stops 107 && misc == other.misc 108 && shadowSVG == other.shadowSVG 109 && inheritedResources == other.inheritedResources 110 && resources == other.resources 111 && svg_inherited_flags == other.svg_inherited_flags 112 && svg_noninherited_flags == other.svg_noninherited_flags; 113} 114 115bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle* other) const 116{ 117 return fill != other->fill 118 || stroke != other->stroke 119 || text != other->text 120 || inheritedResources != other->inheritedResources 121 || svg_inherited_flags != other->svg_inherited_flags; 122} 123 124void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent) 125{ 126 if (!svgInheritParent) 127 return; 128 129 fill = svgInheritParent->fill; 130 stroke = svgInheritParent->stroke; 131 text = svgInheritParent->text; 132 inheritedResources = svgInheritParent->inheritedResources; 133 134 svg_inherited_flags = svgInheritParent->svg_inherited_flags; 135} 136 137void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle* other) 138{ 139 svg_noninherited_flags = other->svg_noninherited_flags; 140 stops = other->stops; 141 misc = other->misc; 142 shadowSVG = other->shadowSVG; 143 resources = other->resources; 144} 145 146Vector<PaintType> SVGRenderStyle::paintTypesForPaintOrder() const 147{ 148 Vector<PaintType, 3> paintOrder; 149 switch (this->paintOrder()) { 150 case PaintOrderNormal: 151 FALLTHROUGH; 152 case PaintOrderFill: 153 paintOrder.append(PaintTypeFill); 154 paintOrder.append(PaintTypeStroke); 155 paintOrder.append(PaintTypeMarkers); 156 break; 157 case PaintOrderFillMarkers: 158 paintOrder.append(PaintTypeFill); 159 paintOrder.append(PaintTypeMarkers); 160 paintOrder.append(PaintTypeStroke); 161 break; 162 case PaintOrderStroke: 163 paintOrder.append(PaintTypeStroke); 164 paintOrder.append(PaintTypeFill); 165 paintOrder.append(PaintTypeMarkers); 166 break; 167 case PaintOrderStrokeMarkers: 168 paintOrder.append(PaintTypeStroke); 169 paintOrder.append(PaintTypeMarkers); 170 paintOrder.append(PaintTypeFill); 171 break; 172 case PaintOrderMarkers: 173 paintOrder.append(PaintTypeMarkers); 174 paintOrder.append(PaintTypeFill); 175 paintOrder.append(PaintTypeStroke); 176 break; 177 case PaintOrderMarkersStroke: 178 paintOrder.append(PaintTypeMarkers); 179 paintOrder.append(PaintTypeStroke); 180 paintOrder.append(PaintTypeFill); 181 break; 182 }; 183 return paintOrder; 184} 185 186StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const 187{ 188 // NOTE: All comparisions that may return StyleDifferenceLayout have to go before those who return StyleDifferenceRepaint 189 190 // If kerning changes, we need a relayout, to force SVGCharacterData to be recalculated in the SVGRootInlineBox. 191 if (text != other->text) 192 return StyleDifferenceLayout; 193 194 // If resources change, we need a relayout, as the presence of resources influences the repaint rect. 195 if (resources != other->resources) 196 return StyleDifferenceLayout; 197 198 // If markers change, we need a relayout, as marker boundaries are cached in RenderSVGPath. 199 if (inheritedResources != other->inheritedResources) 200 return StyleDifferenceLayout; 201 202 // All text related properties influence layout. 203 if (svg_inherited_flags._textAnchor != other->svg_inherited_flags._textAnchor 204 || svg_inherited_flags._writingMode != other->svg_inherited_flags._writingMode 205 || svg_inherited_flags._glyphOrientationHorizontal != other->svg_inherited_flags._glyphOrientationHorizontal 206 || svg_inherited_flags._glyphOrientationVertical != other->svg_inherited_flags._glyphOrientationVertical 207 || svg_noninherited_flags.f._alignmentBaseline != other->svg_noninherited_flags.f._alignmentBaseline 208 || svg_noninherited_flags.f._dominantBaseline != other->svg_noninherited_flags.f._dominantBaseline 209 || svg_noninherited_flags.f._baselineShift != other->svg_noninherited_flags.f._baselineShift) 210 return StyleDifferenceLayout; 211 212 // Text related properties influence layout. 213 bool miscNotEqual = misc != other->misc; 214 if (miscNotEqual && misc->baselineShiftValue != other->misc->baselineShiftValue) 215 return StyleDifferenceLayout; 216 217 // These properties affect the cached stroke bounding box rects. 218 if (svg_inherited_flags._capStyle != other->svg_inherited_flags._capStyle 219 || svg_inherited_flags._joinStyle != other->svg_inherited_flags._joinStyle) 220 return StyleDifferenceLayout; 221 222 // Shadow changes require relayouts, as they affect the repaint rects. 223 if (shadowSVG != other->shadowSVG) 224 return StyleDifferenceLayout; 225 226 // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated. 227 if (stroke != other->stroke) { 228 if (stroke->width != other->stroke->width 229 || stroke->paintType != other->stroke->paintType 230 || stroke->paintColor != other->stroke->paintColor 231 || stroke->paintUri != other->stroke->paintUri 232 || stroke->miterLimit != other->stroke->miterLimit 233 || stroke->dashArray != other->stroke->dashArray 234 || stroke->dashOffset != other->stroke->dashOffset 235 || stroke->visitedLinkPaintColor != other->stroke->visitedLinkPaintColor 236 || stroke->visitedLinkPaintUri != other->stroke->visitedLinkPaintUri 237 || stroke->visitedLinkPaintType != other->stroke->visitedLinkPaintType) 238 return StyleDifferenceLayout; 239 240 // Only the stroke-opacity case remains, where we only need a repaint. 241 ASSERT(stroke->opacity != other->stroke->opacity); 242 return StyleDifferenceRepaint; 243 } 244 245 // vector-effect changes require a re-layout. 246 if (svg_noninherited_flags.f._vectorEffect != other->svg_noninherited_flags.f._vectorEffect) 247 return StyleDifferenceLayout; 248 249 // NOTE: All comparisions below may only return StyleDifferenceRepaint 250 251 // Painting related properties only need repaints. 252 if (miscNotEqual) { 253 if (misc->floodColor != other->misc->floodColor 254 || misc->floodOpacity != other->misc->floodOpacity 255 || misc->lightingColor != other->misc->lightingColor) 256 return StyleDifferenceRepaint; 257 } 258 259 // If fill changes, we just need to repaint. Fill boundaries are not influenced by this, only by the Path, that RenderSVGPath contains. 260 if (fill->paintType != other->fill->paintType || fill->paintColor != other->fill->paintColor 261 || fill->paintUri != other->fill->paintUri || fill->opacity != other->fill->opacity) 262 return StyleDifferenceRepaint; 263 264 // If gradient stops change, we just need to repaint. Style updates are already handled through RenderSVGGradientSTop. 265 if (stops != other->stops) 266 return StyleDifferenceRepaint; 267 268 // Changes of these flags only cause repaints. 269 if (svg_inherited_flags._colorRendering != other->svg_inherited_flags._colorRendering 270 || svg_inherited_flags._shapeRendering != other->svg_inherited_flags._shapeRendering 271 || svg_inherited_flags._clipRule != other->svg_inherited_flags._clipRule 272 || svg_inherited_flags._fillRule != other->svg_inherited_flags._fillRule 273 || svg_inherited_flags._colorInterpolation != other->svg_inherited_flags._colorInterpolation 274 || svg_inherited_flags._colorInterpolationFilters != other->svg_inherited_flags._colorInterpolationFilters) 275 return StyleDifferenceRepaint; 276 277 if (svg_noninherited_flags.f.bufferedRendering != other->svg_noninherited_flags.f.bufferedRendering) 278 return StyleDifferenceRepaint; 279 280 if (svg_noninherited_flags.f.maskType != other->svg_noninherited_flags.f.maskType) 281 return StyleDifferenceRepaint; 282 283 return StyleDifferenceEqual; 284} 285 286} 287