1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/animation/css/CSSPropertyEquality.h"
7
8 #include "core/animation/css/CSSAnimations.h"
9 #include "core/rendering/style/DataEquivalency.h"
10 #include "core/rendering/style/RenderStyle.h"
11 #include "core/rendering/style/ShadowList.h"
12
13 namespace blink {
14
15 namespace {
16
17 template <CSSPropertyID property>
fillLayersEqual(const FillLayer & aLayers,const FillLayer & bLayers)18 bool fillLayersEqual(const FillLayer& aLayers, const FillLayer& bLayers)
19 {
20 const FillLayer* aLayer = &aLayers;
21 const FillLayer* bLayer = &bLayers;
22 while (aLayer && bLayer) {
23 switch (property) {
24 case CSSPropertyBackgroundPositionX:
25 case CSSPropertyWebkitMaskPositionX:
26 if (aLayer->xPosition() != bLayer->xPosition())
27 return false;
28 break;
29 case CSSPropertyBackgroundPositionY:
30 case CSSPropertyWebkitMaskPositionY:
31 if (aLayer->yPosition() != bLayer->yPosition())
32 return false;
33 break;
34 case CSSPropertyBackgroundSize:
35 case CSSPropertyWebkitBackgroundSize:
36 case CSSPropertyWebkitMaskSize:
37 if (!(aLayer->sizeLength() == bLayer->sizeLength()))
38 return false;
39 break;
40 case CSSPropertyBackgroundImage:
41 if (!dataEquivalent(aLayer->image(), bLayer->image()))
42 return false;
43 break;
44 default:
45 ASSERT_NOT_REACHED();
46 return true;
47 }
48
49 aLayer = aLayer->next();
50 bLayer = bLayer->next();
51 }
52
53 // FIXME: Shouldn't this be return !aLayer && !bLayer; ?
54 return true;
55 }
56
57 }
58
propertiesEqual(CSSPropertyID prop,const RenderStyle & a,const RenderStyle & b)59 bool CSSPropertyEquality::propertiesEqual(CSSPropertyID prop, const RenderStyle& a, const RenderStyle& b)
60 {
61 switch (prop) {
62 case CSSPropertyBackgroundColor:
63 return a.backgroundColor() == b.backgroundColor()
64 && a.visitedLinkBackgroundColor() == b.visitedLinkBackgroundColor();
65 case CSSPropertyBackgroundImage:
66 return fillLayersEqual<CSSPropertyBackgroundImage>(a.backgroundLayers(), b.backgroundLayers());
67 case CSSPropertyBackgroundPositionX:
68 return fillLayersEqual<CSSPropertyBackgroundPositionX>(a.backgroundLayers(), b.backgroundLayers());
69 case CSSPropertyBackgroundPositionY:
70 return fillLayersEqual<CSSPropertyBackgroundPositionY>(a.backgroundLayers(), b.backgroundLayers());
71 case CSSPropertyBackgroundSize:
72 return fillLayersEqual<CSSPropertyBackgroundSize>(a.backgroundLayers(), b.backgroundLayers());
73 case CSSPropertyBaselineShift:
74 return dataEquivalent(a.baselineShiftValue(), b.baselineShiftValue());
75 case CSSPropertyBorderBottomColor:
76 return a.borderBottomColor() == b.borderBottomColor()
77 && a.visitedLinkBorderBottomColor() == b.visitedLinkBorderBottomColor();
78 case CSSPropertyBorderBottomLeftRadius:
79 return a.borderBottomLeftRadius() == b.borderBottomLeftRadius();
80 case CSSPropertyBorderBottomRightRadius:
81 return a.borderBottomRightRadius() == b.borderBottomRightRadius();
82 case CSSPropertyBorderBottomWidth:
83 return a.borderBottomWidth() == b.borderBottomWidth();
84 case CSSPropertyBorderImageOutset:
85 return a.borderImageOutset() == b.borderImageOutset();
86 case CSSPropertyBorderImageSlice:
87 return a.borderImageSlices() == b.borderImageSlices();
88 case CSSPropertyBorderImageSource:
89 return dataEquivalent(a.borderImageSource(), b.borderImageSource());
90 case CSSPropertyBorderImageWidth:
91 return a.borderImageWidth() == b.borderImageWidth();
92 case CSSPropertyBorderLeftColor:
93 return a.borderLeftColor() == b.borderLeftColor()
94 && a.visitedLinkBorderLeftColor() == b.visitedLinkBorderLeftColor();
95 case CSSPropertyBorderLeftWidth:
96 return a.borderLeftWidth() == b.borderLeftWidth();
97 case CSSPropertyBorderRightColor:
98 return a.borderRightColor() == b.borderRightColor()
99 && a.visitedLinkBorderRightColor() == b.visitedLinkBorderRightColor();
100 case CSSPropertyBorderRightWidth:
101 return a.borderRightWidth() == b.borderRightWidth();
102 case CSSPropertyBorderTopColor:
103 return a.borderTopColor() == b.borderTopColor()
104 && a.visitedLinkBorderTopColor() == b.visitedLinkBorderTopColor();
105 case CSSPropertyBorderTopLeftRadius:
106 return a.borderTopLeftRadius() == b.borderTopLeftRadius();
107 case CSSPropertyBorderTopRightRadius:
108 return a.borderTopRightRadius() == b.borderTopRightRadius();
109 case CSSPropertyBorderTopWidth:
110 return a.borderTopWidth() == b.borderTopWidth();
111 case CSSPropertyBottom:
112 return a.bottom() == b.bottom();
113 case CSSPropertyBoxShadow:
114 return dataEquivalent(a.boxShadow(), b.boxShadow());
115 case CSSPropertyClip:
116 return a.clip() == b.clip();
117 case CSSPropertyColor:
118 return a.color() == b.color() && a.visitedLinkColor() == b.visitedLinkColor();
119 case CSSPropertyFill: {
120 const SVGRenderStyle& aSVG = a.svgStyle();
121 const SVGRenderStyle& bSVG = b.svgStyle();
122 return aSVG.fillPaintType() == bSVG.fillPaintType()
123 && (aSVG.fillPaintType() != SVG_PAINTTYPE_RGBCOLOR || aSVG.fillPaintColor() == bSVG.fillPaintColor())
124 && aSVG.visitedLinkFillPaintType() == bSVG.visitedLinkFillPaintType()
125 && (aSVG.visitedLinkFillPaintType() != SVG_PAINTTYPE_RGBCOLOR || aSVG.visitedLinkFillPaintColor() == bSVG.visitedLinkFillPaintColor());
126 }
127 case CSSPropertyFillOpacity:
128 return a.fillOpacity() == b.fillOpacity();
129 case CSSPropertyFlexBasis:
130 return a.flexBasis() == b.flexBasis();
131 case CSSPropertyFlexGrow:
132 return a.flexGrow() == b.flexGrow();
133 case CSSPropertyFlexShrink:
134 return a.flexShrink() == b.flexShrink();
135 case CSSPropertyFloodColor:
136 return a.floodColor() == b.floodColor();
137 case CSSPropertyFloodOpacity:
138 return a.floodOpacity() == b.floodOpacity();
139 case CSSPropertyFontSize:
140 // CSSPropertyFontSize: Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size
141 // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
142 // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to
143 // enable text zoom rather than Text Autosizing? See http://crbug.com/227545.
144 return a.specifiedFontSize() == b.specifiedFontSize();
145 case CSSPropertyFontStretch:
146 return a.fontStretch() == b.fontStretch();
147 case CSSPropertyFontWeight:
148 return a.fontWeight() == b.fontWeight();
149 case CSSPropertyHeight:
150 return a.height() == b.height();
151 case CSSPropertyLeft:
152 return a.left() == b.left();
153 case CSSPropertyLetterSpacing:
154 return a.letterSpacing() == b.letterSpacing();
155 case CSSPropertyLightingColor:
156 return a.lightingColor() == b.lightingColor();
157 case CSSPropertyLineHeight:
158 return a.specifiedLineHeight() == b.specifiedLineHeight();
159 case CSSPropertyListStyleImage:
160 return dataEquivalent(a.listStyleImage(), b.listStyleImage());
161 case CSSPropertyMarginBottom:
162 return a.marginBottom() == b.marginBottom();
163 case CSSPropertyMarginLeft:
164 return a.marginLeft() == b.marginLeft();
165 case CSSPropertyMarginRight:
166 return a.marginRight() == b.marginRight();
167 case CSSPropertyMarginTop:
168 return a.marginTop() == b.marginTop();
169 case CSSPropertyMaxHeight:
170 return a.maxHeight() == b.maxHeight();
171 case CSSPropertyMaxWidth:
172 return a.maxWidth() == b.maxWidth();
173 case CSSPropertyMinHeight:
174 return a.minHeight() == b.minHeight();
175 case CSSPropertyMinWidth:
176 return a.minWidth() == b.minWidth();
177 case CSSPropertyObjectPosition:
178 return a.objectPosition() == b.objectPosition();
179 case CSSPropertyOpacity:
180 return a.opacity() == b.opacity();
181 case CSSPropertyOrphans:
182 return a.orphans() == b.orphans();
183 case CSSPropertyOutlineColor:
184 return a.outlineColor() == b.outlineColor()
185 && a.visitedLinkOutlineColor() == b.visitedLinkOutlineColor();
186 case CSSPropertyOutlineOffset:
187 return a.outlineOffset() == b.outlineOffset();
188 case CSSPropertyOutlineWidth:
189 return a.outlineWidth() == b.outlineWidth();
190 case CSSPropertyPaddingBottom:
191 return a.paddingBottom() == b.paddingBottom();
192 case CSSPropertyPaddingLeft:
193 return a.paddingLeft() == b.paddingLeft();
194 case CSSPropertyPaddingRight:
195 return a.paddingRight() == b.paddingRight();
196 case CSSPropertyPaddingTop:
197 return a.paddingTop() == b.paddingTop();
198 case CSSPropertyRight:
199 return a.right() == b.right();
200 case CSSPropertyShapeImageThreshold:
201 return a.shapeImageThreshold() == b.shapeImageThreshold();
202 case CSSPropertyShapeMargin:
203 return a.shapeMargin() == b.shapeMargin();
204 case CSSPropertyShapeOutside:
205 return dataEquivalent(a.shapeOutside(), b.shapeOutside());
206 case CSSPropertyStopColor:
207 return a.stopColor() == b.stopColor();
208 case CSSPropertyStopOpacity:
209 return a.stopOpacity() == b.stopOpacity();
210 case CSSPropertyStroke: {
211 const SVGRenderStyle& aSVG = a.svgStyle();
212 const SVGRenderStyle& bSVG = b.svgStyle();
213 return aSVG.strokePaintType() == bSVG.strokePaintType()
214 && (aSVG.strokePaintType() != SVG_PAINTTYPE_RGBCOLOR || aSVG.strokePaintColor() == bSVG.strokePaintColor())
215 && aSVG.visitedLinkStrokePaintType() == bSVG.visitedLinkStrokePaintType()
216 && (aSVG.visitedLinkStrokePaintType() != SVG_PAINTTYPE_RGBCOLOR || aSVG.visitedLinkStrokePaintColor() == bSVG.visitedLinkStrokePaintColor());
217 }
218 case CSSPropertyStrokeDasharray:
219 return dataEquivalent(a.strokeDashArray(), b.strokeDashArray());
220 case CSSPropertyStrokeDashoffset:
221 return dataEquivalent(a.strokeDashOffset(), b.strokeDashOffset());
222 case CSSPropertyStrokeMiterlimit:
223 return a.strokeMiterLimit() == b.strokeMiterLimit();
224 case CSSPropertyStrokeOpacity:
225 return a.strokeOpacity() == b.strokeOpacity();
226 case CSSPropertyStrokeWidth:
227 return dataEquivalent(a.strokeWidth(), b.strokeWidth());
228 case CSSPropertyTextDecorationColor:
229 return a.textDecorationColor() == b.textDecorationColor()
230 && a.visitedLinkTextDecorationColor() == b.visitedLinkTextDecorationColor();
231 case CSSPropertyTextIndent:
232 return a.textIndent() == b.textIndent();
233 case CSSPropertyTextShadow:
234 return dataEquivalent(a.textShadow(), b.textShadow());
235 case CSSPropertyTop:
236 return a.top() == b.top();
237 case CSSPropertyVerticalAlign:
238 return a.verticalAlign() == b.verticalAlign()
239 && (a.verticalAlign() != LENGTH || a.verticalAlignLength() == b.verticalAlignLength());
240 case CSSPropertyVisibility:
241 return a.visibility() == b.visibility();
242 case CSSPropertyWebkitBackgroundSize:
243 return fillLayersEqual<CSSPropertyWebkitBackgroundSize>(a.backgroundLayers(), b.backgroundLayers());
244 case CSSPropertyWebkitBorderHorizontalSpacing:
245 return a.horizontalBorderSpacing() == b.horizontalBorderSpacing();
246 case CSSPropertyWebkitBorderVerticalSpacing:
247 return a.verticalBorderSpacing() == b.verticalBorderSpacing();
248 case CSSPropertyWebkitBoxShadow:
249 return dataEquivalent(a.boxShadow(), b.boxShadow());
250 case CSSPropertyWebkitClipPath:
251 return dataEquivalent(a.clipPath(), b.clipPath());
252 case CSSPropertyWebkitColumnCount:
253 return a.columnCount() == b.columnCount();
254 case CSSPropertyWebkitColumnGap:
255 return a.columnGap() == b.columnGap();
256 case CSSPropertyWebkitColumnRuleColor:
257 return a.columnRuleColor() == b.columnRuleColor()
258 && a.visitedLinkColumnRuleColor() == b.visitedLinkColumnRuleColor();
259 case CSSPropertyWebkitColumnRuleWidth:
260 return a.columnRuleWidth() == b.columnRuleWidth();
261 case CSSPropertyWebkitColumnWidth:
262 return a.columnWidth() == b.columnWidth();
263 case CSSPropertyWebkitFilter:
264 return a.filter() == b.filter();
265 case CSSPropertyWebkitMaskBoxImageOutset:
266 return a.maskBoxImageOutset() == b.maskBoxImageOutset();
267 case CSSPropertyWebkitMaskBoxImageSlice:
268 return a.maskBoxImageSlices() == b.maskBoxImageSlices();
269 case CSSPropertyWebkitMaskBoxImageSource:
270 return dataEquivalent(a.maskBoxImageSource(), b.maskBoxImageSource());
271 case CSSPropertyWebkitMaskBoxImageWidth:
272 return a.maskBoxImageWidth() == b.maskBoxImageWidth();
273 case CSSPropertyWebkitMaskImage:
274 return dataEquivalent(a.maskImage(), b.maskImage());
275 case CSSPropertyWebkitMaskPositionX:
276 return fillLayersEqual<CSSPropertyWebkitMaskPositionX>(a.maskLayers(), b.maskLayers());
277 case CSSPropertyWebkitMaskPositionY:
278 return fillLayersEqual<CSSPropertyWebkitMaskPositionY>(a.maskLayers(), b.maskLayers());
279 case CSSPropertyWebkitMaskSize:
280 return fillLayersEqual<CSSPropertyWebkitMaskSize>(a.maskLayers(), b.maskLayers());
281 case CSSPropertyPerspective:
282 return a.perspective() == b.perspective();
283 case CSSPropertyPerspectiveOrigin:
284 return a.perspectiveOriginX() == b.perspectiveOriginX() && a.perspectiveOriginY() == b.perspectiveOriginY();
285 case CSSPropertyWebkitTextStrokeColor:
286 return a.textStrokeColor() == b.textStrokeColor()
287 && a.visitedLinkTextStrokeColor() == b.visitedLinkTextStrokeColor();
288 case CSSPropertyTransform:
289 return a.transform() == b.transform();
290 case CSSPropertyTransformOrigin:
291 return a.transformOriginX() == b.transformOriginX() && a.transformOriginY() == b.transformOriginY() && a.transformOriginZ() == b.transformOriginZ();
292 case CSSPropertyWidows:
293 return a.widows() == b.widows();
294 case CSSPropertyWidth:
295 return a.width() == b.width();
296 case CSSPropertyWordSpacing:
297 return a.wordSpacing() == b.wordSpacing();
298 case CSSPropertyZIndex:
299 return a.zIndex() == b.zIndex();
300 case CSSPropertyZoom:
301 return a.zoom() == b.zoom();
302 default:
303 ASSERT_NOT_REACHED();
304 return true;
305 }
306 }
307
308 }
309