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();
44}
45
46Ref<SVGRenderStyle> SVGRenderStyle::createDefaultStyle()
47{
48 return adoptRef(*new SVGRenderStyle(CreateDefault));
49}
50
51SVGRenderStyle::SVGRenderStyle()
52 : m_fillData(defaultSVGStyle().m_fillData)
53 , m_strokeData(defaultSVGStyle().m_strokeData)
54 , m_textData(defaultSVGStyle().m_textData)
55 , m_inheritedResourceData(defaultSVGStyle().m_inheritedResourceData)
56 , m_stopData(defaultSVGStyle().m_stopData)
57 , m_miscData(defaultSVGStyle().m_miscData)
58 , m_shadowData(defaultSVGStyle().m_shadowData)
59 , m_layoutData(defaultSVGStyle().m_layoutData)
60 , m_nonInheritedResourceData(defaultSVGStyle().m_nonInheritedResourceData)
61{
62 setBitDefaults();
63}
64
65SVGRenderStyle::SVGRenderStyle(CreateDefaultType)
66 : m_fillData(StyleFillData::create())
67 , m_strokeData(StyleStrokeData::create())
68 , m_textData(StyleTextData::create())
69 , m_inheritedResourceData(StyleInheritedResourceData::create())
70 , m_stopData(StyleStopData::create())
71 , m_miscData(StyleMiscData::create())
72 , m_shadowData(StyleShadowSVGData::create())
73 , m_layoutData(StyleLayoutData::create())
74 , m_nonInheritedResourceData(StyleResourceData::create())
75{
76 setBitDefaults();
77}
78
79inline SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other)
80 : RefCounted<SVGRenderStyle>()
81 , m_inheritedFlags(other.m_inheritedFlags)
82 , m_nonInheritedFlags(other.m_nonInheritedFlags)
83 , m_fillData(other.m_fillData)
84 , m_strokeData(other.m_strokeData)
85 , m_textData(other.m_textData)
86 , m_inheritedResourceData(other.m_inheritedResourceData)
87 , m_stopData(other.m_stopData)
88 , m_miscData(other.m_miscData)
89 , m_shadowData(other.m_shadowData)
90 , m_layoutData(other.m_layoutData)
91 , m_nonInheritedResourceData(other.m_nonInheritedResourceData)
92{
93}
94
95Ref<SVGRenderStyle> SVGRenderStyle::copy() const
96{
97 return adoptRef(*new SVGRenderStyle(*this));
98}
99
100SVGRenderStyle::~SVGRenderStyle() = default;
101
102bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const
103{
104 return m_fillData == other.m_fillData
105 && m_strokeData == other.m_strokeData
106 && m_textData == other.m_textData
107 && m_stopData == other.m_stopData
108 && m_miscData == other.m_miscData
109 && m_shadowData == other.m_shadowData
110 && m_layoutData == other.m_layoutData
111 && m_inheritedResourceData == other.m_inheritedResourceData
112 && m_nonInheritedResourceData == other.m_nonInheritedResourceData
113 && m_inheritedFlags == other.m_inheritedFlags
114 && m_nonInheritedFlags == other.m_nonInheritedFlags;
115}
116
117bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle& other) const
118{
119 return m_fillData != other.m_fillData
120 || m_strokeData != other.m_strokeData
121 || m_textData != other.m_textData
122 || m_inheritedResourceData != other.m_inheritedResourceData
123 || m_inheritedFlags != other.m_inheritedFlags;
124}
125
126void SVGRenderStyle::inheritFrom(const SVGRenderStyle& other)
127{
128 m_fillData = other.m_fillData;
129 m_strokeData = other.m_strokeData;
130 m_textData = other.m_textData;
131 m_inheritedResourceData = other.m_inheritedResourceData;
132
133 m_inheritedFlags = other.m_inheritedFlags;
134}
135
136void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle& other)
137{
138 m_nonInheritedFlags = other.m_nonInheritedFlags;
139 m_stopData = other.m_stopData;
140 m_miscData = other.m_miscData;
141 m_shadowData = other.m_shadowData;
142 m_layoutData = other.m_layoutData;
143 m_nonInheritedResourceData = other.m_nonInheritedResourceData;
144}
145
146StyleDifference SVGRenderStyle::diff(const SVGRenderStyle& other) const
147{
148 // NOTE: All comparisions that may return StyleDifference::Layout have to go before those who return StyleDifference::Repaint
149
150 // If kerning changes, we need a relayout, to force SVGCharacterData to be recalculated in the SVGRootInlineBox.
151 if (m_textData != other.m_textData)
152 return StyleDifference::Layout;
153
154 // If resources change, we need a relayout, as the presence of resources influences the repaint rect.
155 if (m_nonInheritedResourceData != other.m_nonInheritedResourceData)
156 return StyleDifference::Layout;
157
158 // If markers change, we need a relayout, as marker boundaries are cached in RenderSVGPath.
159 if (m_inheritedResourceData != other.m_inheritedResourceData)
160 return StyleDifference::Layout;
161
162 // All text related properties influence layout.
163 if (m_inheritedFlags.textAnchor != other.m_inheritedFlags.textAnchor
164 || m_inheritedFlags.glyphOrientationHorizontal != other.m_inheritedFlags.glyphOrientationHorizontal
165 || m_inheritedFlags.glyphOrientationVertical != other.m_inheritedFlags.glyphOrientationVertical
166 || m_nonInheritedFlags.flagBits.alignmentBaseline != other.m_nonInheritedFlags.flagBits.alignmentBaseline
167 || m_nonInheritedFlags.flagBits.dominantBaseline != other.m_nonInheritedFlags.flagBits.dominantBaseline
168 || m_nonInheritedFlags.flagBits.baselineShift != other.m_nonInheritedFlags.flagBits.baselineShift)
169 return StyleDifference::Layout;
170
171 // Text related properties influence layout.
172 bool miscNotEqual = m_miscData != other.m_miscData;
173 if (miscNotEqual && m_miscData->baselineShiftValue != other.m_miscData->baselineShiftValue)
174 return StyleDifference::Layout;
175
176 // Shadow changes require relayouts, as they affect the repaint rects.
177 if (m_shadowData != other.m_shadowData)
178 return StyleDifference::Layout;
179
180 // The x or y properties require relayout.
181 if (m_layoutData != other.m_layoutData)
182 return StyleDifference::Layout;
183
184 // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated.
185 if (m_strokeData != other.m_strokeData) {
186 if (m_strokeData->paintType != other.m_strokeData->paintType
187 || m_strokeData->paintColor != other.m_strokeData->paintColor
188 || m_strokeData->paintUri != other.m_strokeData->paintUri
189 || m_strokeData->dashArray != other.m_strokeData->dashArray
190 || m_strokeData->dashOffset != other.m_strokeData->dashOffset
191 || m_strokeData->visitedLinkPaintColor != other.m_strokeData->visitedLinkPaintColor
192 || m_strokeData->visitedLinkPaintUri != other.m_strokeData->visitedLinkPaintUri
193 || m_strokeData->visitedLinkPaintType != other.m_strokeData->visitedLinkPaintType)
194 return StyleDifference::Layout;
195
196 // Only the stroke-opacity case remains, where we only need a repaint.
197 ASSERT(m_strokeData->opacity != other.m_strokeData->opacity);
198 return StyleDifference::Repaint;
199 }
200
201 // vector-effect changes require a re-layout.
202 if (m_nonInheritedFlags.flagBits.vectorEffect != other.m_nonInheritedFlags.flagBits.vectorEffect)
203 return StyleDifference::Layout;
204
205 // NOTE: All comparisions below may only return StyleDifference::Repaint
206
207 // Painting related properties only need repaints.
208 if (miscNotEqual) {
209 if (m_miscData->floodColor != other.m_miscData->floodColor
210 || m_miscData->floodOpacity != other.m_miscData->floodOpacity
211 || m_miscData->lightingColor != other.m_miscData->lightingColor)
212 return StyleDifference::Repaint;
213 }
214
215 // If fill data changes, we just need to repaint. Fill boundaries are not influenced by this, only by the Path, that RenderSVGPath contains.
216 if (m_fillData->paintType != other.m_fillData->paintType || m_fillData->paintColor != other.m_fillData->paintColor
217 || m_fillData->paintUri != other.m_fillData->paintUri || m_fillData->opacity != other.m_fillData->opacity)
218 return StyleDifference::Repaint;
219
220 // If gradient stops change, we just need to repaint. Style updates are already handled through RenderSVGGradientSTop.
221 if (m_stopData != other.m_stopData)
222 return StyleDifference::Repaint;
223
224 // Changes of these flags only cause repaints.
225 if (m_inheritedFlags.colorRendering != other.m_inheritedFlags.colorRendering
226 || m_inheritedFlags.shapeRendering != other.m_inheritedFlags.shapeRendering
227 || m_inheritedFlags.clipRule != other.m_inheritedFlags.clipRule
228 || m_inheritedFlags.fillRule != other.m_inheritedFlags.fillRule
229 || m_inheritedFlags.colorInterpolation != other.m_inheritedFlags.colorInterpolation
230 || m_inheritedFlags.colorInterpolationFilters != other.m_inheritedFlags.colorInterpolationFilters)
231 return StyleDifference::Repaint;
232
233 if (m_nonInheritedFlags.flagBits.bufferedRendering != other.m_nonInheritedFlags.flagBits.bufferedRendering)
234 return StyleDifference::Repaint;
235
236 if (m_nonInheritedFlags.flagBits.maskType != other.m_nonInheritedFlags.flagBits.maskType)
237 return StyleDifference::Repaint;
238
239 return StyleDifference::Equal;
240}
241
242}
243