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 Computer, 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 30#if ENABLE(SVG) 31#include "SVGRenderStyle.h" 32 33#include "CSSPrimitiveValue.h" 34#include "CSSValueList.h" 35#include "IntRect.h" 36#include "NodeRenderStyle.h" 37#include "SVGStyledElement.h" 38 39using namespace std; 40 41namespace WebCore { 42 43SVGRenderStyle::SVGRenderStyle() 44{ 45 static SVGRenderStyle* defaultStyle = new SVGRenderStyle(CreateDefault); 46 47 fill = defaultStyle->fill; 48 stroke = defaultStyle->stroke; 49 text = defaultStyle->text; 50 stops = defaultStyle->stops; 51 misc = defaultStyle->misc; 52 shadowSVG = defaultStyle->shadowSVG; 53 inheritedResources = defaultStyle->inheritedResources; 54 resources = defaultStyle->resources; 55 56 setBitDefaults(); 57} 58 59SVGRenderStyle::SVGRenderStyle(CreateDefaultType) 60{ 61 setBitDefaults(); 62 63 fill.init(); 64 stroke.init(); 65 text.init(); 66 stops.init(); 67 misc.init(); 68 shadowSVG.init(); 69 inheritedResources.init(); 70 resources.init(); 71} 72 73SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other) 74 : RefCounted<SVGRenderStyle>() 75{ 76 fill = other.fill; 77 stroke = other.stroke; 78 text = other.text; 79 stops = other.stops; 80 misc = other.misc; 81 shadowSVG = other.shadowSVG; 82 inheritedResources = other.inheritedResources; 83 resources = other.resources; 84 85 svg_inherited_flags = other.svg_inherited_flags; 86 svg_noninherited_flags = other.svg_noninherited_flags; 87} 88 89SVGRenderStyle::~SVGRenderStyle() 90{ 91} 92 93bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const 94{ 95 return fill == other.fill 96 && stroke == other.stroke 97 && text == other.text 98 && stops == other.stops 99 && misc == other.misc 100 && shadowSVG == other.shadowSVG 101 && inheritedResources == other.inheritedResources 102 && resources == other.resources 103 && svg_inherited_flags == other.svg_inherited_flags 104 && svg_noninherited_flags == other.svg_noninherited_flags; 105} 106 107bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle* other) const 108{ 109 return fill != other->fill 110 || stroke != other->stroke 111 || text != other->text 112 || inheritedResources != other->inheritedResources 113 || svg_inherited_flags != other->svg_inherited_flags; 114} 115 116void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent) 117{ 118 if (!svgInheritParent) 119 return; 120 121 fill = svgInheritParent->fill; 122 stroke = svgInheritParent->stroke; 123 text = svgInheritParent->text; 124 inheritedResources = svgInheritParent->inheritedResources; 125 126 svg_inherited_flags = svgInheritParent->svg_inherited_flags; 127} 128 129void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle* other) 130{ 131 svg_noninherited_flags = other->svg_noninherited_flags; 132 stops = other->stops; 133 misc = other->misc; 134 shadowSVG = other->shadowSVG; 135 resources = other->resources; 136} 137 138StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const 139{ 140 // NOTE: All comparisions that may return StyleDifferenceLayout have to go before those who return StyleDifferenceRepaint 141 142 // If kerning changes, we need a relayout, to force SVGCharacterData to be recalculated in the SVGRootInlineBox. 143 if (text != other->text) 144 return StyleDifferenceLayout; 145 146 // If resources change, we need a relayout, as the presence of resources influences the repaint rect. 147 if (resources != other->resources) 148 return StyleDifferenceLayout; 149 150 // If markers change, we need a relayout, as marker boundaries are cached in RenderSVGPath. 151 if (inheritedResources != other->inheritedResources) 152 return StyleDifferenceLayout; 153 154 // All text related properties influence layout. 155 if (svg_inherited_flags._textAnchor != other->svg_inherited_flags._textAnchor 156 || svg_inherited_flags._writingMode != other->svg_inherited_flags._writingMode 157 || svg_inherited_flags._glyphOrientationHorizontal != other->svg_inherited_flags._glyphOrientationHorizontal 158 || svg_inherited_flags._glyphOrientationVertical != other->svg_inherited_flags._glyphOrientationVertical 159 || svg_noninherited_flags.f._alignmentBaseline != other->svg_noninherited_flags.f._alignmentBaseline 160 || svg_noninherited_flags.f._dominantBaseline != other->svg_noninherited_flags.f._dominantBaseline 161 || svg_noninherited_flags.f._baselineShift != other->svg_noninherited_flags.f._baselineShift) 162 return StyleDifferenceLayout; 163 164 // Text related properties influence layout. 165 bool miscNotEqual = misc != other->misc; 166 if (miscNotEqual && misc->baselineShiftValue != other->misc->baselineShiftValue) 167 return StyleDifferenceLayout; 168 169 // These properties affect the cached stroke bounding box rects. 170 if (svg_inherited_flags._capStyle != other->svg_inherited_flags._capStyle 171 || svg_inherited_flags._joinStyle != other->svg_inherited_flags._joinStyle) 172 return StyleDifferenceLayout; 173 174 // Shadow changes require relayouts, as they affect the repaint rects. 175 if (shadowSVG != other->shadowSVG) 176 return StyleDifferenceLayout; 177 178 // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated. 179 if (stroke != other->stroke) { 180 if (stroke->width != other->stroke->width 181 || stroke->paintType != other->stroke->paintType 182 || stroke->paintColor != other->stroke->paintColor 183 || stroke->paintUri != other->stroke->paintUri 184 || stroke->miterLimit != other->stroke->miterLimit 185 || stroke->dashArray != other->stroke->dashArray 186 || stroke->dashOffset != other->stroke->dashOffset) 187 return StyleDifferenceLayout; 188 189 // Only the stroke-opacity case remains, where we only need a repaint. 190 ASSERT(stroke->opacity != other->stroke->opacity); 191 return StyleDifferenceRepaint; 192 } 193 194 // NOTE: All comparisions below may only return StyleDifferenceRepaint 195 196 // Painting related properties only need repaints. 197 if (miscNotEqual) { 198 if (misc->floodColor != other->misc->floodColor 199 || misc->floodOpacity != other->misc->floodOpacity 200 || misc->lightingColor != other->misc->lightingColor) 201 return StyleDifferenceRepaint; 202 } 203 204 // If fill changes, we just need to repaint. Fill boundaries are not influenced by this, only by the Path, that RenderSVGPath contains. 205 if (fill->paintType != other->fill->paintType || fill->paintColor != other->fill->paintColor 206 || fill->paintUri != other->fill->paintUri || fill->opacity != other->fill->opacity) 207 return StyleDifferenceRepaint; 208 209 // If gradient stops change, we just need to repaint. Style updates are already handled through RenderSVGGradientSTop. 210 if (stops != other->stops) 211 return StyleDifferenceRepaint; 212 213 // Changes of these flags only cause repaints. 214 if (svg_inherited_flags._colorRendering != other->svg_inherited_flags._colorRendering 215 || svg_inherited_flags._shapeRendering != other->svg_inherited_flags._shapeRendering 216 || svg_inherited_flags._clipRule != other->svg_inherited_flags._clipRule 217 || svg_inherited_flags._fillRule != other->svg_inherited_flags._fillRule 218 || svg_inherited_flags._colorInterpolation != other->svg_inherited_flags._colorInterpolation 219 || svg_inherited_flags._colorInterpolationFilters != other->svg_inherited_flags._colorInterpolationFilters) 220 return StyleDifferenceRepaint; 221 222 // FIXME: vector-effect is not taken into account in the layout-phase. Once this is fixed, we should relayout here. 223 if (svg_noninherited_flags.f._vectorEffect != other->svg_noninherited_flags.f._vectorEffect) 224 return StyleDifferenceRepaint; 225 226 if (svg_noninherited_flags.f.bufferedRendering != other->svg_noninherited_flags.f.bufferedRendering) 227 return StyleDifferenceRepaint; 228 229 if (svg_noninherited_flags.f.maskType != other->svg_noninherited_flags.f.maskType) 230 return StyleDifferenceRepaint; 231 232 return StyleDifferenceEqual; 233} 234 235} 236 237#endif // ENABLE(SVG) 238