blob: 7cd98e62a285323a952e43985ad1177a1a8521ed [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/css_property_equality.h"
#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/data_equivalency.h"
#include "third_party/blink/renderer/core/style/shadow_list.h"
// TODO(ikilpatrick): generate this file.
namespace blink {
namespace {
template <CSSPropertyID property>
bool FillLayersEqual(const FillLayer& a_layers, const FillLayer& b_layers) {
const FillLayer* a_layer = &a_layers;
const FillLayer* b_layer = &b_layers;
while (a_layer && b_layer) {
switch (property) {
case CSSPropertyID::kBackgroundPositionX:
case CSSPropertyID::kWebkitMaskPositionX:
if (a_layer->PositionX() != b_layer->PositionX())
return false;
if (a_layer->BackgroundXOrigin() != b_layer->BackgroundXOrigin())
return false;
break;
case CSSPropertyID::kBackgroundPositionY:
case CSSPropertyID::kWebkitMaskPositionY:
if (a_layer->PositionY() != b_layer->PositionY())
return false;
if (a_layer->BackgroundYOrigin() != b_layer->BackgroundYOrigin())
return false;
break;
case CSSPropertyID::kBackgroundSize:
case CSSPropertyID::kWebkitMaskSize:
if (!(a_layer->SizeLength() == b_layer->SizeLength()))
return false;
break;
case CSSPropertyID::kBackgroundImage:
if (!DataEquivalent(a_layer->GetImage(), b_layer->GetImage()))
return false;
break;
default:
NOTREACHED();
return true;
}
a_layer = a_layer->Next();
b_layer = b_layer->Next();
}
// FIXME: Shouldn't this be return !aLayer && !bLayer; ?
return true;
}
} // namespace
bool CSSPropertyEquality::PropertiesEqual(const PropertyHandle& property,
const ComputedStyle& a,
const ComputedStyle& b) {
if (property.IsCSSCustomProperty()) {
const AtomicString& name = property.CustomPropertyName();
return DataEquivalent(a.GetVariableValue(name), b.GetVariableValue(name));
}
switch (property.GetCSSProperty().PropertyID()) {
case CSSPropertyID::kBackgroundColor:
return a.BackgroundColor() == b.BackgroundColor() &&
a.InternalVisitedBackgroundColor() ==
b.InternalVisitedBackgroundColor();
case CSSPropertyID::kBackgroundImage:
return FillLayersEqual<CSSPropertyID::kBackgroundImage>(
a.BackgroundLayers(), b.BackgroundLayers());
case CSSPropertyID::kBackgroundPositionX:
return FillLayersEqual<CSSPropertyID::kBackgroundPositionX>(
a.BackgroundLayers(), b.BackgroundLayers());
case CSSPropertyID::kBackgroundPositionY:
return FillLayersEqual<CSSPropertyID::kBackgroundPositionY>(
a.BackgroundLayers(), b.BackgroundLayers());
case CSSPropertyID::kBackgroundSize:
return FillLayersEqual<CSSPropertyID::kBackgroundSize>(
a.BackgroundLayers(), b.BackgroundLayers());
case CSSPropertyID::kBaselineShift:
return a.BaselineShift() == b.BaselineShift();
case CSSPropertyID::kBorderBottomColor:
return a.BorderBottomColor() == b.BorderBottomColor() &&
a.InternalVisitedBorderBottomColor() ==
b.InternalVisitedBorderBottomColor();
case CSSPropertyID::kBorderBottomLeftRadius:
return a.BorderBottomLeftRadius() == b.BorderBottomLeftRadius();
case CSSPropertyID::kBorderBottomRightRadius:
return a.BorderBottomRightRadius() == b.BorderBottomRightRadius();
case CSSPropertyID::kBorderBottomWidth:
return a.BorderBottomWidth() == b.BorderBottomWidth();
case CSSPropertyID::kBorderImageOutset:
return a.BorderImageOutset() == b.BorderImageOutset();
case CSSPropertyID::kBorderImageSlice:
return a.BorderImageSlices() == b.BorderImageSlices();
case CSSPropertyID::kBorderImageSource:
return DataEquivalent(a.BorderImageSource(), b.BorderImageSource());
case CSSPropertyID::kBorderImageWidth:
return a.BorderImageWidth() == b.BorderImageWidth();
case CSSPropertyID::kBorderLeftColor:
return a.BorderLeftColor() == b.BorderLeftColor() &&
a.InternalVisitedBorderLeftColor() ==
b.InternalVisitedBorderLeftColor();
case CSSPropertyID::kBorderLeftWidth:
return a.BorderLeftWidth() == b.BorderLeftWidth();
case CSSPropertyID::kBorderRightColor:
return a.BorderRightColor() == b.BorderRightColor() &&
a.InternalVisitedBorderRightColor() ==
b.InternalVisitedBorderRightColor();
case CSSPropertyID::kBorderRightWidth:
return a.BorderRightWidth() == b.BorderRightWidth();
case CSSPropertyID::kBorderTopColor:
return a.BorderTopColor() == b.BorderTopColor() &&
a.InternalVisitedBorderTopColor() ==
b.InternalVisitedBorderTopColor();
case CSSPropertyID::kBorderTopLeftRadius:
return a.BorderTopLeftRadius() == b.BorderTopLeftRadius();
case CSSPropertyID::kBorderTopRightRadius:
return a.BorderTopRightRadius() == b.BorderTopRightRadius();
case CSSPropertyID::kBorderTopWidth:
return a.BorderTopWidth() == b.BorderTopWidth();
case CSSPropertyID::kBottom:
return a.Bottom() == b.Bottom();
case CSSPropertyID::kBoxShadow:
return DataEquivalent(a.BoxShadow(), b.BoxShadow());
case CSSPropertyID::kCaretColor:
return a.CaretColor() == b.CaretColor() &&
a.InternalVisitedCaretColor() == b.InternalVisitedCaretColor();
case CSSPropertyID::kClip:
return a.Clip() == b.Clip();
case CSSPropertyID::kColor:
return a.GetColor() == b.GetColor() &&
a.InternalVisitedColor() == b.InternalVisitedColor();
case CSSPropertyID::kFill:
return a.FillPaint().EqualTypeOrColor(b.FillPaint()) &&
a.InternalVisitedFillPaint().EqualTypeOrColor(
b.InternalVisitedFillPaint());
case CSSPropertyID::kFillOpacity:
return a.FillOpacity() == b.FillOpacity();
case CSSPropertyID::kFlexBasis:
return a.FlexBasis() == b.FlexBasis();
case CSSPropertyID::kFlexGrow:
return a.FlexGrow() == b.FlexGrow();
case CSSPropertyID::kFlexShrink:
return a.FlexShrink() == b.FlexShrink();
case CSSPropertyID::kFloodColor:
return a.FloodColor() == b.FloodColor();
case CSSPropertyID::kFloodOpacity:
return a.FloodOpacity() == b.FloodOpacity();
case CSSPropertyID::kFontSize:
// CSSPropertyID::kFontSize: Must pass a specified size to setFontSize if
// Text Autosizing is enabled, but a computed size if text zoom is enabled
// (if neither is enabled it's irrelevant as they're probably the same).
// FIXME: Should we introduce an option to pass the computed font size
// here, allowing consumers to enable text zoom rather than Text
// Autosizing? See http://crbug.com/227545.
return a.SpecifiedFontSize() == b.SpecifiedFontSize();
case CSSPropertyID::kFontSizeAdjust:
return a.FontSizeAdjust() == b.FontSizeAdjust();
case CSSPropertyID::kFontStretch:
return a.GetFontStretch() == b.GetFontStretch();
case CSSPropertyID::kFontVariationSettings:
return DataEquivalent(a.GetFontDescription().VariationSettings(),
b.GetFontDescription().VariationSettings());
case CSSPropertyID::kFontWeight:
return a.GetFontWeight() == b.GetFontWeight();
case CSSPropertyID::kHeight:
return a.Height() == b.Height();
case CSSPropertyID::kLeft:
return a.Left() == b.Left();
case CSSPropertyID::kLetterSpacing:
return a.LetterSpacing() == b.LetterSpacing();
case CSSPropertyID::kLightingColor:
return a.LightingColor() == b.LightingColor();
case CSSPropertyID::kLineHeight:
return a.SpecifiedLineHeight() == b.SpecifiedLineHeight();
case CSSPropertyID::kTabSize:
return a.GetTabSize() == b.GetTabSize();
case CSSPropertyID::kListStyleImage:
return DataEquivalent(a.ListStyleImage(), b.ListStyleImage());
case CSSPropertyID::kMarginBottom:
return a.MarginBottom() == b.MarginBottom();
case CSSPropertyID::kMarginLeft:
return a.MarginLeft() == b.MarginLeft();
case CSSPropertyID::kMarginRight:
return a.MarginRight() == b.MarginRight();
case CSSPropertyID::kMarginTop:
return a.MarginTop() == b.MarginTop();
case CSSPropertyID::kMaxHeight:
return a.MaxHeight() == b.MaxHeight();
case CSSPropertyID::kMaxWidth:
return a.MaxWidth() == b.MaxWidth();
case CSSPropertyID::kMinHeight:
return a.MinHeight() == b.MinHeight();
case CSSPropertyID::kMinWidth:
return a.MinWidth() == b.MinWidth();
case CSSPropertyID::kObjectPosition:
return a.ObjectPosition() == b.ObjectPosition();
case CSSPropertyID::kOffsetAnchor:
return a.OffsetAnchor() == b.OffsetAnchor();
case CSSPropertyID::kOffsetDistance:
return a.OffsetDistance() == b.OffsetDistance();
case CSSPropertyID::kOffsetPath:
return DataEquivalent(a.OffsetPath(), b.OffsetPath());
case CSSPropertyID::kOffsetPosition:
return a.OffsetPosition() == b.OffsetPosition();
case CSSPropertyID::kOffsetRotate:
return a.OffsetRotate() == b.OffsetRotate();
case CSSPropertyID::kOpacity:
return a.Opacity() == b.Opacity();
case CSSPropertyID::kOrder:
return a.Order() == b.Order();
case CSSPropertyID::kOrphans:
return a.Orphans() == b.Orphans();
case CSSPropertyID::kOutlineColor:
return a.OutlineColor() == b.OutlineColor() &&
a.InternalVisitedOutlineColor() == b.InternalVisitedOutlineColor();
case CSSPropertyID::kOutlineOffset:
return a.OutlineOffset() == b.OutlineOffset();
case CSSPropertyID::kOutlineWidth:
return a.OutlineWidth() == b.OutlineWidth();
case CSSPropertyID::kPaddingBottom:
return a.PaddingBottom() == b.PaddingBottom();
case CSSPropertyID::kPaddingLeft:
return a.PaddingLeft() == b.PaddingLeft();
case CSSPropertyID::kPaddingRight:
return a.PaddingRight() == b.PaddingRight();
case CSSPropertyID::kPaddingTop:
return a.PaddingTop() == b.PaddingTop();
case CSSPropertyID::kRight:
return a.Right() == b.Right();
case CSSPropertyID::kShapeImageThreshold:
return a.ShapeImageThreshold() == b.ShapeImageThreshold();
case CSSPropertyID::kShapeMargin:
return a.ShapeMargin() == b.ShapeMargin();
case CSSPropertyID::kShapeOutside:
return DataEquivalent(a.ShapeOutside(), b.ShapeOutside());
case CSSPropertyID::kStopColor:
return a.StopColor() == b.StopColor();
case CSSPropertyID::kStopOpacity:
return a.StopOpacity() == b.StopOpacity();
case CSSPropertyID::kStroke:
return a.StrokePaint().EqualTypeOrColor(b.StrokePaint()) &&
a.InternalVisitedStrokePaint().EqualTypeOrColor(
b.InternalVisitedStrokePaint());
case CSSPropertyID::kStrokeDasharray:
return a.StrokeDashArray() == b.StrokeDashArray();
case CSSPropertyID::kStrokeDashoffset:
return a.StrokeDashOffset() == b.StrokeDashOffset();
case CSSPropertyID::kStrokeMiterlimit:
return a.StrokeMiterLimit() == b.StrokeMiterLimit();
case CSSPropertyID::kStrokeOpacity:
return a.StrokeOpacity() == b.StrokeOpacity();
case CSSPropertyID::kStrokeWidth:
return a.StrokeWidth() == b.StrokeWidth();
case CSSPropertyID::kTextDecorationColor:
return a.TextDecorationColor() == b.TextDecorationColor() &&
a.InternalVisitedTextDecorationColor() ==
b.InternalVisitedTextDecorationColor();
case CSSPropertyID::kTextDecorationSkipInk:
return a.TextDecorationSkipInk() == b.TextDecorationSkipInk();
case CSSPropertyID::kTextIndent:
return a.TextIndent() == b.TextIndent();
case CSSPropertyID::kTextShadow:
return DataEquivalent(a.TextShadow(), b.TextShadow());
case CSSPropertyID::kTextSizeAdjust:
return a.GetTextSizeAdjust() == b.GetTextSizeAdjust();
case CSSPropertyID::kTop:
return a.Top() == b.Top();
case CSSPropertyID::kVerticalAlign:
return a.VerticalAlign() == b.VerticalAlign() &&
(a.VerticalAlign() != EVerticalAlign::kLength ||
a.GetVerticalAlignLength() == b.GetVerticalAlignLength());
case CSSPropertyID::kVisibility:
return a.Visibility() == b.Visibility();
case CSSPropertyID::kWebkitBorderHorizontalSpacing:
return a.HorizontalBorderSpacing() == b.HorizontalBorderSpacing();
case CSSPropertyID::kWebkitBorderVerticalSpacing:
return a.VerticalBorderSpacing() == b.VerticalBorderSpacing();
case CSSPropertyID::kClipPath:
return DataEquivalent(a.ClipPath(), b.ClipPath());
case CSSPropertyID::kColumnCount:
return a.ColumnCount() == b.ColumnCount();
case CSSPropertyID::kColumnGap:
return a.ColumnGap() == b.ColumnGap();
case CSSPropertyID::kRowGap:
return a.RowGap() == b.RowGap();
case CSSPropertyID::kColumnRuleColor:
return a.ColumnRuleColor() == b.ColumnRuleColor() &&
a.InternalVisitedColumnRuleColor() ==
b.InternalVisitedColumnRuleColor();
case CSSPropertyID::kColumnRuleWidth:
return a.ColumnRuleWidth() == b.ColumnRuleWidth();
case CSSPropertyID::kColumnWidth:
return a.ColumnWidth() == b.ColumnWidth();
case CSSPropertyID::kFilter:
return a.Filter() == b.Filter();
case CSSPropertyID::kBackdropFilter:
return a.BackdropFilter() == b.BackdropFilter();
case CSSPropertyID::kWebkitMaskBoxImageOutset:
return a.MaskBoxImageOutset() == b.MaskBoxImageOutset();
case CSSPropertyID::kWebkitMaskBoxImageSlice:
return a.MaskBoxImageSlices() == b.MaskBoxImageSlices();
case CSSPropertyID::kWebkitMaskBoxImageSource:
return DataEquivalent(a.MaskBoxImageSource(), b.MaskBoxImageSource());
case CSSPropertyID::kWebkitMaskBoxImageWidth:
return a.MaskBoxImageWidth() == b.MaskBoxImageWidth();
case CSSPropertyID::kWebkitMaskImage:
return DataEquivalent(a.MaskImage(), b.MaskImage());
case CSSPropertyID::kWebkitMaskPositionX:
return FillLayersEqual<CSSPropertyID::kWebkitMaskPositionX>(
a.MaskLayers(), b.MaskLayers());
case CSSPropertyID::kWebkitMaskPositionY:
return FillLayersEqual<CSSPropertyID::kWebkitMaskPositionY>(
a.MaskLayers(), b.MaskLayers());
case CSSPropertyID::kWebkitMaskSize:
return FillLayersEqual<CSSPropertyID::kWebkitMaskSize>(a.MaskLayers(),
b.MaskLayers());
case CSSPropertyID::kPerspective:
return a.Perspective() == b.Perspective();
case CSSPropertyID::kPerspectiveOrigin:
return a.PerspectiveOriginX() == b.PerspectiveOriginX() &&
a.PerspectiveOriginY() == b.PerspectiveOriginY();
case CSSPropertyID::kWebkitTextStrokeColor:
return a.TextStrokeColor() == b.TextStrokeColor() &&
a.InternalVisitedTextStrokeColor() ==
b.InternalVisitedTextStrokeColor();
case CSSPropertyID::kTransform:
return a.Transform() == b.Transform();
case CSSPropertyID::kTranslate:
return DataEquivalent<TransformOperation>(a.Translate(), b.Translate());
case CSSPropertyID::kRotate:
return DataEquivalent<TransformOperation>(a.Rotate(), b.Rotate());
case CSSPropertyID::kScale:
return DataEquivalent<TransformOperation>(a.Scale(), b.Scale());
case CSSPropertyID::kTransformOrigin:
return a.TransformOriginX() == b.TransformOriginX() &&
a.TransformOriginY() == b.TransformOriginY() &&
a.TransformOriginZ() == b.TransformOriginZ();
case CSSPropertyID::kWebkitPerspectiveOriginX:
return a.PerspectiveOriginX() == b.PerspectiveOriginX();
case CSSPropertyID::kWebkitPerspectiveOriginY:
return a.PerspectiveOriginY() == b.PerspectiveOriginY();
case CSSPropertyID::kWebkitTransformOriginX:
return a.TransformOriginX() == b.TransformOriginX();
case CSSPropertyID::kWebkitTransformOriginY:
return a.TransformOriginY() == b.TransformOriginY();
case CSSPropertyID::kWebkitTransformOriginZ:
return a.TransformOriginZ() == b.TransformOriginZ();
case CSSPropertyID::kWidows:
return a.Widows() == b.Widows();
case CSSPropertyID::kWidth:
return a.Width() == b.Width();
case CSSPropertyID::kWordSpacing:
return a.WordSpacing() == b.WordSpacing();
case CSSPropertyID::kD:
return DataEquivalent(a.D(), b.D());
case CSSPropertyID::kCx:
return a.Cx() == b.Cx();
case CSSPropertyID::kCy:
return a.Cy() == b.Cy();
case CSSPropertyID::kX:
return a.X() == b.X();
case CSSPropertyID::kY:
return a.Y() == b.Y();
case CSSPropertyID::kR:
return a.R() == b.R();
case CSSPropertyID::kRx:
return a.Rx() == b.Rx();
case CSSPropertyID::kRy:
return a.Ry() == b.Ry();
case CSSPropertyID::kZIndex:
return a.HasAutoZIndex() == b.HasAutoZIndex() &&
(a.HasAutoZIndex() || a.ZIndex() == b.ZIndex());
case CSSPropertyID::kContainIntrinsicSize:
return a.ContainIntrinsicSize() == b.ContainIntrinsicSize();
case CSSPropertyID::kAspectRatio:
return a.AspectRatio() == b.AspectRatio();
case CSSPropertyID::kMathDepth:
return a.MathDepth() == b.MathDepth();
default:
NOTREACHED();
return true;
}
}
} // namespace blink