Apply SVG styles paint-order, stroke-linejoin, and stroke-linecap on DOM text.
[WebKit-https.git] / Source / WebCore / rendering / style / SVGRenderStyle.cpp
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()
101 {
102 }
103
104 bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const
105 {
106     return m_fillData == other.m_fillData
107         && m_strokeData == other.m_strokeData
108         && m_textData == other.m_textData
109         && m_stopData == other.m_stopData
110         && m_miscData == other.m_miscData
111         && m_shadowData == other.m_shadowData
112         && m_layoutData == other.m_layoutData
113         && m_inheritedResourceData == other.m_inheritedResourceData
114         && m_nonInheritedResourceData == other.m_nonInheritedResourceData
115         && m_inheritedFlags == other.m_inheritedFlags
116         && m_nonInheritedFlags == other.m_nonInheritedFlags;
117 }
118
119 bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle& other) const
120 {
121     return m_fillData != other.m_fillData
122         || m_strokeData != other.m_strokeData
123         || m_textData != other.m_textData
124         || m_inheritedResourceData != other.m_inheritedResourceData
125         || m_inheritedFlags != other.m_inheritedFlags;
126 }
127
128 void SVGRenderStyle::inheritFrom(const SVGRenderStyle& other)
129 {
130     m_fillData = other.m_fillData;
131     m_strokeData = other.m_strokeData;
132     m_textData = other.m_textData;
133     m_inheritedResourceData = other.m_inheritedResourceData;
134
135     m_inheritedFlags = other.m_inheritedFlags;
136 }
137
138 void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle& other)
139 {
140     m_nonInheritedFlags = other.m_nonInheritedFlags;
141     m_stopData = other.m_stopData;
142     m_miscData = other.m_miscData;
143     m_shadowData = other.m_shadowData;
144     m_layoutData = other.m_layoutData;
145     m_nonInheritedResourceData = other.m_nonInheritedResourceData;
146 }
147
148 StyleDifference SVGRenderStyle::diff(const SVGRenderStyle& other) const
149 {
150     // NOTE: All comparisions that may return StyleDifferenceLayout have to go before those who return StyleDifferenceRepaint
151
152     // If kerning changes, we need a relayout, to force SVGCharacterData to be recalculated in the SVGRootInlineBox.
153     if (m_textData != other.m_textData)
154         return StyleDifferenceLayout;
155
156     // If resources change, we need a relayout, as the presence of resources influences the repaint rect.
157     if (m_nonInheritedResourceData != other.m_nonInheritedResourceData)
158         return StyleDifferenceLayout;
159
160     // If markers change, we need a relayout, as marker boundaries are cached in RenderSVGPath.
161     if (m_inheritedResourceData != other.m_inheritedResourceData)
162         return StyleDifferenceLayout;
163
164     // All text related properties influence layout.
165     if (m_inheritedFlags.textAnchor != other.m_inheritedFlags.textAnchor
166         || m_inheritedFlags.glyphOrientationHorizontal != other.m_inheritedFlags.glyphOrientationHorizontal
167         || m_inheritedFlags.glyphOrientationVertical != other.m_inheritedFlags.glyphOrientationVertical
168         || m_nonInheritedFlags.flagBits.alignmentBaseline != other.m_nonInheritedFlags.flagBits.alignmentBaseline
169         || m_nonInheritedFlags.flagBits.dominantBaseline != other.m_nonInheritedFlags.flagBits.dominantBaseline
170         || m_nonInheritedFlags.flagBits.baselineShift != other.m_nonInheritedFlags.flagBits.baselineShift)
171         return StyleDifferenceLayout;
172
173     // Text related properties influence layout.
174     bool miscNotEqual = m_miscData != other.m_miscData;
175     if (miscNotEqual && m_miscData->baselineShiftValue != other.m_miscData->baselineShiftValue)
176         return StyleDifferenceLayout;
177
178     // Shadow changes require relayouts, as they affect the repaint rects.
179     if (m_shadowData != other.m_shadowData)
180         return StyleDifferenceLayout;
181
182     // The x or y properties require relayout.
183     if (m_layoutData != other.m_layoutData)
184         return StyleDifferenceLayout; 
185
186     // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated.
187     if (m_strokeData != other.m_strokeData) {
188         if (m_strokeData->paintType != other.m_strokeData->paintType
189             || m_strokeData->paintColor != other.m_strokeData->paintColor
190             || m_strokeData->paintUri != other.m_strokeData->paintUri
191             || m_strokeData->miterLimit != other.m_strokeData->miterLimit
192             || m_strokeData->dashArray != other.m_strokeData->dashArray
193             || m_strokeData->dashOffset != other.m_strokeData->dashOffset
194             || m_strokeData->visitedLinkPaintColor != other.m_strokeData->visitedLinkPaintColor
195             || m_strokeData->visitedLinkPaintUri != other.m_strokeData->visitedLinkPaintUri
196             || m_strokeData->visitedLinkPaintType != other.m_strokeData->visitedLinkPaintType)
197             return StyleDifferenceLayout;
198
199         // Only the stroke-opacity case remains, where we only need a repaint.
200         ASSERT(m_strokeData->opacity != other.m_strokeData->opacity);
201         return StyleDifferenceRepaint;
202     }
203
204     // vector-effect changes require a re-layout.
205     if (m_nonInheritedFlags.flagBits.vectorEffect != other.m_nonInheritedFlags.flagBits.vectorEffect)
206         return StyleDifferenceLayout;
207
208     // NOTE: All comparisions below may only return StyleDifferenceRepaint
209
210     // Painting related properties only need repaints. 
211     if (miscNotEqual) {
212         if (m_miscData->floodColor != other.m_miscData->floodColor
213             || m_miscData->floodOpacity != other.m_miscData->floodOpacity
214             || m_miscData->lightingColor != other.m_miscData->lightingColor)
215             return StyleDifferenceRepaint;
216     }
217
218     // If fill data changes, we just need to repaint. Fill boundaries are not influenced by this, only by the Path, that RenderSVGPath contains.
219     if (m_fillData->paintType != other.m_fillData->paintType || m_fillData->paintColor != other.m_fillData->paintColor
220         || m_fillData->paintUri != other.m_fillData->paintUri || m_fillData->opacity != other.m_fillData->opacity)
221         return StyleDifferenceRepaint;
222
223     // If gradient stops change, we just need to repaint. Style updates are already handled through RenderSVGGradientSTop.
224     if (m_stopData != other.m_stopData)
225         return StyleDifferenceRepaint;
226
227     // Changes of these flags only cause repaints.
228     if (m_inheritedFlags.colorRendering != other.m_inheritedFlags.colorRendering
229         || m_inheritedFlags.shapeRendering != other.m_inheritedFlags.shapeRendering
230         || m_inheritedFlags.clipRule != other.m_inheritedFlags.clipRule
231         || m_inheritedFlags.fillRule != other.m_inheritedFlags.fillRule
232         || m_inheritedFlags.colorInterpolation != other.m_inheritedFlags.colorInterpolation
233         || m_inheritedFlags.colorInterpolationFilters != other.m_inheritedFlags.colorInterpolationFilters)
234         return StyleDifferenceRepaint;
235
236     if (m_nonInheritedFlags.flagBits.bufferedRendering != other.m_nonInheritedFlags.flagBits.bufferedRendering)
237         return StyleDifferenceRepaint;
238
239     if (m_nonInheritedFlags.flagBits.maskType != other.m_nonInheritedFlags.flagBits.maskType)
240         return StyleDifferenceRepaint;
241
242     return StyleDifferenceEqual;
243 }
244
245 }