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 | |
38 | namespace WebCore { |
39 | |
40 | static const SVGRenderStyle& defaultSVGStyle() |
41 | { |
42 | static NeverDestroyed<DataRef<SVGRenderStyle>> style(SVGRenderStyle::createDefaultStyle()); |
43 | return *style.get(); |
44 | } |
45 | |
46 | Ref<SVGRenderStyle> SVGRenderStyle::createDefaultStyle() |
47 | { |
48 | return adoptRef(*new SVGRenderStyle(CreateDefault)); |
49 | } |
50 | |
51 | SVGRenderStyle::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 | |
65 | SVGRenderStyle::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 | |
79 | inline 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 | |
95 | Ref<SVGRenderStyle> SVGRenderStyle::copy() const |
96 | { |
97 | return adoptRef(*new SVGRenderStyle(*this)); |
98 | } |
99 | |
100 | SVGRenderStyle::~SVGRenderStyle() = default; |
101 | |
102 | bool 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 | |
117 | bool 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 | |
126 | void 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 | |
136 | void 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 | |
146 | StyleDifference 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 | |