/*
 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "core/style/ComputedStyle.h"

#include <algorithm>
#include <memory>
#include "core/animation/css/CSSAnimationData.h"
#include "core/animation/css/CSSTransitionData.h"
#include "core/css/CSSPaintValue.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSPropertyEquality.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/layout/LayoutTheme.h"
#include "core/layout/TextAutosizer.h"
#include "core/style/AppliedTextDecoration.h"
#include "core/style/BorderEdge.h"
#include "core/style/ComputedStyleConstants.h"
#include "core/style/ContentData.h"
#include "core/style/CursorData.h"
#include "core/style/DataEquivalency.h"
#include "core/style/QuotesData.h"
#include "core/style/ShadowList.h"
#include "core/style/StyleImage.h"
#include "core/style/StyleInheritedData.h"
#include "core/style/StyleInheritedVariables.h"
#include "core/style/StyleNonInheritedVariables.h"
#include "platform/LengthFunctions.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/Font.h"
#include "platform/fonts/FontSelector.h"
#include "platform/geometry/FloatRoundedRect.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/transforms/RotateTransformOperation.h"
#include "platform/transforms/ScaleTransformOperation.h"
#include "platform/transforms/TranslateTransformOperation.h"
#include "platform/wtf/MathExtras.h"
#include "platform/wtf/PtrUtil.h"
#include "platform/wtf/SaturatedArithmetic.h"
#include "platform/wtf/SizeAssertions.h"

namespace blink {

struct SameSizeAsBorderValue {
  RGBA32 color_;
  unsigned bitfield_;
};

ASSERT_SIZE(BorderValue, SameSizeAsBorderValue);

// Since different compilers/architectures pack ComputedStyle differently,
// re-create the same structure for an accurate size comparison.
struct SameSizeAsComputedStyle : public RefCounted<SameSizeAsComputedStyle> {
  struct ComputedStyleBase {
    unsigned bitfields_[4];
  } base_;

  void* data_refs[7];
  void* own_ptrs[1];
  void* data_ref_svg_style;
};

// If this assert fails, it means that size of ComputedStyle has changed. Please
// check that you really *do* what to increase the size of ComputedStyle, then
// update the SameSizeAsComputedStyle struct to match the updated storage of
// ComputedStyle.
ASSERT_SIZE(ComputedStyle, SameSizeAsComputedStyle);

PassRefPtr<ComputedStyle> ComputedStyle::Create() {
  return AdoptRef(new ComputedStyle(InitialStyle()));
}

PassRefPtr<ComputedStyle> ComputedStyle::CreateInitialStyle() {
  return AdoptRef(new ComputedStyle());
}

void ComputedStyle::InvalidateInitialStyle() {
  MutableInitialStyle().SetTapHighlightColor(InitialTapHighlightColor());
}

PassRefPtr<ComputedStyle> ComputedStyle::CreateAnonymousStyleWithDisplay(
    const ComputedStyle& parent_style,
    EDisplay display) {
  RefPtr<ComputedStyle> new_style = ComputedStyle::Create();
  new_style->InheritFrom(parent_style);
  new_style->SetUnicodeBidi(parent_style.GetUnicodeBidi());
  new_style->SetDisplay(display);
  return new_style;
}

PassRefPtr<ComputedStyle> ComputedStyle::Clone(const ComputedStyle& other) {
  return AdoptRef(new ComputedStyle(other));
}

ALWAYS_INLINE ComputedStyle::ComputedStyle()
    : ComputedStyleBase(), RefCounted<ComputedStyle>() {
  box_data_.Init();
  visual_data_.Init();
  background_data_.Init();
  rare_non_inherited_data_.Init();
  rare_non_inherited_data_.Access()->deprecated_flexible_box_.Init();
  rare_non_inherited_data_.Access()->flexible_box_.Init();
  rare_non_inherited_data_.Access()->multi_col_.Init();
  rare_non_inherited_data_.Access()->transform_.Init();
  rare_non_inherited_data_.Access()->will_change_.Init();
  rare_non_inherited_data_.Access()->filter_.Init();
  rare_non_inherited_data_.Access()->backdrop_filter_.Init();
  rare_non_inherited_data_.Access()->grid_.Init();
  rare_non_inherited_data_.Access()->grid_item_.Init();
  rare_non_inherited_data_.Access()->scroll_snap_.Init();
  rare_inherited_data_.Init();
  inherited_data_.Init();
  svg_style_.Init();
}

ALWAYS_INLINE ComputedStyle::ComputedStyle(const ComputedStyle& o)
    : ComputedStyleBase(o),
      RefCounted<ComputedStyle>(),
      box_data_(o.box_data_),
      visual_data_(o.visual_data_),
      background_data_(o.background_data_),
      rare_non_inherited_data_(o.rare_non_inherited_data_),
      rare_inherited_data_(o.rare_inherited_data_),
      inherited_data_(o.inherited_data_),
      svg_style_(o.svg_style_) {}

static StyleRecalcChange DiffPseudoStyles(const ComputedStyle& old_style,
                                          const ComputedStyle& new_style) {
  // If the pseudoStyles have changed, ensure layoutObject triggers setStyle.
  if (!old_style.HasAnyPublicPseudoStyles() &&
      !new_style.HasAnyPublicPseudoStyles())
    return kNoChange;
  for (PseudoId pseudo_id = kFirstPublicPseudoId;
       pseudo_id < kFirstInternalPseudoId;
       pseudo_id = static_cast<PseudoId>(pseudo_id + 1)) {
    if (!old_style.HasPseudoStyle(pseudo_id) &&
        !new_style.HasPseudoStyle(pseudo_id))
      continue;
    const ComputedStyle* new_pseudo_style =
        new_style.GetCachedPseudoStyle(pseudo_id);
    if (!new_pseudo_style)
      return kNoInherit;
    const ComputedStyle* old_pseudo_style =
        old_style.GetCachedPseudoStyle(pseudo_id);
    if (old_pseudo_style && *old_pseudo_style != *new_pseudo_style)
      return kNoInherit;
  }
  return kNoChange;
}

StyleRecalcChange ComputedStyle::StylePropagationDiff(
    const ComputedStyle* old_style,
    const ComputedStyle* new_style) {
  // If the style has changed from display none or to display none, then the
  // layout subtree needs to be reattached
  if ((!old_style && new_style) || (old_style && !new_style))
    return kReattach;

  if (!old_style && !new_style)
    return kNoChange;

  if (old_style->Display() != new_style->Display() ||
      old_style->HasPseudoStyle(kPseudoIdFirstLetter) !=
          new_style->HasPseudoStyle(kPseudoIdFirstLetter) ||
      !old_style->ContentDataEquivalent(new_style) ||
      old_style->HasTextCombine() != new_style->HasTextCombine())
    return kReattach;

  bool independent_equal = old_style->IndependentInheritedEqual(*new_style);
  bool non_independent_equal =
      old_style->NonIndependentInheritedEqual(*new_style);
  if (!independent_equal || !non_independent_equal) {
    if (non_independent_equal && !old_style->HasExplicitlyInheritedProperties())
      return kIndependentInherit;
    return kInherit;
  }

  if (!old_style->LoadingCustomFontsEqual(*new_style) ||
      old_style->AlignItems() != new_style->AlignItems() ||
      old_style->JustifyItems() != new_style->JustifyItems())
    return kInherit;

  if (*old_style == *new_style)
    return DiffPseudoStyles(*old_style, *new_style);

  if (old_style->HasExplicitlyInheritedProperties())
    return kInherit;

  return kNoInherit;
}

void ComputedStyle::PropagateIndependentInheritedProperties(
    const ComputedStyle& parent_style) {
  ComputedStyleBase::PropagateIndependentInheritedProperties(parent_style);
}

StyleSelfAlignmentData ResolvedSelfAlignment(
    const StyleSelfAlignmentData& value,
    ItemPosition normal_value_behavior) {
  // To avoid needing to copy the RareNonInheritedData, we repurpose the 'auto'
  // flag to not just mean 'auto' prior to running the StyleAdjuster but also
  // mean 'normal' after running it.
  if (value.GetPosition() == kItemPositionNormal ||
      value.GetPosition() == kItemPositionAuto)
    return {normal_value_behavior, kOverflowAlignmentDefault};
  return value;
}

StyleSelfAlignmentData ComputedStyle::ResolvedAlignItems(
    ItemPosition normal_value_behaviour) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  return ResolvedSelfAlignment(AlignItems(), normal_value_behaviour);
}

StyleSelfAlignmentData ComputedStyle::ResolvedAlignSelf(
    ItemPosition normal_value_behaviour,
    const ComputedStyle* parent_style) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  if (!parent_style || AlignSelfPosition() != kItemPositionAuto)
    return ResolvedSelfAlignment(AlignSelf(), normal_value_behaviour);

  // We shouldn't need to resolve any 'auto' value in post-adjusment
  // ComputedStyle, but some layout models can generate anonymous boxes that may
  // need 'auto' value resolution during layout.
  // The 'auto' keyword computes to the parent's align-items computed value.
  return parent_style->ResolvedAlignItems(normal_value_behaviour);
}

StyleSelfAlignmentData ComputedStyle::ResolvedJustifyItems(
    ItemPosition normal_value_behaviour) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  return ResolvedSelfAlignment(JustifyItems(), normal_value_behaviour);
}

StyleSelfAlignmentData ComputedStyle::ResolvedJustifySelf(
    ItemPosition normal_value_behaviour,
    const ComputedStyle* parent_style) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  if (!parent_style || JustifySelfPosition() != kItemPositionAuto)
    return ResolvedSelfAlignment(JustifySelf(), normal_value_behaviour);

  // We shouldn't need to resolve any 'auto' value in post-adjusment
  // ComputedStyle, but some layout models can generate anonymous boxes that may
  // need 'auto' value resolution during layout.
  // The auto keyword computes to the parent's justify-items computed value.
  return parent_style->ResolvedJustifyItems(normal_value_behaviour);
}

static inline ContentPosition ResolvedContentAlignmentPosition(
    const StyleContentAlignmentData& value,
    const StyleContentAlignmentData& normal_value_behavior) {
  return (value.GetPosition() == kContentPositionNormal &&
          value.Distribution() == kContentDistributionDefault)
             ? normal_value_behavior.GetPosition()
             : value.GetPosition();
}

static inline ContentDistributionType ResolvedContentAlignmentDistribution(
    const StyleContentAlignmentData& value,
    const StyleContentAlignmentData& normal_value_behavior) {
  return (value.GetPosition() == kContentPositionNormal &&
          value.Distribution() == kContentDistributionDefault)
             ? normal_value_behavior.Distribution()
             : value.Distribution();
}

ContentPosition ComputedStyle::ResolvedJustifyContentPosition(
    const StyleContentAlignmentData& normal_value_behavior) const {
  return ResolvedContentAlignmentPosition(JustifyContent(),
                                          normal_value_behavior);
}

ContentDistributionType ComputedStyle::ResolvedJustifyContentDistribution(
    const StyleContentAlignmentData& normal_value_behavior) const {
  return ResolvedContentAlignmentDistribution(JustifyContent(),
                                              normal_value_behavior);
}

ContentPosition ComputedStyle::ResolvedAlignContentPosition(
    const StyleContentAlignmentData& normal_value_behavior) const {
  return ResolvedContentAlignmentPosition(AlignContent(),
                                          normal_value_behavior);
}

ContentDistributionType ComputedStyle::ResolvedAlignContentDistribution(
    const StyleContentAlignmentData& normal_value_behavior) const {
  return ResolvedContentAlignmentDistribution(AlignContent(),
                                              normal_value_behavior);
}

void ComputedStyle::InheritFrom(const ComputedStyle& inherit_parent,
                                IsAtShadowBoundary is_at_shadow_boundary) {
  ComputedStyleBase::InheritFrom(inherit_parent, is_at_shadow_boundary);
  if (is_at_shadow_boundary == kAtShadowBoundary) {
    // Even if surrounding content is user-editable, shadow DOM should act as a
    // single unit, and not necessarily be editable
    EUserModify current_user_modify = UserModify();
    rare_inherited_data_ = inherit_parent.rare_inherited_data_;
    SetUserModify(current_user_modify);
  } else {
    rare_inherited_data_ = inherit_parent.rare_inherited_data_;
  }
  inherited_data_ = inherit_parent.inherited_data_;
  if (svg_style_ != inherit_parent.svg_style_)
    svg_style_.Access()->InheritFrom(inherit_parent.svg_style_.Get());
}

void ComputedStyle::CopyNonInheritedFromCached(const ComputedStyle& other) {
  ComputedStyleBase::CopyNonInheritedFromCached(other);
  box_data_ = other.box_data_;
  visual_data_ = other.visual_data_;
  background_data_ = other.background_data_;
  rare_non_inherited_data_ = other.rare_non_inherited_data_;

  // The flags are copied one-by-one because they contain
  // bunch of stuff other than real style data.
  // See comments for each skipped flag below.

  // These are not generated in ComputedStyleBase
  SetHasViewportUnits(other.HasViewportUnits());
  SetHasRemUnitsInternal(other.HasRemUnits());

  // Correctly set during selector matching:
  // m_styleType
  // m_pseudoBits

  // Set correctly while computing style for children:
  // m_explicitInheritance

  // unique() styles are not cacheable.
  DCHECK(!other.Unique());

  // styles with non inherited properties that reference variables are not
  // cacheable.
  DCHECK(!other.HasVariableReferenceFromNonInheritedProperty());

  // The following flags are set during matching before we decide that we get a
  // match in the MatchedPropertiesCache which in turn calls this method. The
  // reason why we don't copy these flags is that they're already correctly set
  // and that they may differ between elements which have the same set of
  // matched properties. For instance, given the rule:
  //
  // :-webkit-any(:hover, :focus) { background-color: green }"
  //
  // A hovered element, and a focused element may use the same cached matched
  // properties here, but the affectedBy flags will be set differently based on
  // the matching order of the :-webkit-any components.
  //
  // m_emptyState
  // m_affectedByFocus
  // m_affectedByHover
  // m_affectedByActive
  // m_affectedByDrag
  // m_isLink

  if (svg_style_ != other.svg_style_)
    svg_style_.Access()->CopyNonInheritedFromCached(other.svg_style_.Get());
  DCHECK_EQ(Zoom(), InitialZoom());
}

bool ComputedStyle::operator==(const ComputedStyle& o) const {
  return InheritedEqual(o) && NonInheritedEqual(o);
}

bool ComputedStyle::IsStyleAvailable() const {
  return this != StyleResolver::StyleNotYetAvailable();
}

bool ComputedStyle::HasUniquePseudoStyle() const {
  if (!cached_pseudo_styles_ || StyleType() != kPseudoIdNone)
    return false;

  for (size_t i = 0; i < cached_pseudo_styles_->size(); ++i) {
    const ComputedStyle& pseudo_style = *cached_pseudo_styles_->at(i);
    if (pseudo_style.Unique())
      return true;
  }

  return false;
}

ComputedStyle* ComputedStyle::GetCachedPseudoStyle(PseudoId pid) const {
  if (!cached_pseudo_styles_ || !cached_pseudo_styles_->size())
    return 0;

  if (StyleType() != kPseudoIdNone)
    return 0;

  for (size_t i = 0; i < cached_pseudo_styles_->size(); ++i) {
    ComputedStyle* pseudo_style = cached_pseudo_styles_->at(i).Get();
    if (pseudo_style->StyleType() == pid)
      return pseudo_style;
  }

  return 0;
}

ComputedStyle* ComputedStyle::AddCachedPseudoStyle(
    PassRefPtr<ComputedStyle> pseudo) {
  if (!pseudo)
    return 0;

  DCHECK_GT(pseudo->StyleType(), kPseudoIdNone);

  ComputedStyle* result = pseudo.Get();

  if (!cached_pseudo_styles_)
    cached_pseudo_styles_ = WTF::WrapUnique(new PseudoStyleCache);

  cached_pseudo_styles_->push_back(std::move(pseudo));

  return result;
}

void ComputedStyle::RemoveCachedPseudoStyle(PseudoId pid) {
  if (!cached_pseudo_styles_)
    return;
  for (size_t i = 0; i < cached_pseudo_styles_->size(); ++i) {
    ComputedStyle* pseudo_style = cached_pseudo_styles_->at(i).Get();
    if (pseudo_style->StyleType() == pid) {
      cached_pseudo_styles_->erase(i);
      return;
    }
  }
}

bool ComputedStyle::InheritedEqual(const ComputedStyle& other) const {
  return IndependentInheritedEqual(other) &&
         NonIndependentInheritedEqual(other);
}

bool ComputedStyle::IndependentInheritedEqual(
    const ComputedStyle& other) const {
  return ComputedStyleBase::IndependentInheritedEqual(other);
}

bool ComputedStyle::NonIndependentInheritedEqual(
    const ComputedStyle& other) const {
  return ComputedStyleBase::NonIndependentInheritedEqual(other) &&
         inherited_data_ == other.inherited_data_ &&
         svg_style_->InheritedEqual(*other.svg_style_) &&
         rare_inherited_data_ == other.rare_inherited_data_;
}

bool ComputedStyle::LoadingCustomFontsEqual(const ComputedStyle& other) const {
  return GetFont().LoadingCustomFonts() == other.GetFont().LoadingCustomFonts();
}

bool ComputedStyle::NonInheritedEqual(const ComputedStyle& other) const {
  // compare everything except the pseudoStyle pointer
  return ComputedStyleBase::NonInheritedEqual(other) &&
         box_data_ == other.box_data_ &&
         visual_data_ == other.visual_data_ &&
         background_data_ == other.background_data_ &&
         rare_non_inherited_data_ == other.rare_non_inherited_data_ &&
         svg_style_->NonInheritedEqual(*other.svg_style_);
}

bool ComputedStyle::InheritedDataShared(const ComputedStyle& other) const {
  // This is a fast check that only looks if the data structures are shared.
  // TODO(sashab): Should ComputedStyleBase have an inheritedDataShared method?
  return ComputedStyleBase::InheritedEqual(other) &&
         inherited_data_.Get() == other.inherited_data_.Get() &&
         svg_style_.Get() == other.svg_style_.Get() &&
         rare_inherited_data_.Get() == other.rare_inherited_data_.Get();
}

static bool DependenceOnContentHeightHasChanged(const ComputedStyle& a,
                                                const ComputedStyle& b) {
  // If top or bottom become auto/non-auto then it means we either have to solve
  // height based on the content or stop doing so
  // (http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height)
  // - either way requires a layout.
  return a.LogicalTop().IsAuto() != b.LogicalTop().IsAuto() ||
         a.LogicalBottom().IsAuto() != b.LogicalBottom().IsAuto();
}

StyleDifference ComputedStyle::VisualInvalidationDiff(
    const ComputedStyle& other) const {
  // Note, we use .Get() on each DataRef below because DataRef::operator== will
  // do a deep compare, which is duplicate work when we're going to compare each
  // property inside this function anyway.

  StyleDifference diff;
  if (svg_style_.Get() != other.svg_style_.Get())
    diff = svg_style_->Diff(other.svg_style_.Get());

  if ((!diff.NeedsFullLayout() || !diff.NeedsFullPaintInvalidation()) &&
      DiffNeedsFullLayoutAndPaintInvalidation(other)) {
    diff.SetNeedsFullLayout();
    diff.SetNeedsPaintInvalidationObject();
  }

  if (!diff.NeedsFullLayout() && DiffNeedsFullLayout(other))
    diff.SetNeedsFullLayout();

  if (!diff.NeedsFullLayout() && !MarginEqual(other)) {
    // Relative-positioned elements collapse their margins so need a full
    // layout.
    if (HasOutOfFlowPosition())
      diff.SetNeedsPositionedMovementLayout();
    else
      diff.SetNeedsFullLayout();
  }

  if (!diff.NeedsFullLayout() && GetPosition() != EPosition::kStatic &&
      !OffsetEqual(other)) {
    // Optimize for the case where a positioned layer is moving but not changing
    // size.
    if (DependenceOnContentHeightHasChanged(*this, other))
      diff.SetNeedsFullLayout();
    else
      diff.SetNeedsPositionedMovementLayout();
  }

  if (DiffNeedsPaintInvalidationSubtree(other))
    diff.SetNeedsPaintInvalidationSubtree();
  else if (DiffNeedsPaintInvalidationObject(other))
    diff.SetNeedsPaintInvalidationObject();

  if (DiffNeedsVisualRectUpdate(other))
    diff.SetNeedsVisualRectUpdate();

  UpdatePropertySpecificDifferences(other, diff);

  // The following condition needs to be at last, because it may depend on
  // conditions in diff computed above.
  if (ScrollAnchorDisablingPropertyChanged(other, diff))
    diff.SetScrollAnchorDisablingPropertyChanged();

  // Cursors are not checked, since they will be set appropriately in response
  // to mouse events, so they don't need to cause any paint invalidation or
  // layout.

  // Animations don't need to be checked either. We always set the new style on
  // the layoutObject, so we will get a chance to fire off the resulting
  // transition properly.

  return diff;
}

bool ComputedStyle::ScrollAnchorDisablingPropertyChanged(
    const ComputedStyle& other,
    const StyleDifference& diff) const {
  if (GetPosition() != other.GetPosition())
    return true;

  if (box_data_.Get() != other.box_data_.Get()) {
    if (box_data_->width_ != other.box_data_->width_ ||
        box_data_->min_width_ != other.box_data_->min_width_ ||
        box_data_->max_width_ != other.box_data_->max_width_ ||
        box_data_->height_ != other.box_data_->height_ ||
        box_data_->min_height_ != other.box_data_->min_height_ ||
        box_data_->max_height_ != other.box_data_->max_height_)
      return true;
  }

  if (ComputedStyleBase::ScrollAnchorDisablingPropertyChanged(other, diff))
    return true;

  if (diff.TransformChanged())
    return true;

  return false;
}

bool ComputedStyle::DiffNeedsFullLayoutAndPaintInvalidation(
    const ComputedStyle& other) const {
  // FIXME: Not all cases in this method need both full layout and paint
  // invalidation.
  // Should move cases into DiffNeedsFullLayout() if
  // - don't need paint invalidation at all;
  // - or the layoutObject knows how to exactly invalidate paints caused by the
  //   layout change instead of forced full paint invalidation.

  if (surround_data_.Get() != other.surround_data_.Get()) {
    // If our border widths change, then we need to layout. Other changes to
    // borders only necessitate a paint invalidation.
    if (BorderLeftWidth() != other.BorderLeftWidth() ||
        BorderTopWidth() != other.BorderTopWidth() ||
        BorderBottomWidth() != other.BorderBottomWidth() ||
        BorderRightWidth() != other.BorderRightWidth())
      return true;
  }

  if (ComputedStyleBase::DiffNeedsFullLayoutAndPaintInvalidation(other))
    return true;

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->appearance_ !=
            other.rare_non_inherited_data_->appearance_ ||
        rare_non_inherited_data_->margin_before_collapse !=
            other.rare_non_inherited_data_->margin_before_collapse ||
        rare_non_inherited_data_->margin_after_collapse !=
            other.rare_non_inherited_data_->margin_after_collapse ||
        rare_non_inherited_data_->line_clamp !=
            other.rare_non_inherited_data_->line_clamp ||
        rare_non_inherited_data_->text_overflow !=
            other.rare_non_inherited_data_->text_overflow ||
        rare_non_inherited_data_->shape_margin_ !=
            other.rare_non_inherited_data_->shape_margin_ ||
        rare_non_inherited_data_->order_ !=
            other.rare_non_inherited_data_->order_ ||
        rare_non_inherited_data_->HasFilters() !=
            other.rare_non_inherited_data_->HasFilters())
      return true;

    if (rare_non_inherited_data_->grid_.Get() !=
            other.rare_non_inherited_data_->grid_.Get() &&
        *rare_non_inherited_data_->grid_.Get() !=
            *other.rare_non_inherited_data_->grid_.Get())
      return true;

    if (rare_non_inherited_data_->grid_item_.Get() !=
            other.rare_non_inherited_data_->grid_item_.Get() &&
        *rare_non_inherited_data_->grid_item_.Get() !=
            *other.rare_non_inherited_data_->grid_item_.Get())
      return true;

    if (rare_non_inherited_data_->deprecated_flexible_box_.Get() !=
            other.rare_non_inherited_data_->deprecated_flexible_box_.Get() &&
        *rare_non_inherited_data_->deprecated_flexible_box_.Get() !=
            *other.rare_non_inherited_data_->deprecated_flexible_box_.Get())
      return true;

    if (rare_non_inherited_data_->flexible_box_.Get() !=
            other.rare_non_inherited_data_->flexible_box_.Get() &&
        *rare_non_inherited_data_->flexible_box_.Get() !=
            *other.rare_non_inherited_data_->flexible_box_.Get())
      return true;

    if (rare_non_inherited_data_->multi_col_.Get() !=
            other.rare_non_inherited_data_->multi_col_.Get() &&
        *rare_non_inherited_data_->multi_col_.Get() !=
            *other.rare_non_inherited_data_->multi_col_.Get())
      return true;

    // If the counter directives change, trigger a relayout to re-calculate
    // counter values and rebuild the counter node tree.
    const CounterDirectiveMap* map_a =
        rare_non_inherited_data_->counter_directives_.get();
    const CounterDirectiveMap* map_b =
        other.rare_non_inherited_data_->counter_directives_.get();
    if (!(map_a == map_b || (map_a && map_b && *map_a == *map_b)))
      return true;

    // We only need do layout for opacity changes if adding or losing opacity
    // could trigger a change
    // in us being a stacking context.
    if (IsStackingContext() != other.IsStackingContext() &&
        rare_non_inherited_data_->HasOpacity() !=
            other.rare_non_inherited_data_->HasOpacity()) {
      // FIXME: We would like to use SimplifiedLayout here, but we can't quite
      // do that yet.  We need to make sure SimplifiedLayout can operate
      // correctly on LayoutInlines (we will need to add a
      // selfNeedsSimplifiedLayout bit in order to not get confused and taint
      // every line).  In addition we need to solve the floating object issue
      // when layers come and go. Right now a full layout is necessary to keep
      // floating object lists sane.
      return true;
    }
  }

  if (rare_inherited_data_.Get() != other.rare_inherited_data_.Get()) {
    if (rare_inherited_data_->highlight !=
            other.rare_inherited_data_->highlight ||
        rare_inherited_data_->indent != other.rare_inherited_data_->indent ||
        rare_inherited_data_->text_align_last_ !=
            other.rare_inherited_data_->text_align_last_ ||
        rare_inherited_data_->text_indent_line_ !=
            other.rare_inherited_data_->text_indent_line_ ||
        rare_inherited_data_->effective_zoom_ !=
            other.rare_inherited_data_->effective_zoom_ ||
        rare_inherited_data_->word_break !=
            other.rare_inherited_data_->word_break ||
        rare_inherited_data_->overflow_wrap !=
            other.rare_inherited_data_->overflow_wrap ||
        rare_inherited_data_->line_break !=
            other.rare_inherited_data_->line_break ||
        rare_inherited_data_->text_security !=
            other.rare_inherited_data_->text_security ||
        rare_inherited_data_->hyphens != other.rare_inherited_data_->hyphens ||
        rare_inherited_data_->hyphenation_limit_before !=
            other.rare_inherited_data_->hyphenation_limit_before ||
        rare_inherited_data_->hyphenation_limit_after !=
            other.rare_inherited_data_->hyphenation_limit_after ||
        rare_inherited_data_->hyphenation_string !=
            other.rare_inherited_data_->hyphenation_string ||
        rare_inherited_data_->respect_image_orientation_ !=
            other.rare_inherited_data_->respect_image_orientation_ ||
        rare_inherited_data_->ruby_position_ !=
            other.rare_inherited_data_->ruby_position_ ||
        rare_inherited_data_->text_emphasis_mark !=
            other.rare_inherited_data_->text_emphasis_mark ||
        rare_inherited_data_->text_emphasis_position !=
            other.rare_inherited_data_->text_emphasis_position ||
        rare_inherited_data_->text_emphasis_custom_mark !=
            other.rare_inherited_data_->text_emphasis_custom_mark ||
        rare_inherited_data_->text_justify_ !=
            other.rare_inherited_data_->text_justify_ ||
        rare_inherited_data_->text_orientation_ !=
            other.rare_inherited_data_->text_orientation_ ||
        rare_inherited_data_->text_combine_ !=
            other.rare_inherited_data_->text_combine_ ||
        rare_inherited_data_->tab_size_ !=
            other.rare_inherited_data_->tab_size_ ||
        rare_inherited_data_->text_size_adjust_ !=
            other.rare_inherited_data_->text_size_adjust_ ||
        rare_inherited_data_->list_style_image !=
            other.rare_inherited_data_->list_style_image ||
        rare_inherited_data_->line_height_step_ !=
            other.rare_inherited_data_->line_height_step_ ||
        rare_inherited_data_->text_stroke_width !=
            other.rare_inherited_data_->text_stroke_width)
      return true;

    if (!rare_inherited_data_->ShadowDataEquivalent(
            *other.rare_inherited_data_.Get()))
      return true;

    if (!rare_inherited_data_->QuotesDataEquivalent(
            *other.rare_inherited_data_.Get()))
      return true;
  }

  if (inherited_data_->text_autosizing_multiplier_ !=
      other.inherited_data_->text_autosizing_multiplier_)
    return true;

  if (inherited_data_->font_.LoadingCustomFonts() !=
      other.inherited_data_->font_.LoadingCustomFonts())
    return true;

  if (inherited_data_.Get() != other.inherited_data_.Get()) {
    if (inherited_data_->line_height_ != other.inherited_data_->line_height_ ||
        inherited_data_->font_ != other.inherited_data_->font_ ||
        inherited_data_->horizontal_border_spacing_ !=
            other.inherited_data_->horizontal_border_spacing_ ||
        inherited_data_->vertical_border_spacing_ !=
            other.inherited_data_->vertical_border_spacing_)
      return true;
  }

  if (BoxDirection() != other.BoxDirection() ||
      RtlOrdering() != other.RtlOrdering() ||
      GetTextAlign() != other.GetTextAlign() ||
      TextTransform() != other.TextTransform() ||
      Direction() != other.Direction() || WhiteSpace() != other.WhiteSpace() ||
      GetWritingMode() != other.GetWritingMode())
    return true;

  if (OverflowX() != other.OverflowX() || OverflowY() != other.OverflowY() ||
      Clear() != other.Clear() || GetUnicodeBidi() != other.GetUnicodeBidi() ||
      Floating() != other.Floating() ||
      OriginalDisplay() != other.OriginalDisplay())
    return true;

  if (IsDisplayTableType(Display())) {
    if (BorderCollapse() != other.BorderCollapse() ||
        EmptyCells() != other.EmptyCells() ||
        CaptionSide() != other.CaptionSide() ||
        TableLayout() != other.TableLayout())
      return true;

    // In the collapsing border model, 'hidden' suppresses other borders, while
    // 'none' does not, so these style differences can be width differences.
    if ((BorderCollapse() == EBorderCollapse::kCollapse) &&
        ((BorderTopStyle() == kBorderStyleHidden &&
          other.BorderTopStyle() == kBorderStyleNone) ||
         (BorderTopStyle() == kBorderStyleNone &&
          other.BorderTopStyle() == kBorderStyleHidden) ||
         (BorderBottomStyle() == kBorderStyleHidden &&
          other.BorderBottomStyle() == kBorderStyleNone) ||
         (BorderBottomStyle() == kBorderStyleNone &&
          other.BorderBottomStyle() == kBorderStyleHidden) ||
         (BorderLeftStyle() == kBorderStyleHidden &&
          other.BorderLeftStyle() == kBorderStyleNone) ||
         (BorderLeftStyle() == kBorderStyleNone &&
          other.BorderLeftStyle() == kBorderStyleHidden) ||
         (BorderRightStyle() == kBorderStyleHidden &&
          other.BorderRightStyle() == kBorderStyleNone) ||
         (BorderRightStyle() == kBorderStyleNone &&
          other.BorderRightStyle() == kBorderStyleHidden)))
      return true;
  } else if (Display() == EDisplay::kListItem) {
    if (ListStyleType() != other.ListStyleType() ||
        ListStylePosition() != other.ListStylePosition())
      return true;
  }

  if ((Visibility() == EVisibility::kCollapse) !=
      (other.Visibility() == EVisibility::kCollapse))
    return true;

  if (HasPseudoStyle(kPseudoIdScrollbar) !=
      other.HasPseudoStyle(kPseudoIdScrollbar))
    return true;

  // Movement of non-static-positioned object is special cased in
  // ComputedStyle::VisualInvalidationDiff().

  return false;
}

bool ComputedStyle::DiffNeedsFullLayout(const ComputedStyle& other) const {
  if (box_data_.Get() != other.box_data_.Get()) {
    if (box_data_->width_ != other.box_data_->width_ ||
        box_data_->min_width_ != other.box_data_->min_width_ ||
        box_data_->max_width_ != other.box_data_->max_width_ ||
        box_data_->height_ != other.box_data_->height_ ||
        box_data_->min_height_ != other.box_data_->min_height_ ||
        box_data_->max_height_ != other.box_data_->max_height_)
      return true;

    if (box_data_->vertical_align_length_ !=
        other.box_data_->vertical_align_length_)
      return true;

    if (box_data_->box_sizing_ != other.box_data_->box_sizing_)
      return true;
  }

  if (VerticalAlign() != other.VerticalAlign() ||
      GetPosition() != other.GetPosition())
    return true;

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->align_content_ !=
            other.rare_non_inherited_data_->align_content_ ||
        rare_non_inherited_data_->align_items_ !=
            other.rare_non_inherited_data_->align_items_ ||
        rare_non_inherited_data_->align_self_ !=
            other.rare_non_inherited_data_->align_self_ ||
        rare_non_inherited_data_->justify_content_ !=
            other.rare_non_inherited_data_->justify_content_ ||
        rare_non_inherited_data_->justify_items_ !=
            other.rare_non_inherited_data_->justify_items_ ||
        rare_non_inherited_data_->justify_self_ !=
            other.rare_non_inherited_data_->justify_self_ ||
        rare_non_inherited_data_->contain_ !=
            other.rare_non_inherited_data_->contain_)
      return true;
  }

  return false;
}

bool ComputedStyle::DiffNeedsPaintInvalidationSubtree(
    const ComputedStyle& other) const {
  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->effective_blend_mode_ !=
            other.rare_non_inherited_data_->effective_blend_mode_ ||
        rare_non_inherited_data_->isolation_ !=
            other.rare_non_inherited_data_->isolation_)
      return true;

    if (rare_non_inherited_data_->mask_ !=
            other.rare_non_inherited_data_->mask_ ||
        rare_non_inherited_data_->mask_box_image_ !=
            other.rare_non_inherited_data_->mask_box_image_)
      return true;
  }

  return false;
}

bool ComputedStyle::DiffNeedsPaintInvalidationObject(
    const ComputedStyle& other) const {
  if (Visibility() != other.Visibility() ||
      PrintColorAdjust() != other.PrintColorAdjust() ||
      InsideLink() != other.InsideLink() ||
      !Border().VisuallyEqual(other.Border()) || !RadiiEqual(other) ||
      *background_data_ != *other.background_data_)
    return true;

  if (rare_inherited_data_.Get() != other.rare_inherited_data_.Get()) {
    if (rare_inherited_data_->user_modify !=
            other.rare_inherited_data_->user_modify ||
        rare_inherited_data_->user_select !=
            other.rare_inherited_data_->user_select ||
        rare_inherited_data_->image_rendering_ !=
            other.rare_inherited_data_->image_rendering_)
      return true;
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->user_drag !=
            other.rare_non_inherited_data_->user_drag ||
        rare_non_inherited_data_->object_fit_ !=
            other.rare_non_inherited_data_->object_fit_ ||
        rare_non_inherited_data_->object_position_ !=
            other.rare_non_inherited_data_->object_position_ ||
        !rare_non_inherited_data_->ShadowDataEquivalent(
            *other.rare_non_inherited_data_.Get()) ||
        !rare_non_inherited_data_->ShapeOutsideDataEquivalent(
            *other.rare_non_inherited_data_.Get()) ||
        !rare_non_inherited_data_->ClipPathDataEquivalent(
            *other.rare_non_inherited_data_.Get()) ||
        !rare_non_inherited_data_->outline_.VisuallyEqual(
            other.rare_non_inherited_data_->outline_) ||
        (VisitedLinkBorderLeftColor() != other.VisitedLinkBorderLeftColor() &&
         BorderLeftWidth()) ||
        (VisitedLinkBorderRightColor() != other.VisitedLinkBorderRightColor() &&
         BorderRightWidth()) ||
        (VisitedLinkBorderBottomColor() !=
             other.VisitedLinkBorderBottomColor() &&
         BorderBottomWidth()) ||
        (VisitedLinkBorderTopColor() != other.VisitedLinkBorderTopColor() &&
         BorderTopWidth()) ||
        (VisitedLinkOutlineColor() != other.VisitedLinkOutlineColor() &&
         OutlineWidth()) ||
        (VisitedLinkBackgroundColor() != other.VisitedLinkBackgroundColor()))
      return true;
  }

  if (Resize() != other.Resize())
    return true;

  if (rare_non_inherited_data_->paint_images_) {
    for (const auto& image : *rare_non_inherited_data_->paint_images_) {
      if (DiffNeedsPaintInvalidationObjectForPaintImage(image, other))
        return true;
    }
  }

  return false;
}

bool ComputedStyle::DiffNeedsPaintInvalidationObjectForPaintImage(
    const StyleImage* image,
    const ComputedStyle& other) const {
  CSSPaintValue* value = ToCSSPaintValue(image->CssValue());

  // NOTE: If the invalidation properties vectors are null, we are invalid as
  // we haven't yet been painted (and can't provide the invalidation
  // properties yet).
  if (!value->NativeInvalidationProperties() ||
      !value->CustomInvalidationProperties())
    return true;

  for (CSSPropertyID property_id : *value->NativeInvalidationProperties()) {
    // TODO(ikilpatrick): remove IsInterpolableProperty check once
    // CSSPropertyEquality::PropertiesEqual correctly handles all properties.
    if (!CSSPropertyMetadata::IsInterpolableProperty(property_id) ||
        !CSSPropertyEquality::PropertiesEqual(property_id, *this, other))
      return true;
  }

  if (InheritedVariables() || NonInheritedVariables() ||
      other.InheritedVariables() || other.NonInheritedVariables()) {
    for (const AtomicString& property :
         *value->CustomInvalidationProperties()) {
      if (!DataEquivalent(GetVariable(property), other.GetVariable(property)))
        return true;
    }
  }

  return false;
}

// This doesn't include conditions needing layout or overflow recomputation
// which implies visual rect update.
bool ComputedStyle::DiffNeedsVisualRectUpdate(
    const ComputedStyle& other) const {
  // Visual rect is empty if visibility is hidden.
  if (Visibility() != other.Visibility())
    return true;

  // Need to update visual rect of the resizer.
  if (Resize() != other.Resize())
    return true;

  return false;
}

void ComputedStyle::UpdatePropertySpecificDifferences(
    const ComputedStyle& other,
    StyleDifference& diff) const {
  if (box_data_->z_index_ != other.box_data_->z_index_ ||
      IsStackingContext() != other.IsStackingContext())
    diff.SetZIndexChanged();

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    // It's possible for the old and new style transform data to be equivalent
    // while hasTransform() differs, as it checks a number of conditions aside
    // from just the matrix, including but not limited to animation state.
    if (HasTransform() != other.HasTransform() ||
        !TransformDataEquivalent(other) ||
        rare_non_inherited_data_->perspective_ !=
            other.rare_non_inherited_data_->perspective_ ||
        rare_non_inherited_data_->perspective_origin_ !=
            other.rare_non_inherited_data_->perspective_origin_)
      diff.SetTransformChanged();
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->opacity !=
        other.rare_non_inherited_data_->opacity)
      diff.SetOpacityChanged();
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->filter_ !=
        other.rare_non_inherited_data_->filter_)
      diff.SetFilterChanged();
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (!rare_non_inherited_data_->ShadowDataEquivalent(
            *other.rare_non_inherited_data_.Get()))
      diff.SetNeedsRecomputeOverflow();
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (rare_non_inherited_data_->backdrop_filter_ !=
        other.rare_non_inherited_data_->backdrop_filter_)
      diff.SetBackdropFilterChanged();
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (!rare_non_inherited_data_->ReflectionDataEquivalent(
            *other.rare_non_inherited_data_.Get()))
      diff.SetFilterChanged();
  }

  if (rare_non_inherited_data_.Get() != other.rare_non_inherited_data_.Get()) {
    if (!rare_non_inherited_data_->outline_.VisuallyEqual(
            other.rare_non_inherited_data_->outline_))
      diff.SetNeedsRecomputeOverflow();
  }

  if (!Border().VisualOverflowEqual(other.Border()))
    diff.SetNeedsRecomputeOverflow();

  if (!diff.NeedsFullPaintInvalidation()) {
    if (inherited_data_->color_ != other.inherited_data_->color_ ||
        inherited_data_->visited_link_color_ !=
            other.inherited_data_->visited_link_color_ ||
        HasSimpleUnderlineInternal() != other.HasSimpleUnderlineInternal() ||
        visual_data_->text_decoration != other.visual_data_->text_decoration) {
      diff.SetTextDecorationOrColorChanged();
    } else {
      if (rare_non_inherited_data_.Get() !=
              other.rare_non_inherited_data_.Get() &&
          (rare_non_inherited_data_->text_decoration_style_ !=
               other.rare_non_inherited_data_->text_decoration_style_ ||
           rare_non_inherited_data_->text_decoration_color_ !=
               other.rare_non_inherited_data_->text_decoration_color_ ||
           rare_non_inherited_data_->visited_link_text_decoration_color_ !=
               other.rare_non_inherited_data_
                   ->visited_link_text_decoration_color_)) {
        diff.SetTextDecorationOrColorChanged();
      } else {
        if (rare_inherited_data_.Get() != other.rare_inherited_data_.Get() &&
            (rare_inherited_data_->TextFillColor() !=
                 other.rare_inherited_data_->TextFillColor() ||
             rare_inherited_data_->TextStrokeColor() !=
                 other.rare_inherited_data_->TextStrokeColor() ||
             rare_inherited_data_->TextEmphasisColor() !=
                 other.rare_inherited_data_->TextEmphasisColor() ||
             rare_inherited_data_->VisitedLinkTextFillColor() !=
                 other.rare_inherited_data_->VisitedLinkTextFillColor() ||
             rare_inherited_data_->VisitedLinkTextStrokeColor() !=
                 other.rare_inherited_data_->VisitedLinkTextStrokeColor() ||
             rare_inherited_data_->VisitedLinkTextEmphasisColor() !=
                 other.rare_inherited_data_->VisitedLinkTextEmphasisColor() ||
             rare_inherited_data_->text_emphasis_fill !=
                 other.rare_inherited_data_->text_emphasis_fill ||
             rare_inherited_data_->text_underline_position_ !=
                 other.rare_inherited_data_->text_underline_position_ ||
             rare_inherited_data_->text_decoration_skip_ !=
                 other.rare_inherited_data_->text_decoration_skip_ ||
             rare_inherited_data_->applied_text_decorations !=
                 other.rare_inherited_data_->applied_text_decorations ||
             rare_inherited_data_->CaretColor() !=
                 other.rare_inherited_data_->CaretColor() ||
             rare_inherited_data_->VisitedLinkCaretColor() !=
                 other.rare_inherited_data_->VisitedLinkCaretColor())) {
          diff.SetTextDecorationOrColorChanged();
        }
      }
    }
  }

  bool has_clip = HasOutOfFlowPosition() && !visual_data_->has_auto_clip;
  bool other_has_clip =
      other.HasOutOfFlowPosition() && !other.visual_data_->has_auto_clip;
  if (has_clip != other_has_clip ||
      (has_clip && visual_data_->clip != other.visual_data_->clip))
    diff.SetCSSClipChanged();
}

void ComputedStyle::AddPaintImage(StyleImage* image) {
  if (!rare_non_inherited_data_.Access()->paint_images_) {
    rare_non_inherited_data_.Access()->paint_images_ =
        WTF::MakeUnique<Vector<Persistent<StyleImage>>>();
  }
  rare_non_inherited_data_.Access()->paint_images_->push_back(image);
}

void ComputedStyle::AddCursor(StyleImage* image,
                              bool hot_spot_specified,
                              const IntPoint& hot_spot) {
  if (!rare_inherited_data_.Access()->cursor_data)
    rare_inherited_data_.Access()->cursor_data = new CursorList;
  rare_inherited_data_.Access()->cursor_data->push_back(
      CursorData(image, hot_spot_specified, hot_spot));
}

void ComputedStyle::SetCursorList(CursorList* other) {
  rare_inherited_data_.Access()->cursor_data = other;
}

void ComputedStyle::SetQuotes(PassRefPtr<QuotesData> q) {
  rare_inherited_data_.Access()->quotes = std::move(q);
}

void ComputedStyle::ClearCursorList() {
  if (rare_inherited_data_->cursor_data)
    rare_inherited_data_.Access()->cursor_data = nullptr;
}

static bool HasPropertyThatCreatesStackingContext(
    const Vector<CSSPropertyID>& properties) {
  for (CSSPropertyID property : properties) {
    switch (property) {
      case CSSPropertyOpacity:
      case CSSPropertyTransform:
      case CSSPropertyAliasWebkitTransform:
      case CSSPropertyTransformStyle:
      case CSSPropertyAliasWebkitTransformStyle:
      case CSSPropertyPerspective:
      case CSSPropertyAliasWebkitPerspective:
      case CSSPropertyTranslate:
      case CSSPropertyRotate:
      case CSSPropertyScale:
      case CSSPropertyOffsetPath:
      case CSSPropertyOffsetPosition:
      case CSSPropertyWebkitMask:
      case CSSPropertyWebkitMaskBoxImage:
      case CSSPropertyClipPath:
      case CSSPropertyAliasWebkitClipPath:
      case CSSPropertyWebkitBoxReflect:
      case CSSPropertyFilter:
      case CSSPropertyAliasWebkitFilter:
      case CSSPropertyBackdropFilter:
      case CSSPropertyZIndex:
      case CSSPropertyPosition:
      case CSSPropertyMixBlendMode:
      case CSSPropertyIsolation:
        return true;
      default:
        break;
    }
  }
  return false;
}

void ComputedStyle::UpdateIsStackingContext(bool is_document_element,
                                            bool is_in_top_layer) {
  if (IsStackingContext())
    return;

  // Force a stacking context for transform-style: preserve-3d. This happens
  // even if preserves-3d is ignored due to a 'grouping property' being present
  // which requires flattening. See ComputedStyle::UsedTransformStyle3D() and
  // ComputedStyle::HasGroupingProperty().
  // This is legacy behavior that is left ambiguous in the official specs.
  // See crbug.com/663650 for more details."
  if (TransformStyle3D() == kTransformStyle3DPreserve3D) {
    SetIsStackingContext(true);
    return;
  }

  if (is_document_element || is_in_top_layer ||
      StyleType() == kPseudoIdBackdrop || HasOpacity() ||
      HasTransformRelatedProperty() || HasMask() || ClipPath() ||
      BoxReflect() || HasFilterInducingProperty() || HasBackdropFilter() ||
      HasBlendMode() || HasIsolation() || HasViewportConstrainedPosition() ||
      HasPropertyThatCreatesStackingContext(WillChangeProperties()) ||
      ContainsPaint()) {
    SetIsStackingContext(true);
  }
}

void ComputedStyle::AddCallbackSelector(const String& selector) {
  if (!rare_non_inherited_data_->callback_selectors_.Contains(selector))
    rare_non_inherited_data_.Access()->callback_selectors_.push_back(selector);
}

void ComputedStyle::SetContent(ContentData* content_data) {
  SET_VAR(rare_non_inherited_data_, content_, content_data);
}

bool ComputedStyle::HasWillChangeCompositingHint() const {
  for (size_t i = 0;
       i < rare_non_inherited_data_->will_change_->properties_.size(); ++i) {
    switch (rare_non_inherited_data_->will_change_->properties_[i]) {
      case CSSPropertyOpacity:
      case CSSPropertyTransform:
      case CSSPropertyAliasWebkitTransform:
      case CSSPropertyTop:
      case CSSPropertyLeft:
      case CSSPropertyBottom:
      case CSSPropertyRight:
        return true;
      default:
        break;
    }
  }
  return false;
}

bool ComputedStyle::HasWillChangeTransformHint() const {
  for (const auto& property :
       rare_non_inherited_data_->will_change_->properties_) {
    switch (property) {
      case CSSPropertyTransform:
      case CSSPropertyAliasWebkitTransform:
      case CSSPropertyPerspective:
      case CSSPropertyTranslate:
      case CSSPropertyScale:
      case CSSPropertyRotate:
      case CSSPropertyOffsetPath:
      case CSSPropertyOffsetPosition:
        return true;
      default:
        break;
    }
  }
  return false;
}

bool ComputedStyle::RequireTransformOrigin(
    ApplyTransformOrigin apply_origin,
    ApplyMotionPath apply_motion_path) const {
  // transform-origin brackets the transform with translate operations.
  // Optimize for the case where the only transform is a translation, since the
  // transform-origin is irrelevant in that case.
  if (apply_origin != kIncludeTransformOrigin)
    return false;

  if (apply_motion_path == kIncludeMotionPath)
    return true;

  for (const auto& operation : Transform().Operations()) {
    TransformOperation::OperationType type = operation->GetType();
    if (type != TransformOperation::kTranslateX &&
        type != TransformOperation::kTranslateY &&
        type != TransformOperation::kTranslate &&
        type != TransformOperation::kTranslateZ &&
        type != TransformOperation::kTranslate3D)
      return true;
  }

  return Scale() || Rotate();
}

void ComputedStyle::ApplyTransform(
    TransformationMatrix& result,
    const LayoutSize& border_box_size,
    ApplyTransformOrigin apply_origin,
    ApplyMotionPath apply_motion_path,
    ApplyIndependentTransformProperties apply_independent_transform_properties)
    const {
  ApplyTransform(result, FloatRect(FloatPoint(), FloatSize(border_box_size)),
                 apply_origin, apply_motion_path,
                 apply_independent_transform_properties);
}

void ComputedStyle::ApplyTransform(
    TransformationMatrix& result,
    const FloatRect& bounding_box,
    ApplyTransformOrigin apply_origin,
    ApplyMotionPath apply_motion_path,
    ApplyIndependentTransformProperties apply_independent_transform_properties)
    const {
  if (!HasOffset())
    apply_motion_path = kExcludeMotionPath;
  bool apply_transform_origin =
      RequireTransformOrigin(apply_origin, apply_motion_path);

  float origin_x = 0;
  float origin_y = 0;
  float origin_z = 0;

  const FloatSize& box_size = bounding_box.Size();
  if (apply_transform_origin ||
      // We need to calculate originX and originY for applying motion path.
      apply_motion_path == kIncludeMotionPath) {
    origin_x = FloatValueForLength(TransformOriginX(), box_size.Width()) +
               bounding_box.X();
    origin_y = FloatValueForLength(TransformOriginY(), box_size.Height()) +
               bounding_box.Y();
    if (apply_transform_origin) {
      origin_z = TransformOriginZ();
      result.Translate3d(origin_x, origin_y, origin_z);
    }
  }

  if (apply_independent_transform_properties ==
      kIncludeIndependentTransformProperties) {
    if (Translate())
      Translate()->Apply(result, box_size);

    if (Rotate())
      Rotate()->Apply(result, box_size);

    if (Scale())
      Scale()->Apply(result, box_size);
  }

  if (apply_motion_path == kIncludeMotionPath)
    ApplyMotionPathTransform(origin_x, origin_y, bounding_box, result);

  for (const auto& operation : Transform().Operations())
    operation->Apply(result, box_size);

  if (apply_transform_origin) {
    result.Translate3d(-origin_x, -origin_y, -origin_z);
  }
}

void ComputedStyle::ApplyMotionPathTransform(
    float origin_x,
    float origin_y,
    const FloatRect& bounding_box,
    TransformationMatrix& transform) const {
  const StyleMotionData& motion_data =
      rare_non_inherited_data_->transform_->motion_;
  // TODO(ericwilligers): crbug.com/638055 Apply offset-position.
  if (!motion_data.path_) {
    return;
  }
  const LengthPoint& position = OffsetPosition();
  const LengthPoint& anchor = OffsetAnchor();
  const StylePath& motion_path = *motion_data.path_;
  float path_length = motion_path.length();
  float distance = FloatValueForLength(motion_data.distance_, path_length);
  float computed_distance;
  if (motion_path.IsClosed() && path_length > 0) {
    computed_distance = fmod(distance, path_length);
    if (computed_distance < 0)
      computed_distance += path_length;
  } else {
    computed_distance = clampTo<float>(distance, 0, path_length);
  }

  FloatPoint point;
  float angle;
  motion_path.GetPath().PointAndNormalAtLength(computed_distance, point, angle);

  if (motion_data.rotation_.type == kOffsetRotationFixed)
    angle = 0;

  float origin_shift_x = 0;
  float origin_shift_y = 0;
  // If offset-Position and offset-anchor properties are not yet enabled,
  // they will have the default value, auto.
  if (position.X() != Length(kAuto) || anchor.X() != Length(kAuto)) {
    // Shift the origin from transform-origin to offset-anchor.
    origin_shift_x =
        FloatValueForLength(anchor.X(), bounding_box.Width()) -
        FloatValueForLength(TransformOriginX(), bounding_box.Width());
    origin_shift_y =
        FloatValueForLength(anchor.Y(), bounding_box.Height()) -
        FloatValueForLength(TransformOriginY(), bounding_box.Height());
  }

  transform.Translate(point.X() - origin_x + origin_shift_x,
                      point.Y() - origin_y + origin_shift_y);
  transform.Rotate(angle + motion_data.rotation_.angle);

  if (position.X() != Length(kAuto) || anchor.X() != Length(kAuto))
    // Shift the origin back to transform-origin.
    transform.Translate(-origin_shift_x, -origin_shift_y);
}

void ComputedStyle::SetTextShadow(PassRefPtr<ShadowList> s) {
  rare_inherited_data_.Access()->text_shadow = std::move(s);
}

void ComputedStyle::SetBoxShadow(PassRefPtr<ShadowList> s) {
  rare_non_inherited_data_.Access()->box_shadow_ = std::move(s);
}

static FloatRoundedRect::Radii CalcRadiiFor(const BorderData& border,
                                            const LengthSize& top_left,
                                            const LengthSize& top_right,
                                            const LengthSize& bottom_left,
                                            const LengthSize& bottom_right,
                                            LayoutSize size) {
  return FloatRoundedRect::Radii(
      FloatSize(
          FloatValueForLength(top_left.Width(), size.Width().ToFloat()),
          FloatValueForLength(top_left.Height(), size.Height().ToFloat())),
      FloatSize(
          FloatValueForLength(top_right.Width(), size.Width().ToFloat()),
          FloatValueForLength(top_right.Height(), size.Height().ToFloat())),
      FloatSize(
          FloatValueForLength(bottom_left.Width(), size.Width().ToFloat()),
          FloatValueForLength(bottom_left.Height(), size.Height().ToFloat())),
      FloatSize(
          FloatValueForLength(bottom_right.Width(), size.Width().ToFloat()),
          FloatValueForLength(bottom_right.Height(), size.Height().ToFloat())));
}

StyleImage* ComputedStyle::ListStyleImage() const {
  return rare_inherited_data_->list_style_image.Get();
}
void ComputedStyle::SetListStyleImage(StyleImage* v) {
  if (rare_inherited_data_->list_style_image != v)
    rare_inherited_data_.Access()->list_style_image = v;
}

Color ComputedStyle::GetColor() const {
  return inherited_data_->color_;
}
Color ComputedStyle::VisitedLinkColor() const {
  return inherited_data_->visited_link_color_;
}
void ComputedStyle::SetColor(const Color& v) {
  SET_VAR(inherited_data_, color_, v);
}
void ComputedStyle::SetVisitedLinkColor(const Color& v) {
  SET_VAR(inherited_data_, visited_link_color_, v);
}

short ComputedStyle::HorizontalBorderSpacing() const {
  return inherited_data_->horizontal_border_spacing_;
}
short ComputedStyle::VerticalBorderSpacing() const {
  return inherited_data_->vertical_border_spacing_;
}
void ComputedStyle::SetHorizontalBorderSpacing(short v) {
  SET_VAR(inherited_data_, horizontal_border_spacing_, v);
}
void ComputedStyle::SetVerticalBorderSpacing(short v) {
  SET_VAR(inherited_data_, vertical_border_spacing_, v);
}

FloatRoundedRect ComputedStyle::GetRoundedBorderFor(
    const LayoutRect& border_rect,
    bool include_logical_left_edge,
    bool include_logical_right_edge) const {
  FloatRoundedRect rounded_rect(PixelSnappedIntRect(border_rect));
  if (HasBorderRadius()) {
    FloatRoundedRect::Radii radii =
        CalcRadiiFor(Border(), BorderTopLeftRadius(), BorderTopRightRadius(),
                     BorderBottomLeftRadius(), BorderBottomRightRadius(),
                     border_rect.Size());
    rounded_rect.IncludeLogicalEdges(radii, IsHorizontalWritingMode(),
                                     include_logical_left_edge,
                                     include_logical_right_edge);
    rounded_rect.ConstrainRadii();
  }
  return rounded_rect;
}

FloatRoundedRect ComputedStyle::GetRoundedInnerBorderFor(
    const LayoutRect& border_rect,
    bool include_logical_left_edge,
    bool include_logical_right_edge) const {
  bool horizontal = IsHorizontalWritingMode();

  int left_width = (!horizontal || include_logical_left_edge)
                       ? roundf(BorderLeftWidth())
                       : 0;
  int right_width = (!horizontal || include_logical_right_edge)
                        ? roundf(BorderRightWidth())
                        : 0;
  int top_width =
      (horizontal || include_logical_left_edge) ? roundf(BorderTopWidth()) : 0;
  int bottom_width = (horizontal || include_logical_right_edge)
                         ? roundf(BorderBottomWidth())
                         : 0;

  return GetRoundedInnerBorderFor(
      border_rect,
      LayoutRectOutsets(-top_width, -right_width, -bottom_width, -left_width),
      include_logical_left_edge, include_logical_right_edge);
}

FloatRoundedRect ComputedStyle::GetRoundedInnerBorderFor(
    const LayoutRect& border_rect,
    const LayoutRectOutsets& insets,
    bool include_logical_left_edge,
    bool include_logical_right_edge) const {
  LayoutRect inner_rect(border_rect);
  inner_rect.Expand(insets);
  LayoutSize inner_rect_size = inner_rect.Size();
  inner_rect_size.ClampNegativeToZero();
  inner_rect.SetSize(inner_rect_size);

  FloatRoundedRect rounded_rect(PixelSnappedIntRect(inner_rect));

  if (HasBorderRadius()) {
    FloatRoundedRect::Radii radii = GetRoundedBorderFor(border_rect).GetRadii();
    // Insets use negative values.
    radii.Shrink(-insets.Top().ToFloat(), -insets.Bottom().ToFloat(),
                 -insets.Left().ToFloat(), -insets.Right().ToFloat());
    rounded_rect.IncludeLogicalEdges(radii, IsHorizontalWritingMode(),
                                     include_logical_left_edge,
                                     include_logical_right_edge);
  }
  return rounded_rect;
}

static bool AllLayersAreFixed(const FillLayer& layer) {
  for (const FillLayer* curr_layer = &layer; curr_layer;
       curr_layer = curr_layer->Next()) {
    if (!curr_layer->GetImage() ||
        curr_layer->Attachment() != kFixedBackgroundAttachment)
      return false;
  }

  return true;
}

bool ComputedStyle::HasEntirelyFixedBackground() const {
  return AllLayersAreFixed(BackgroundLayers());
}

const CounterDirectiveMap* ComputedStyle::GetCounterDirectives() const {
  return rare_non_inherited_data_->counter_directives_.get();
}

CounterDirectiveMap& ComputedStyle::AccessCounterDirectives() {
  std::unique_ptr<CounterDirectiveMap>& map =
      rare_non_inherited_data_.Access()->counter_directives_;
  if (!map)
    map = WTF::WrapUnique(new CounterDirectiveMap);
  return *map;
}

const CounterDirectives ComputedStyle::GetCounterDirectives(
    const AtomicString& identifier) const {
  if (const CounterDirectiveMap* directives = GetCounterDirectives())
    return directives->at(identifier);
  return CounterDirectives();
}

void ComputedStyle::ClearIncrementDirectives() {
  if (!GetCounterDirectives())
    return;

  // This makes us copy even if we may not be removing any items.
  CounterDirectiveMap& map = AccessCounterDirectives();
  typedef CounterDirectiveMap::iterator Iterator;

  Iterator end = map.end();
  for (Iterator it = map.begin(); it != end; ++it)
    it->value.ClearIncrement();
}

void ComputedStyle::ClearResetDirectives() {
  if (!GetCounterDirectives())
    return;

  // This makes us copy even if we may not be removing any items.
  CounterDirectiveMap& map = AccessCounterDirectives();
  typedef CounterDirectiveMap::iterator Iterator;

  Iterator end = map.end();
  for (Iterator it = map.begin(); it != end; ++it)
    it->value.ClearReset();
}

Hyphenation* ComputedStyle::GetHyphenation() const {
  return GetHyphens() == kHyphensAuto
             ? GetFontDescription().LocaleOrDefault().GetHyphenation()
             : nullptr;
}

const AtomicString& ComputedStyle::HyphenString() const {
  const AtomicString& hyphenation_string =
      rare_inherited_data_.Get()->hyphenation_string;
  if (!hyphenation_string.IsNull())
    return hyphenation_string;

  // FIXME: This should depend on locale.
  DEFINE_STATIC_LOCAL(AtomicString, hyphen_minus_string,
                      (&kHyphenMinusCharacter, 1));
  DEFINE_STATIC_LOCAL(AtomicString, hyphen_string, (&kHyphenCharacter, 1));
  const SimpleFontData* primary_font = GetFont().PrimaryFont();
  DCHECK(primary_font);
  return primary_font && primary_font->GlyphForCharacter(kHyphenCharacter)
             ? hyphen_string
             : hyphen_minus_string;
}

const AtomicString& ComputedStyle::TextEmphasisMarkString() const {
  switch (GetTextEmphasisMark()) {
    case kTextEmphasisMarkNone:
      return g_null_atom;
    case kTextEmphasisMarkCustom:
      return TextEmphasisCustomMark();
    case kTextEmphasisMarkDot: {
      DEFINE_STATIC_LOCAL(AtomicString, filled_dot_string,
                          (&kBulletCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, open_dot_string,
                          (&kWhiteBulletCharacter, 1));
      return GetTextEmphasisFill() == kTextEmphasisFillFilled
                 ? filled_dot_string
                 : open_dot_string;
    }
    case kTextEmphasisMarkCircle: {
      DEFINE_STATIC_LOCAL(AtomicString, filled_circle_string,
                          (&kBlackCircleCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, open_circle_string,
                          (&kWhiteCircleCharacter, 1));
      return GetTextEmphasisFill() == kTextEmphasisFillFilled
                 ? filled_circle_string
                 : open_circle_string;
    }
    case kTextEmphasisMarkDoubleCircle: {
      DEFINE_STATIC_LOCAL(AtomicString, filled_double_circle_string,
                          (&kFisheyeCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, open_double_circle_string,
                          (&kBullseyeCharacter, 1));
      return GetTextEmphasisFill() == kTextEmphasisFillFilled
                 ? filled_double_circle_string
                 : open_double_circle_string;
    }
    case kTextEmphasisMarkTriangle: {
      DEFINE_STATIC_LOCAL(AtomicString, filled_triangle_string,
                          (&kBlackUpPointingTriangleCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, open_triangle_string,
                          (&kWhiteUpPointingTriangleCharacter, 1));
      return GetTextEmphasisFill() == kTextEmphasisFillFilled
                 ? filled_triangle_string
                 : open_triangle_string;
    }
    case kTextEmphasisMarkSesame: {
      DEFINE_STATIC_LOCAL(AtomicString, filled_sesame_string,
                          (&kSesameDotCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, open_sesame_string,
                          (&kWhiteSesameDotCharacter, 1));
      return GetTextEmphasisFill() == kTextEmphasisFillFilled
                 ? filled_sesame_string
                 : open_sesame_string;
    }
    case kTextEmphasisMarkAuto:
      NOTREACHED();
      return g_null_atom;
  }

  NOTREACHED();
  return g_null_atom;
}

CSSAnimationData& ComputedStyle::AccessAnimations() {
  if (!rare_non_inherited_data_.Access()->animations_)
    rare_non_inherited_data_.Access()->animations_ = CSSAnimationData::Create();
  return *rare_non_inherited_data_->animations_;
}

CSSTransitionData& ComputedStyle::AccessTransitions() {
  if (!rare_non_inherited_data_.Access()->transitions_)
    rare_non_inherited_data_.Access()->transitions_ =
        CSSTransitionData::Create();
  return *rare_non_inherited_data_->transitions_;
}

const Font& ComputedStyle::GetFont() const {
  return inherited_data_->font_;
}
const FontDescription& ComputedStyle::GetFontDescription() const {
  return inherited_data_->font_.GetFontDescription();
}
float ComputedStyle::SpecifiedFontSize() const {
  return GetFontDescription().SpecifiedSize();
}
float ComputedStyle::ComputedFontSize() const {
  return GetFontDescription().ComputedSize();
}
LayoutUnit ComputedStyle::ComputedFontSizeAsFixed() const {
  return LayoutUnit::FromFloatRound(GetFontDescription().ComputedSize());
}
int ComputedStyle::FontSize() const {
  return GetFontDescription().ComputedPixelSize();
}
float ComputedStyle::FontSizeAdjust() const {
  return GetFontDescription().SizeAdjust();
}
bool ComputedStyle::HasFontSizeAdjust() const {
  return GetFontDescription().HasSizeAdjust();
}
FontWeight ComputedStyle::GetFontWeight() const {
  return GetFontDescription().Weight();
}
FontStretch ComputedStyle::GetFontStretch() const {
  return GetFontDescription().Stretch();
}

TextDecoration ComputedStyle::TextDecorationsInEffect() const {
  if (HasSimpleUnderlineInternal())
    return kTextDecorationUnderline;
  if (!rare_inherited_data_->applied_text_decorations)
    return kTextDecorationNone;

  int decorations = 0;

  const Vector<AppliedTextDecoration>& applied = AppliedTextDecorations();

  for (size_t i = 0; i < applied.size(); ++i)
    decorations |= applied[i].Lines();

  return static_cast<TextDecoration>(decorations);
}

const Vector<AppliedTextDecoration>& ComputedStyle::AppliedTextDecorations()
    const {
  if (HasSimpleUnderlineInternal()) {
    DEFINE_STATIC_LOCAL(
        Vector<AppliedTextDecoration>, underline,
        (1, AppliedTextDecoration(
                kTextDecorationUnderline, kTextDecorationStyleSolid,
                VisitedDependentColor(CSSPropertyTextDecorationColor))));
    // Since we only have one of these in memory, just update the color before
    // returning.
    underline.at(0).SetColor(
        VisitedDependentColor(CSSPropertyTextDecorationColor));
    return underline;
  }
  if (!rare_inherited_data_->applied_text_decorations) {
    DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ());
    return empty;
  }

  return rare_inherited_data_->applied_text_decorations->GetVector();
}

StyleInheritedVariables* ComputedStyle::InheritedVariables() const {
  return rare_inherited_data_->variables.Get();
}

StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const {
  return rare_non_inherited_data_->variables_.get();
}

StyleInheritedVariables& ComputedStyle::MutableInheritedVariables() {
  RefPtr<StyleInheritedVariables>& variables =
      rare_inherited_data_.Access()->variables;
  if (!variables)
    variables = StyleInheritedVariables::Create();
  else if (!variables->HasOneRef())
    variables = variables->Copy();
  return *variables;
}

StyleNonInheritedVariables& ComputedStyle::MutableNonInheritedVariables() {
  std::unique_ptr<StyleNonInheritedVariables>& variables =
      rare_non_inherited_data_.Access()->variables_;
  if (!variables)
    variables = StyleNonInheritedVariables::Create();
  return *variables;
}

void ComputedStyle::SetUnresolvedInheritedVariable(
    const AtomicString& name,
    PassRefPtr<CSSVariableData> value) {
  DCHECK(value && value->NeedsVariableResolution());
  MutableInheritedVariables().SetVariable(name, std::move(value));
}

void ComputedStyle::SetUnresolvedNonInheritedVariable(
    const AtomicString& name,
    PassRefPtr<CSSVariableData> value) {
  DCHECK(value && value->NeedsVariableResolution());
  MutableNonInheritedVariables().SetVariable(name, std::move(value));
}

void ComputedStyle::SetResolvedUnregisteredVariable(
    const AtomicString& name,
    PassRefPtr<CSSVariableData> value) {
  DCHECK(value && !value->NeedsVariableResolution());
  MutableInheritedVariables().SetVariable(name, std::move(value));
}

void ComputedStyle::SetResolvedInheritedVariable(
    const AtomicString& name,
    PassRefPtr<CSSVariableData> value,
    const CSSValue* parsed_value) {
  DCHECK(!!value == !!parsed_value);
  DCHECK(!(value && value->NeedsVariableResolution()));

  StyleInheritedVariables& variables = MutableInheritedVariables();
  variables.SetVariable(name, std::move(value));
  variables.SetRegisteredVariable(name, parsed_value);
}

void ComputedStyle::SetResolvedNonInheritedVariable(
    const AtomicString& name,
    PassRefPtr<CSSVariableData> value,
    const CSSValue* parsed_value) {
  DCHECK(!!value == !!parsed_value);
  DCHECK(!(value && value->NeedsVariableResolution()));

  StyleNonInheritedVariables& variables = MutableNonInheritedVariables();
  variables.SetVariable(name, std::move(value));
  variables.SetRegisteredVariable(name, parsed_value);
}

void ComputedStyle::RemoveVariable(const AtomicString& name,
                                   bool is_inherited_property) {
  if (is_inherited_property) {
    MutableInheritedVariables().RemoveVariable(name);
  } else {
    MutableNonInheritedVariables().RemoveVariable(name);
  }
}

CSSVariableData* ComputedStyle::GetVariable(const AtomicString& name) const {
  CSSVariableData* variable = GetVariable(name, true);
  if (variable) {
    return variable;
  }
  return GetVariable(name, false);
}

CSSVariableData* ComputedStyle::GetVariable(const AtomicString& name,
                                            bool is_inherited_property) const {
  if (is_inherited_property) {
    return InheritedVariables() ? InheritedVariables()->GetVariable(name)
                                : nullptr;
  }
  return NonInheritedVariables() ? NonInheritedVariables()->GetVariable(name)
                                 : nullptr;
}

const CSSValue* ComputedStyle::GetRegisteredVariable(
    const AtomicString& name,
    bool is_inherited_property) const {
  if (is_inherited_property) {
    return InheritedVariables() ? InheritedVariables()->RegisteredVariable(name)
                                : nullptr;
  }
  return NonInheritedVariables()
             ? NonInheritedVariables()->RegisteredVariable(name)
             : nullptr;
}

const CSSValue* ComputedStyle::GetRegisteredVariable(
    const AtomicString& name) const {
  // Registered custom properties are by default non-inheriting so check there
  // first.
  const CSSValue* result = GetRegisteredVariable(name, false);
  if (result) {
    return result;
  }
  return GetRegisteredVariable(name, true);
}

float ComputedStyle::WordSpacing() const {
  return GetFontDescription().WordSpacing();
}
float ComputedStyle::LetterSpacing() const {
  return GetFontDescription().LetterSpacing();
}

bool ComputedStyle::SetFontDescription(const FontDescription& v) {
  if (inherited_data_->font_.GetFontDescription() != v) {
    inherited_data_.Access()->font_ = Font(v);
    return true;
  }
  return false;
}

void ComputedStyle::SetFont(const Font& font) {
  inherited_data_.Access()->font_ = font;
}

bool ComputedStyle::HasIdenticalAscentDescentAndLineGap(
    const ComputedStyle& other) const {
  const SimpleFontData* font_data = GetFont().PrimaryFont();
  const SimpleFontData* other_font_data = other.GetFont().PrimaryFont();
  return font_data && other_font_data &&
         font_data->GetFontMetrics().HasIdenticalAscentDescentAndLineGap(
             other_font_data->GetFontMetrics());
}

const Length& ComputedStyle::SpecifiedLineHeight() const {
  return inherited_data_->line_height_;
}
Length ComputedStyle::LineHeight() const {
  const Length& lh = inherited_data_->line_height_;
  // Unlike getFontDescription().computedSize() and hence fontSize(), this is
  // recalculated on demand as we only store the specified line height.
  // FIXME: Should consider scaling the fixed part of any calc expressions
  // too, though this involves messily poking into CalcExpressionLength.
  if (lh.IsFixed()) {
    float multiplier = TextAutosizingMultiplier();
    return Length(
        TextAutosizer::ComputeAutosizedFontSize(lh.Value(), multiplier),
        kFixed);
  }

  return lh;
}

void ComputedStyle::SetLineHeight(const Length& specified_line_height) {
  SET_VAR(inherited_data_, line_height_, specified_line_height);
}

int ComputedStyle::ComputedLineHeight() const {
  const Length& lh = LineHeight();

  // Negative value means the line height is not set. Use the font's built-in
  // spacing, if avalible.
  if (lh.IsNegative() && GetFont().PrimaryFont())
    return GetFont().PrimaryFont()->GetFontMetrics().LineSpacing();

  if (lh.IsPercentOrCalc())
    return MinimumValueForLength(lh, LayoutUnit(ComputedFontSize())).ToInt();

  return std::min(lh.Value(), LayoutUnit::Max().ToFloat());
}

LayoutUnit ComputedStyle::ComputedLineHeightAsFixed() const {
  const Length& lh = LineHeight();

  // Negative value means the line height is not set. Use the font's built-in
  // spacing, if avalible.
  if (lh.IsNegative() && GetFont().PrimaryFont())
    return GetFont().PrimaryFont()->GetFontMetrics().FixedLineSpacing();

  if (lh.IsPercentOrCalc())
    return MinimumValueForLength(lh, ComputedFontSizeAsFixed());

  return LayoutUnit::FromFloatRound(lh.Value());
}

void ComputedStyle::SetWordSpacing(float word_spacing) {
  FontSelector* current_font_selector = GetFont().GetFontSelector();
  FontDescription desc(GetFontDescription());
  desc.SetWordSpacing(word_spacing);
  SetFontDescription(desc);
  GetFont().Update(current_font_selector);
}

void ComputedStyle::SetLetterSpacing(float letter_spacing) {
  FontSelector* current_font_selector = GetFont().GetFontSelector();
  FontDescription desc(GetFontDescription());
  desc.SetLetterSpacing(letter_spacing);
  SetFontDescription(desc);
  GetFont().Update(current_font_selector);
}

void ComputedStyle::SetTextAutosizingMultiplier(float multiplier) {
  SET_VAR(inherited_data_, text_autosizing_multiplier_, multiplier);

  float size = SpecifiedFontSize();

  DCHECK(std::isfinite(size));
  if (!std::isfinite(size) || size < 0)
    size = 0;
  else
    size = std::min(kMaximumAllowedFontSize, size);

  FontSelector* current_font_selector = GetFont().GetFontSelector();
  FontDescription desc(GetFontDescription());
  desc.SetSpecifiedSize(size);
  desc.SetComputedSize(size);

  float autosized_font_size =
      TextAutosizer::ComputeAutosizedFontSize(size, multiplier);
  desc.SetComputedSize(std::min(kMaximumAllowedFontSize, autosized_font_size));

  SetFontDescription(desc);
  GetFont().Update(current_font_selector);
}

void ComputedStyle::AddAppliedTextDecoration(
    const AppliedTextDecoration& decoration) {
  RefPtr<AppliedTextDecorationList>& list =
      rare_inherited_data_.Access()->applied_text_decorations;

  if (!list)
    list = AppliedTextDecorationList::Create();
  else if (!list->HasOneRef())
    list = list->Copy();

  list->push_back(decoration);
}

void ComputedStyle::OverrideTextDecorationColors(Color override_color) {
  RefPtr<AppliedTextDecorationList>& list =
      rare_inherited_data_.Access()->applied_text_decorations;
  DCHECK(list);
  if (!list->HasOneRef())
    list = list->Copy();

  for (size_t i = 0; i < list->size(); ++i)
    list->at(i).SetColor(override_color);
}

void ComputedStyle::ApplyTextDecorations(
    const Color& parent_text_decoration_color,
    bool override_existing_colors) {
  if (GetTextDecoration() == kTextDecorationNone &&
      !HasSimpleUnderlineInternal() &&
      !rare_inherited_data_->applied_text_decorations)
    return;

  // If there are any color changes or decorations set by this element, stop
  // using m_hasSimpleUnderline.
  Color current_text_decoration_color =
      VisitedDependentColor(CSSPropertyTextDecorationColor);
  if (HasSimpleUnderlineInternal() &&
      (GetTextDecoration() != kTextDecorationNone ||
       current_text_decoration_color != parent_text_decoration_color)) {
    SetHasSimpleUnderlineInternal(false);
    AddAppliedTextDecoration(AppliedTextDecoration(
        kTextDecorationUnderline, kTextDecorationStyleSolid,
        parent_text_decoration_color));
  }
  if (override_existing_colors &&
      rare_inherited_data_->applied_text_decorations)
    OverrideTextDecorationColors(current_text_decoration_color);
  if (GetTextDecoration() == kTextDecorationNone)
    return;
  DCHECK(!HasSimpleUnderlineInternal());
  // To save memory, we don't use AppliedTextDecoration objects in the common
  // case of a single simple underline of currentColor.
  TextDecoration decoration_lines = GetTextDecoration();
  TextDecorationStyle decoration_style = GetTextDecorationStyle();
  bool is_simple_underline = decoration_lines == kTextDecorationUnderline &&
                             decoration_style == kTextDecorationStyleSolid &&
                             TextDecorationColor().IsCurrentColor();
  if (is_simple_underline && !rare_inherited_data_->applied_text_decorations) {
    SetHasSimpleUnderlineInternal(true);
    return;
  }

  AddAppliedTextDecoration(AppliedTextDecoration(
      decoration_lines, decoration_style, current_text_decoration_color));
}

void ComputedStyle::ClearAppliedTextDecorations() {
  SetHasSimpleUnderlineInternal(false);

  if (rare_inherited_data_->applied_text_decorations)
    rare_inherited_data_.Access()->applied_text_decorations = nullptr;
}

void ComputedStyle::RestoreParentTextDecorations(
    const ComputedStyle& parent_style) {
  SetHasSimpleUnderlineInternal(parent_style.HasSimpleUnderlineInternal());
  if (rare_inherited_data_->applied_text_decorations !=
      parent_style.rare_inherited_data_->applied_text_decorations)
    rare_inherited_data_.Access()->applied_text_decorations =
        parent_style.rare_inherited_data_->applied_text_decorations;
}

void ComputedStyle::ClearMultiCol() {
  rare_non_inherited_data_.Access()->multi_col_ = nullptr;
  rare_non_inherited_data_.Access()->multi_col_.Init();
}

StyleColor ComputedStyle::DecorationColorIncludingFallback(
    bool visited_link) const {
  StyleColor style_color =
      visited_link ? VisitedLinkTextDecorationColor() : TextDecorationColor();

  if (!style_color.IsCurrentColor())
    return style_color;

  if (TextStrokeWidth()) {
    // Prefer stroke color if possible, but not if it's fully transparent.
    StyleColor text_stroke_style_color =
        visited_link ? VisitedLinkTextStrokeColor() : TextStrokeColor();
    if (!text_stroke_style_color.IsCurrentColor() &&
        text_stroke_style_color.GetColor().Alpha())
      return text_stroke_style_color;
  }

  return visited_link ? VisitedLinkTextFillColor() : TextFillColor();
}

Color ComputedStyle::ColorIncludingFallback(int color_property,
                                            bool visited_link) const {
  StyleColor result(StyleColor::CurrentColor());
  EBorderStyle border_style = kBorderStyleNone;
  switch (color_property) {
    case CSSPropertyBackgroundColor:
      result = visited_link ? VisitedLinkBackgroundColor() : BackgroundColor();
      break;
    case CSSPropertyBorderLeftColor:
      result = visited_link ? VisitedLinkBorderLeftColor() : BorderLeftColor();
      border_style = BorderLeftStyle();
      break;
    case CSSPropertyBorderRightColor:
      result =
          visited_link ? VisitedLinkBorderRightColor() : BorderRightColor();
      border_style = BorderRightStyle();
      break;
    case CSSPropertyBorderTopColor:
      result = visited_link ? VisitedLinkBorderTopColor() : BorderTopColor();
      border_style = BorderTopStyle();
      break;
    case CSSPropertyBorderBottomColor:
      result =
          visited_link ? VisitedLinkBorderBottomColor() : BorderBottomColor();
      border_style = BorderBottomStyle();
      break;
    case CSSPropertyCaretColor: {
      StyleAutoColor auto_color =
          visited_link ? VisitedLinkCaretColor() : CaretColor();
      // TODO(rego): We may want to adjust the caret color if it's the same than
      // the background to ensure good visibility and contrast.
      result = auto_color.IsAutoColor() ? StyleColor::CurrentColor()
                                        : auto_color.ToStyleColor();
      break;
    }
    case CSSPropertyColor:
      result = visited_link ? VisitedLinkColor() : GetColor();
      break;
    case CSSPropertyOutlineColor:
      result = visited_link ? VisitedLinkOutlineColor() : OutlineColor();
      break;
    case CSSPropertyColumnRuleColor:
      result = visited_link ? VisitedLinkColumnRuleColor() : ColumnRuleColor();
      break;
    case CSSPropertyWebkitTextEmphasisColor:
      result =
          visited_link ? VisitedLinkTextEmphasisColor() : TextEmphasisColor();
      break;
    case CSSPropertyWebkitTextFillColor:
      result = visited_link ? VisitedLinkTextFillColor() : TextFillColor();
      break;
    case CSSPropertyWebkitTextStrokeColor:
      result = visited_link ? VisitedLinkTextStrokeColor() : TextStrokeColor();
      break;
    case CSSPropertyFloodColor:
      result = FloodColor();
      break;
    case CSSPropertyLightingColor:
      result = LightingColor();
      break;
    case CSSPropertyStopColor:
      result = StopColor();
      break;
    case CSSPropertyWebkitTapHighlightColor:
      result = TapHighlightColor();
      break;
    case CSSPropertyTextDecorationColor:
      result = DecorationColorIncludingFallback(visited_link);
      break;
    default:
      NOTREACHED();
      break;
  }

  if (!result.IsCurrentColor())
    return result.GetColor();

  // FIXME: Treating styled borders with initial color differently causes
  // problems, see crbug.com/316559, crbug.com/276231
  if (!visited_link &&
      (border_style == kBorderStyleInset ||
       border_style == kBorderStyleOutset ||
       border_style == kBorderStyleRidge || border_style == kBorderStyleGroove))
    return Color(238, 238, 238);
  return visited_link ? VisitedLinkColor() : GetColor();
}

Color ComputedStyle::VisitedDependentColor(int color_property) const {
  Color unvisited_color = ColorIncludingFallback(color_property, false);
  if (InsideLink() != EInsideLink::kInsideVisitedLink)
    return unvisited_color;

  Color visited_color = ColorIncludingFallback(color_property, true);

  // FIXME: Technically someone could explicitly specify the color transparent,
  // but for now we'll just assume that if the background color is transparent
  // that it wasn't set. Note that it's weird that we're returning unvisited
  // info for a visited link, but given our restriction that the alpha values
  // have to match, it makes more sense to return the unvisited background color
  // if specified than it does to return black. This behavior matches what
  // Firefox 4 does as well.
  if (color_property == CSSPropertyBackgroundColor &&
      visited_color == Color::kTransparent)
    return unvisited_color;

  // Take the alpha from the unvisited color, but get the RGB values from the
  // visited color.
  return Color(visited_color.Red(), visited_color.Green(), visited_color.Blue(),
               unvisited_color.Alpha());
}

const BorderValue& ComputedStyle::BorderBefore() const {
  switch (GetWritingMode()) {
    case WritingMode::kHorizontalTb:
      return BorderTop();
    case WritingMode::kVerticalLr:
      return BorderLeft();
    case WritingMode::kVerticalRl:
      return BorderRight();
  }
  NOTREACHED();
  return BorderTop();
}

const BorderValue& ComputedStyle::BorderAfter() const {
  switch (GetWritingMode()) {
    case WritingMode::kHorizontalTb:
      return BorderBottom();
    case WritingMode::kVerticalLr:
      return BorderRight();
    case WritingMode::kVerticalRl:
      return BorderLeft();
  }
  NOTREACHED();
  return BorderBottom();
}

const BorderValue& ComputedStyle::BorderStart() const {
  if (IsHorizontalWritingMode())
    return IsLeftToRightDirection() ? BorderLeft() : BorderRight();
  return IsLeftToRightDirection() ? BorderTop() : BorderBottom();
}

const BorderValue& ComputedStyle::BorderEnd() const {
  if (IsHorizontalWritingMode())
    return IsLeftToRightDirection() ? BorderRight() : BorderLeft();
  return IsLeftToRightDirection() ? BorderBottom() : BorderTop();
}

float ComputedStyle::BorderBeforeWidth() const {
  switch (GetWritingMode()) {
    case WritingMode::kHorizontalTb:
      return BorderTopWidth();
    case WritingMode::kVerticalLr:
      return BorderLeftWidth();
    case WritingMode::kVerticalRl:
      return BorderRightWidth();
  }
  NOTREACHED();
  return BorderTopWidth();
}

float ComputedStyle::BorderAfterWidth() const {
  switch (GetWritingMode()) {
    case WritingMode::kHorizontalTb:
      return BorderBottomWidth();
    case WritingMode::kVerticalLr:
      return BorderRightWidth();
    case WritingMode::kVerticalRl:
      return BorderLeftWidth();
  }
  NOTREACHED();
  return BorderBottomWidth();
}

float ComputedStyle::BorderStartWidth() const {
  if (IsHorizontalWritingMode())
    return IsLeftToRightDirection() ? BorderLeftWidth() : BorderRightWidth();
  return IsLeftToRightDirection() ? BorderTopWidth() : BorderBottomWidth();
}

float ComputedStyle::BorderEndWidth() const {
  if (IsHorizontalWritingMode())
    return IsLeftToRightDirection() ? BorderRightWidth() : BorderLeftWidth();
  return IsLeftToRightDirection() ? BorderBottomWidth() : BorderTopWidth();
}

float ComputedStyle::BorderOverWidth() const {
  return IsHorizontalWritingMode() ? BorderTopWidth() : BorderRightWidth();
}

float ComputedStyle::BorderUnderWidth() const {
  return IsHorizontalWritingMode() ? BorderBottomWidth() : BorderLeftWidth();
}

void ComputedStyle::SetMarginStart(const Length& margin) {
  if (IsHorizontalWritingMode()) {
    if (IsLeftToRightDirection())
      SetMarginLeft(margin);
    else
      SetMarginRight(margin);
  } else {
    if (IsLeftToRightDirection())
      SetMarginTop(margin);
    else
      SetMarginBottom(margin);
  }
}

void ComputedStyle::SetMarginEnd(const Length& margin) {
  if (IsHorizontalWritingMode()) {
    if (IsLeftToRightDirection())
      SetMarginRight(margin);
    else
      SetMarginLeft(margin);
  } else {
    if (IsLeftToRightDirection())
      SetMarginBottom(margin);
    else
      SetMarginTop(margin);
  }
}

void ComputedStyle::SetOffsetPath(PassRefPtr<StylePath> path) {
  rare_non_inherited_data_.Access()->transform_.Access()->motion_.path_ =
      std::move(path);
}

int ComputedStyle::OutlineOutsetExtent() const {
  if (!HasOutline())
    return 0;
  if (OutlineStyleIsAuto()) {
    return GraphicsContext::FocusRingOutsetExtent(
        OutlineOffset(), std::ceil(GetOutlineStrokeWidthForFocusRing()));
  }
  return std::max(0, SaturatedAddition(OutlineWidth(), OutlineOffset()));
}

float ComputedStyle::GetOutlineStrokeWidthForFocusRing() const {
#if OS(MACOSX)
  return OutlineWidth();
#else
  // Draw an outline with thickness in proportion to the zoom level, but never
  // less than 1 pixel so that it remains visible.
  return std::max(EffectiveZoom(), 1.f);
#endif
}

bool ComputedStyle::ColumnRuleEquivalent(
    const ComputedStyle* other_style) const {
  return ColumnRuleStyle() == other_style->ColumnRuleStyle() &&
         ColumnRuleWidth() == other_style->ColumnRuleWidth() &&
         VisitedDependentColor(CSSPropertyColumnRuleColor) ==
             other_style->VisitedDependentColor(CSSPropertyColumnRuleColor);
}

TextEmphasisMark ComputedStyle::GetTextEmphasisMark() const {
  TextEmphasisMark mark =
      static_cast<TextEmphasisMark>(rare_inherited_data_->text_emphasis_mark);
  if (mark != kTextEmphasisMarkAuto)
    return mark;

  if (IsHorizontalWritingMode())
    return kTextEmphasisMarkDot;

  return kTextEmphasisMarkSesame;
}

Color ComputedStyle::InitialTapHighlightColor() {
  return LayoutTheme::TapHighlightColor();
}

const FilterOperations& ComputedStyle::InitialFilter() {
  DEFINE_STATIC_LOCAL(FilterOperationsWrapper, ops,
                      (FilterOperationsWrapper::Create()));
  return ops.Operations();
}

const FilterOperations& ComputedStyle::InitialBackdropFilter() {
  DEFINE_STATIC_LOCAL(FilterOperationsWrapper, ops,
                      (FilterOperationsWrapper::Create()));
  return ops.Operations();
}

LayoutRectOutsets ComputedStyle::ImageOutsets(
    const NinePieceImage& image) const {
  return LayoutRectOutsets(
      NinePieceImage::ComputeOutset(image.Outset().Top(), BorderTopWidth()),
      NinePieceImage::ComputeOutset(image.Outset().Right(), BorderRightWidth()),
      NinePieceImage::ComputeOutset(image.Outset().Bottom(),
                                    BorderBottomWidth()),
      NinePieceImage::ComputeOutset(image.Outset().Left(), BorderLeftWidth()));
}

void ComputedStyle::SetBorderImageSource(StyleImage* image) {
  if (Border().image_.GetImage() == image)
    return;
  surround_data_.Access()->border_.image_.SetImage(image);
}

void ComputedStyle::SetBorderImageSlices(const LengthBox& slices) {
  if (Border().image_.ImageSlices() == slices)
    return;
  surround_data_.Access()->border_.image_.SetImageSlices(slices);
}

void ComputedStyle::SetBorderImageSlicesFill(bool fill) {
  if (Border().image_.Fill() == fill)
    return;
  surround_data_.Access()->border_.image_.SetFill(fill);
}

void ComputedStyle::SetBorderImageWidth(const BorderImageLengthBox& slices) {
  if (Border().image_.BorderSlices() == slices)
    return;
  surround_data_.Access()->border_.image_.SetBorderSlices(slices);
}

void ComputedStyle::SetBorderImageOutset(const BorderImageLengthBox& outset) {
  if (Border().image_.Outset() == outset)
    return;
  surround_data_.Access()->border_.image_.SetOutset(outset);
}

bool ComputedStyle::BorderObscuresBackground() const {
  if (!HasBorder())
    return false;

  // Bail if we have any border-image for now. We could look at the image alpha
  // to improve this.
  if (BorderImage().GetImage())
    return false;

  BorderEdge edges[4];
  GetBorderEdgeInfo(edges);

  for (int i = kBSTop; i <= kBSLeft; ++i) {
    const BorderEdge& curr_edge = edges[i];
    if (!curr_edge.ObscuresBackground())
      return false;
  }

  return true;
}

void ComputedStyle::GetBorderEdgeInfo(BorderEdge edges[],
                                      bool include_logical_left_edge,
                                      bool include_logical_right_edge) const {
  bool horizontal = IsHorizontalWritingMode();

  edges[kBSTop] = BorderEdge(
      BorderTopWidth(), VisitedDependentColor(CSSPropertyBorderTopColor),
      BorderTopStyle(), horizontal || include_logical_left_edge);

  edges[kBSRight] = BorderEdge(
      BorderRightWidth(), VisitedDependentColor(CSSPropertyBorderRightColor),
      BorderRightStyle(), !horizontal || include_logical_right_edge);

  edges[kBSBottom] = BorderEdge(
      BorderBottomWidth(), VisitedDependentColor(CSSPropertyBorderBottomColor),
      BorderBottomStyle(), horizontal || include_logical_right_edge);

  edges[kBSLeft] = BorderEdge(
      BorderLeftWidth(), VisitedDependentColor(CSSPropertyBorderLeftColor),
      BorderLeftStyle(), !horizontal || include_logical_left_edge);
}

void ComputedStyle::CopyChildDependentFlagsFrom(const ComputedStyle& other) {
  SetEmptyState(other.EmptyState());
  if (other.HasExplicitlyInheritedProperties())
    SetHasExplicitlyInheritedProperties();
}

bool ComputedStyle::ShadowListHasCurrentColor(const ShadowList* shadow_list) {
  if (!shadow_list)
    return false;
  for (size_t i = shadow_list->Shadows().size(); i--;) {
    if (shadow_list->Shadows()[i].GetColor().IsCurrentColor())
      return true;
  }
  return false;
}

static inline Vector<GridTrackSize> InitialGridAutoTracks() {
  Vector<GridTrackSize> track_size_list;
  track_size_list.ReserveInitialCapacity(1);
  track_size_list.UncheckedAppend(GridTrackSize(Length(kAuto)));
  return track_size_list;
}

Vector<GridTrackSize> ComputedStyle::InitialGridAutoColumns() {
  return InitialGridAutoTracks();
}

Vector<GridTrackSize> ComputedStyle::InitialGridAutoRows() {
  return InitialGridAutoTracks();
}

int AdjustForAbsoluteZoom(int value, float zoom_factor) {
  if (zoom_factor == 1)
    return value;
  // Needed because computeLengthInt truncates (rather than rounds) when scaling
  // up.
  float fvalue = value;
  if (zoom_factor > 1) {
    if (value < 0)
      fvalue -= 0.5f;
    else
      fvalue += 0.5f;
  }

  return RoundForImpreciseConversion<int>(fvalue / zoom_factor);
}

}  // namespace blink
