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 13namespace blink { 14 15namespace { 16 17template <CSSPropertyID property> 18bool 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 59bool 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