/*
 * 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 "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 "wtf/MathExtras.h"
#include "wtf/PtrUtil.h"
#include "wtf/SaturatedArithmetic.h"
#include "wtf/SizeAssertions.h"
#include <algorithm>
#include <memory>

namespace blink {

struct SameSizeAsBorderValue {
  RGBA32 m_color;
  unsigned m_width;
};

ASSERT_SIZE(BorderValue, SameSizeAsBorderValue);

// Since different compilers/architectures pack ComputedStyle differently,
// re-create the same structure for an accurate size comparison.
struct SameSizeAsComputedStyle : public ComputedStyleBase,
                                 public RefCounted<ComputedStyle> {
  void* dataRefs[7];
  void* ownPtrs[1];
  void* dataRefSvgStyle;

  struct InheritedData {
    unsigned m_bitfields[1];
  } m_inheritedData;

  struct NonInheritedData {
    unsigned m_bitfields[3];
  } m_nonInheritedData;
};

ASSERT_SIZE(ComputedStyle, SameSizeAsComputedStyle);

PassRefPtr<ComputedStyle> ComputedStyle::create() {
  return adoptRef(new ComputedStyle());
}

PassRefPtr<ComputedStyle> ComputedStyle::createInitialStyle() {
  return adoptRef(new ComputedStyle(InitialStyle));
}

void ComputedStyle::invalidateInitialStyle() {
  mutableInitialStyle().setTapHighlightColor(initialTapHighlightColor());
}

PassRefPtr<ComputedStyle> ComputedStyle::createAnonymousStyleWithDisplay(
    const ComputedStyle& parentStyle,
    EDisplay display) {
  RefPtr<ComputedStyle> newStyle = ComputedStyle::create();
  newStyle->inheritFrom(parentStyle);
  newStyle->inheritUnicodeBidiFrom(parentStyle);
  newStyle->setDisplay(display);
  return newStyle;
}

PassRefPtr<ComputedStyle> ComputedStyle::clone(const ComputedStyle& other) {
  return adoptRef(new ComputedStyle(other));
}

ALWAYS_INLINE ComputedStyle::ComputedStyle()
    : ComputedStyleBase(),
      RefCounted<ComputedStyle>(),
      m_box(initialStyle().m_box),
      m_visual(initialStyle().m_visual),
      m_background(initialStyle().m_background),
      m_surround(initialStyle().m_surround),
      m_rareNonInheritedData(initialStyle().m_rareNonInheritedData),
      m_rareInheritedData(initialStyle().m_rareInheritedData),
      m_styleInheritedData(initialStyle().m_styleInheritedData),
      m_svgStyle(initialStyle().m_svgStyle) {
  setBitDefaults();  // Would it be faster to copy this from the default style?
  static_assert((sizeof(InheritedData) <= 8), "InheritedData should not grow");
  static_assert((sizeof(NonInheritedData) <= 12),
                "NonInheritedData should not grow");
}

ALWAYS_INLINE ComputedStyle::ComputedStyle(InitialStyleTag)
    : ComputedStyleBase(), RefCounted<ComputedStyle>() {
  setBitDefaults();

  m_box.init();
  m_visual.init();
  m_background.init();
  m_surround.init();
  m_rareNonInheritedData.init();
  m_rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
  m_rareNonInheritedData.access()->m_flexibleBox.init();
  m_rareNonInheritedData.access()->m_multiCol.init();
  m_rareNonInheritedData.access()->m_transform.init();
  m_rareNonInheritedData.access()->m_willChange.init();
  m_rareNonInheritedData.access()->m_filter.init();
  m_rareNonInheritedData.access()->m_backdropFilter.init();
  m_rareNonInheritedData.access()->m_grid.init();
  m_rareNonInheritedData.access()->m_gridItem.init();
  m_rareNonInheritedData.access()->m_scrollSnap.init();
  m_rareInheritedData.init();
  m_styleInheritedData.init();
  m_svgStyle.init();
}

ALWAYS_INLINE ComputedStyle::ComputedStyle(const ComputedStyle& o)
    : ComputedStyleBase(o),
      RefCounted<ComputedStyle>(),
      m_box(o.m_box),
      m_visual(o.m_visual),
      m_background(o.m_background),
      m_surround(o.m_surround),
      m_rareNonInheritedData(o.m_rareNonInheritedData),
      m_rareInheritedData(o.m_rareInheritedData),
      m_styleInheritedData(o.m_styleInheritedData),
      m_svgStyle(o.m_svgStyle),
      m_inheritedData(o.m_inheritedData),
      m_nonInheritedData(o.m_nonInheritedData) {}

static StyleRecalcChange diffPseudoStyles(const ComputedStyle& oldStyle,
                                          const ComputedStyle& newStyle) {
  // If the pseudoStyles have changed, ensure layoutObject triggers setStyle.
  if (!oldStyle.hasAnyPublicPseudoStyles() &&
      !newStyle.hasAnyPublicPseudoStyles())
    return NoChange;
  for (PseudoId pseudoId = FirstPublicPseudoId;
       pseudoId < FirstInternalPseudoId;
       pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
    if (!oldStyle.hasPseudoStyle(pseudoId) &&
        !newStyle.hasPseudoStyle(pseudoId))
      continue;
    const ComputedStyle* newPseudoStyle =
        newStyle.getCachedPseudoStyle(pseudoId);
    if (!newPseudoStyle)
      return NoInherit;
    const ComputedStyle* oldPseudoStyle =
        oldStyle.getCachedPseudoStyle(pseudoId);
    if (oldPseudoStyle && *oldPseudoStyle != *newPseudoStyle)
      return NoInherit;
  }
  return NoChange;
}

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

  if (!oldStyle && !newStyle)
    return NoChange;

  if (oldStyle->display() != newStyle->display() ||
      oldStyle->hasPseudoStyle(PseudoIdFirstLetter) !=
          newStyle->hasPseudoStyle(PseudoIdFirstLetter) ||
      !oldStyle->contentDataEquivalent(newStyle) ||
      oldStyle->hasTextCombine() != newStyle->hasTextCombine())
    return Reattach;

  bool independentEqual = oldStyle->independentInheritedEqual(*newStyle);
  bool nonIndependentEqual = oldStyle->nonIndependentInheritedEqual(*newStyle);
  if (!independentEqual || !nonIndependentEqual) {
    if (nonIndependentEqual && !oldStyle->hasExplicitlyInheritedProperties())
      return IndependentInherit;
    return Inherit;
  }

  if (!oldStyle->loadingCustomFontsEqual(*newStyle) ||
      oldStyle->alignItems() != newStyle->alignItems() ||
      oldStyle->justifyItems() != newStyle->justifyItems())
    return Inherit;

  if (*oldStyle == *newStyle)
    return diffPseudoStyles(*oldStyle, *newStyle);

  if (oldStyle->hasExplicitlyInheritedProperties())
    return Inherit;

  return NoInherit;
}

void ComputedStyle::propagateIndependentInheritedProperties(
    const ComputedStyle& parentStyle) {
  ComputedStyleBase::propagateIndependentInheritedProperties(parentStyle);
}

StyleSelfAlignmentData resolvedSelfAlignment(
    const StyleSelfAlignmentData& value,
    ItemPosition normalValueBehavior) {
  // 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.position() == ItemPositionNormal ||
      value.position() == ItemPositionAuto)
    return {normalValueBehavior, OverflowAlignmentDefault};
  return value;
}

StyleSelfAlignmentData ComputedStyle::resolvedAlignItems(
    ItemPosition normalValueBehaviour) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  return resolvedSelfAlignment(alignItems(), normalValueBehaviour);
}

StyleSelfAlignmentData ComputedStyle::resolvedAlignSelf(
    ItemPosition normalValueBehaviour,
    const ComputedStyle* parentStyle) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  if (!parentStyle || alignSelfPosition() != ItemPositionAuto)
    return resolvedSelfAlignment(alignSelf(), normalValueBehaviour);

  // 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 parentStyle->resolvedAlignItems(normalValueBehaviour);
}

StyleSelfAlignmentData ComputedStyle::resolvedJustifyItems(
    ItemPosition normalValueBehaviour) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  return resolvedSelfAlignment(justifyItems(), normalValueBehaviour);
}

StyleSelfAlignmentData ComputedStyle::resolvedJustifySelf(
    ItemPosition normalValueBehaviour,
    const ComputedStyle* parentStyle) const {
  // We will return the behaviour of 'normal' value if needed, which is specific
  // of each layout model.
  if (!parentStyle || justifySelfPosition() != ItemPositionAuto)
    return resolvedSelfAlignment(justifySelf(), normalValueBehaviour);

  // 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 parentStyle->resolvedJustifyItems(normalValueBehaviour);
}

static inline ContentPosition resolvedContentAlignmentPosition(
    const StyleContentAlignmentData& value,
    const StyleContentAlignmentData& normalValueBehavior) {
  return (value.position() == ContentPositionNormal &&
          value.distribution() == ContentDistributionDefault)
             ? normalValueBehavior.position()
             : value.position();
}

static inline ContentDistributionType resolvedContentAlignmentDistribution(
    const StyleContentAlignmentData& value,
    const StyleContentAlignmentData& normalValueBehavior) {
  return (value.position() == ContentPositionNormal &&
          value.distribution() == ContentDistributionDefault)
             ? normalValueBehavior.distribution()
             : value.distribution();
}

ContentPosition ComputedStyle::resolvedJustifyContentPosition(
    const StyleContentAlignmentData& normalValueBehavior) const {
  return resolvedContentAlignmentPosition(justifyContent(),
                                          normalValueBehavior);
}

ContentDistributionType ComputedStyle::resolvedJustifyContentDistribution(
    const StyleContentAlignmentData& normalValueBehavior) const {
  return resolvedContentAlignmentDistribution(justifyContent(),
                                              normalValueBehavior);
}

ContentPosition ComputedStyle::resolvedAlignContentPosition(
    const StyleContentAlignmentData& normalValueBehavior) const {
  return resolvedContentAlignmentPosition(alignContent(), normalValueBehavior);
}

ContentDistributionType ComputedStyle::resolvedAlignContentDistribution(
    const StyleContentAlignmentData& normalValueBehavior) const {
  return resolvedContentAlignmentDistribution(alignContent(),
                                              normalValueBehavior);
}

void ComputedStyle::inheritFrom(const ComputedStyle& inheritParent,
                                IsAtShadowBoundary isAtShadowBoundary) {
  ComputedStyleBase::inheritFrom(inheritParent, isAtShadowBoundary);
  if (isAtShadowBoundary == AtShadowBoundary) {
    // Even if surrounding content is user-editable, shadow DOM should act as a
    // single unit, and not necessarily be editable
    EUserModify currentUserModify = userModify();
    m_rareInheritedData = inheritParent.m_rareInheritedData;
    setUserModify(currentUserModify);
  } else {
    m_rareInheritedData = inheritParent.m_rareInheritedData;
  }
  m_styleInheritedData = inheritParent.m_styleInheritedData;
  m_inheritedData = inheritParent.m_inheritedData;
  if (m_svgStyle != inheritParent.m_svgStyle)
    m_svgStyle.access()->inheritFrom(inheritParent.m_svgStyle.get());
}

void ComputedStyle::copyNonInheritedFromCached(const ComputedStyle& other) {
  ComputedStyleBase::copyNonInheritedFromCached(other);
  m_box = other.m_box;
  m_visual = other.m_visual;
  m_background = other.m_background;
  m_surround = other.m_surround;
  m_rareNonInheritedData = other.m_rareNonInheritedData;

  // The flags are copied one-by-one because m_nonInheritedData.m_contains a
  // bunch of stuff other than real style data.
  // See comments for each skipped flag below.
  m_nonInheritedData.m_effectiveDisplay =
      other.m_nonInheritedData.m_effectiveDisplay;
  m_nonInheritedData.m_originalDisplay =
      other.m_nonInheritedData.m_originalDisplay;
  m_nonInheritedData.m_overflowAnchor =
      other.m_nonInheritedData.m_overflowAnchor;
  m_nonInheritedData.m_overflowX = other.m_nonInheritedData.m_overflowX;
  m_nonInheritedData.m_overflowY = other.m_nonInheritedData.m_overflowY;
  m_nonInheritedData.m_verticalAlign = other.m_nonInheritedData.m_verticalAlign;
  m_nonInheritedData.m_clear = other.m_nonInheritedData.m_clear;
  m_nonInheritedData.m_position = other.m_nonInheritedData.m_position;
  m_nonInheritedData.m_tableLayout = other.m_nonInheritedData.m_tableLayout;
  m_nonInheritedData.m_unicodeBidi = other.m_nonInheritedData.m_unicodeBidi;
  m_nonInheritedData.m_hasViewportUnits =
      other.m_nonInheritedData.m_hasViewportUnits;
  m_nonInheritedData.m_breakBefore = other.m_nonInheritedData.m_breakBefore;
  m_nonInheritedData.m_breakAfter = other.m_nonInheritedData.m_breakAfter;
  m_nonInheritedData.m_breakInside = other.m_nonInheritedData.m_breakInside;
  m_nonInheritedData.m_hasRemUnits = other.m_nonInheritedData.m_hasRemUnits;

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

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

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

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

  // 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_nonInheritedData.m_emptyState
  // m_nonInheritedData.m_affectedByFocus
  // m_nonInheritedData.m_affectedByHover
  // m_nonInheritedData.m_affectedByActive
  // m_nonInheritedData.m_affectedByDrag
  // m_nonInheritedData.m_isLink

  if (m_svgStyle != other.m_svgStyle)
    m_svgStyle.access()->copyNonInheritedFromCached(other.m_svgStyle.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 (!m_cachedPseudoStyles || styleType() != PseudoIdNone)
    return false;

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

  return false;
}

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

  if (styleType() != PseudoIdNone)
    return 0;

  for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
    ComputedStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
    if (pseudoStyle->styleType() == pid)
      return pseudoStyle;
  }

  return 0;
}

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

  ASSERT(pseudo->styleType() > PseudoIdNone);

  ComputedStyle* result = pseudo.get();

  if (!m_cachedPseudoStyles)
    m_cachedPseudoStyles = WTF::wrapUnique(new PseudoStyleCache);

  m_cachedPseudoStyles->append(pseudo);

  return result;
}

void ComputedStyle::removeCachedPseudoStyle(PseudoId pid) {
  if (!m_cachedPseudoStyles)
    return;
  for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
    ComputedStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
    if (pseudoStyle->styleType() == pid) {
      m_cachedPseudoStyles->remove(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) &&
         m_inheritedData == other.m_inheritedData &&
         m_styleInheritedData == other.m_styleInheritedData &&
         m_svgStyle->inheritedEqual(*other.m_svgStyle) &&
         m_rareInheritedData == other.m_rareInheritedData;
}

bool ComputedStyle::loadingCustomFontsEqual(const ComputedStyle& other) const {
  return font().loadingCustomFonts() == other.font().loadingCustomFonts();
}

bool ComputedStyle::nonInheritedEqual(const ComputedStyle& other) const {
  // compare everything except the pseudoStyle pointer
  return ComputedStyleBase::nonInheritedEqual(other) &&
         m_nonInheritedData == other.m_nonInheritedData &&
         m_box == other.m_box && m_visual == other.m_visual &&
         m_background == other.m_background && m_surround == other.m_surround &&
         m_rareNonInheritedData == other.m_rareNonInheritedData &&
         m_svgStyle->nonInheritedEqual(*other.m_svgStyle);
}

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) &&
         m_inheritedData == other.m_inheritedData &&
         m_styleInheritedData.get() == other.m_styleInheritedData.get() &&
         m_svgStyle.get() == other.m_svgStyle.get() &&
         m_rareInheritedData.get() == other.m_rareInheritedData.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 (m_svgStyle.get() != other.m_svgStyle.get())
    diff = m_svgStyle->diff(other.m_svgStyle.get());

  if ((!diff.needsFullLayout() || !diff.needsPaintInvalidation()) &&
      diffNeedsFullLayoutAndPaintInvalidation(other)) {
    diff.setNeedsFullLayout();
    diff.setNeedsPaintInvalidationObject();
  }

  if (!diff.needsFullLayout() && diffNeedsFullLayout(other))
    diff.setNeedsFullLayout();

  if (!diff.needsFullLayout() &&
      m_surround->margin != other.m_surround->margin) {
    // Relative-positioned elements collapse their margins so need a full
    // layout.
    if (hasOutOfFlowPosition())
      diff.setNeedsPositionedMovementLayout();
    else
      diff.setNeedsFullLayout();
  }

  if (!diff.needsFullLayout() && position() != StaticPosition &&
      m_surround->offset != other.m_surround->offset) {
    // 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();

  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 (m_nonInheritedData.m_position != other.m_nonInheritedData.m_position)
    return true;

  if (m_box.get() != other.m_box.get()) {
    if (m_box->width() != other.m_box->width() ||
        m_box->minWidth() != other.m_box->minWidth() ||
        m_box->maxWidth() != other.m_box->maxWidth() ||
        m_box->height() != other.m_box->height() ||
        m_box->minHeight() != other.m_box->minHeight() ||
        m_box->maxHeight() != other.m_box->maxHeight())
      return true;
  }

  if (m_surround.get() != other.m_surround.get()) {
    if (m_surround->margin != other.m_surround->margin ||
        m_surround->offset != other.m_surround->offset ||
        m_surround->padding != other.m_surround->padding)
      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 (m_surround.get() != other.m_surround.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 (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
    if (m_rareNonInheritedData->m_appearance !=
            other.m_rareNonInheritedData->m_appearance ||
        m_rareNonInheritedData->marginBeforeCollapse !=
            other.m_rareNonInheritedData->marginBeforeCollapse ||
        m_rareNonInheritedData->marginAfterCollapse !=
            other.m_rareNonInheritedData->marginAfterCollapse ||
        m_rareNonInheritedData->lineClamp !=
            other.m_rareNonInheritedData->lineClamp ||
        m_rareNonInheritedData->textOverflow !=
            other.m_rareNonInheritedData->textOverflow ||
        m_rareNonInheritedData->m_shapeMargin !=
            other.m_rareNonInheritedData->m_shapeMargin ||
        m_rareNonInheritedData->m_order !=
            other.m_rareNonInheritedData->m_order ||
        m_rareNonInheritedData->hasFilters() !=
            other.m_rareNonInheritedData->hasFilters())
      return true;

    if (m_rareNonInheritedData->m_grid.get() !=
            other.m_rareNonInheritedData->m_grid.get() &&
        *m_rareNonInheritedData->m_grid.get() !=
            *other.m_rareNonInheritedData->m_grid.get())
      return true;

    if (m_rareNonInheritedData->m_gridItem.get() !=
            other.m_rareNonInheritedData->m_gridItem.get() &&
        *m_rareNonInheritedData->m_gridItem.get() !=
            *other.m_rareNonInheritedData->m_gridItem.get())
      return true;

    if (m_rareNonInheritedData->m_deprecatedFlexibleBox.get() !=
            other.m_rareNonInheritedData->m_deprecatedFlexibleBox.get() &&
        *m_rareNonInheritedData->m_deprecatedFlexibleBox.get() !=
            *other.m_rareNonInheritedData->m_deprecatedFlexibleBox.get())
      return true;

    if (m_rareNonInheritedData->m_flexibleBox.get() !=
            other.m_rareNonInheritedData->m_flexibleBox.get() &&
        *m_rareNonInheritedData->m_flexibleBox.get() !=
            *other.m_rareNonInheritedData->m_flexibleBox.get())
      return true;

    if (m_rareNonInheritedData->m_multiCol.get() !=
            other.m_rareNonInheritedData->m_multiCol.get() &&
        *m_rareNonInheritedData->m_multiCol.get() !=
            *other.m_rareNonInheritedData->m_multiCol.get())
      return true;

    // If the counter directives change, trigger a relayout to re-calculate
    // counter values and rebuild the counter node tree.
    const CounterDirectiveMap* mapA =
        m_rareNonInheritedData->m_counterDirectives.get();
    const CounterDirectiveMap* mapB =
        other.m_rareNonInheritedData->m_counterDirectives.get();
    if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
      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() &&
        m_rareNonInheritedData->hasOpacity() !=
            other.m_rareNonInheritedData->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 (m_rareInheritedData.get() != other.m_rareInheritedData.get()) {
    if (m_rareInheritedData->highlight !=
            other.m_rareInheritedData->highlight ||
        m_rareInheritedData->indent != other.m_rareInheritedData->indent ||
        m_rareInheritedData->m_textAlignLast !=
            other.m_rareInheritedData->m_textAlignLast ||
        m_rareInheritedData->m_textIndentLine !=
            other.m_rareInheritedData->m_textIndentLine ||
        m_rareInheritedData->m_effectiveZoom !=
            other.m_rareInheritedData->m_effectiveZoom ||
        m_rareInheritedData->wordBreak !=
            other.m_rareInheritedData->wordBreak ||
        m_rareInheritedData->overflowWrap !=
            other.m_rareInheritedData->overflowWrap ||
        m_rareInheritedData->lineBreak !=
            other.m_rareInheritedData->lineBreak ||
        m_rareInheritedData->textSecurity !=
            other.m_rareInheritedData->textSecurity ||
        m_rareInheritedData->hyphens != other.m_rareInheritedData->hyphens ||
        m_rareInheritedData->hyphenationLimitBefore !=
            other.m_rareInheritedData->hyphenationLimitBefore ||
        m_rareInheritedData->hyphenationLimitAfter !=
            other.m_rareInheritedData->hyphenationLimitAfter ||
        m_rareInheritedData->hyphenationString !=
            other.m_rareInheritedData->hyphenationString ||
        m_rareInheritedData->m_respectImageOrientation !=
            other.m_rareInheritedData->m_respectImageOrientation ||
        m_rareInheritedData->m_rubyPosition !=
            other.m_rareInheritedData->m_rubyPosition ||
        m_rareInheritedData->textEmphasisMark !=
            other.m_rareInheritedData->textEmphasisMark ||
        m_rareInheritedData->textEmphasisPosition !=
            other.m_rareInheritedData->textEmphasisPosition ||
        m_rareInheritedData->textEmphasisCustomMark !=
            other.m_rareInheritedData->textEmphasisCustomMark ||
        m_rareInheritedData->m_textJustify !=
            other.m_rareInheritedData->m_textJustify ||
        m_rareInheritedData->m_textOrientation !=
            other.m_rareInheritedData->m_textOrientation ||
        m_rareInheritedData->m_textCombine !=
            other.m_rareInheritedData->m_textCombine ||
        m_rareInheritedData->m_tabSize !=
            other.m_rareInheritedData->m_tabSize ||
        m_rareInheritedData->m_textSizeAdjust !=
            other.m_rareInheritedData->m_textSizeAdjust ||
        m_rareInheritedData->listStyleImage !=
            other.m_rareInheritedData->listStyleImage ||
        m_rareInheritedData->m_snapHeightUnit !=
            other.m_rareInheritedData->m_snapHeightUnit ||
        m_rareInheritedData->m_snapHeightPosition !=
            other.m_rareInheritedData->m_snapHeightPosition ||
        m_rareInheritedData->textStrokeWidth !=
            other.m_rareInheritedData->textStrokeWidth)
      return true;

    if (!m_rareInheritedData->shadowDataEquivalent(
            *other.m_rareInheritedData.get()))
      return true;

    if (!m_rareInheritedData->quotesDataEquivalent(
            *other.m_rareInheritedData.get()))
      return true;
  }

  if (m_styleInheritedData->textAutosizingMultiplier !=
      other.m_styleInheritedData->textAutosizingMultiplier)
    return true;

  if (m_styleInheritedData->font.loadingCustomFonts() !=
      other.m_styleInheritedData->font.loadingCustomFonts())
    return true;

  if (m_styleInheritedData.get() != other.m_styleInheritedData.get()) {
    if (m_styleInheritedData->line_height !=
            other.m_styleInheritedData->line_height ||
        m_styleInheritedData->font != other.m_styleInheritedData->font ||
        m_styleInheritedData->horizontal_border_spacing !=
            other.m_styleInheritedData->horizontal_border_spacing ||
        m_styleInheritedData->vertical_border_spacing !=
            other.m_styleInheritedData->vertical_border_spacing)
      return true;
  }

  if (boxDirection() != other.boxDirection() ||
      m_inheritedData.m_rtlOrdering != other.m_inheritedData.m_rtlOrdering ||
      m_inheritedData.m_textAlign != other.m_inheritedData.m_textAlign ||
      textTransform() != other.textTransform() ||
      m_inheritedData.m_direction != other.m_inheritedData.m_direction ||
      whiteSpace() != other.whiteSpace() ||
      m_inheritedData.m_writingMode != other.m_inheritedData.m_writingMode)
    return true;

  if (m_nonInheritedData.m_overflowX != other.m_nonInheritedData.m_overflowX ||
      m_nonInheritedData.m_overflowY != other.m_nonInheritedData.m_overflowY ||
      m_nonInheritedData.m_clear != other.m_nonInheritedData.m_clear ||
      m_nonInheritedData.m_unicodeBidi !=
          other.m_nonInheritedData.m_unicodeBidi ||
      floating() != other.floating() ||
      m_nonInheritedData.m_originalDisplay !=
          other.m_nonInheritedData.m_originalDisplay)
    return true;

  if (isDisplayTableType(display())) {
    if (borderCollapse() != other.borderCollapse() ||
        emptyCells() != other.emptyCells() ||
        captionSide() != other.captionSide() ||
        m_nonInheritedData.m_tableLayout !=
            other.m_nonInheritedData.m_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::Collapse) &&
        ((borderTopStyle() == BorderStyleHidden &&
          other.borderTopStyle() == BorderStyleNone) ||
         (borderTopStyle() == BorderStyleNone &&
          other.borderTopStyle() == BorderStyleHidden) ||
         (borderBottomStyle() == BorderStyleHidden &&
          other.borderBottomStyle() == BorderStyleNone) ||
         (borderBottomStyle() == BorderStyleNone &&
          other.borderBottomStyle() == BorderStyleHidden) ||
         (borderLeftStyle() == BorderStyleHidden &&
          other.borderLeftStyle() == BorderStyleNone) ||
         (borderLeftStyle() == BorderStyleNone &&
          other.borderLeftStyle() == BorderStyleHidden) ||
         (borderRightStyle() == BorderStyleHidden &&
          other.borderRightStyle() == BorderStyleNone) ||
         (borderRightStyle() == BorderStyleNone &&
          other.borderRightStyle() == BorderStyleHidden)))
      return true;
  } else if (display() == EDisplay::ListItem) {
    if (m_inheritedData.m_listStyleType !=
            other.m_inheritedData.m_listStyleType ||
        listStylePosition() != other.listStylePosition())
      return true;
  }

  if ((visibility() == EVisibility::Collapse) !=
      (other.visibility() == EVisibility::Collapse))
    return true;

  if (hasPseudoStyle(PseudoIdScrollbar) !=
      other.hasPseudoStyle(PseudoIdScrollbar))
    return true;

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

  return false;
}

bool ComputedStyle::diffNeedsFullLayout(const ComputedStyle& other) const {
  if (m_box.get() != other.m_box.get()) {
    if (m_box->width() != other.m_box->width() ||
        m_box->minWidth() != other.m_box->minWidth() ||
        m_box->maxWidth() != other.m_box->maxWidth() ||
        m_box->height() != other.m_box->height() ||
        m_box->minHeight() != other.m_box->minHeight() ||
        m_box->maxHeight() != other.m_box->maxHeight())
      return true;

    if (m_box->verticalAlign() != other.m_box->verticalAlign())
      return true;

    if (m_box->boxSizing() != other.m_box->boxSizing())
      return true;
  }

  if (m_nonInheritedData.m_verticalAlign !=
          other.m_nonInheritedData.m_verticalAlign ||
      m_nonInheritedData.m_position != other.m_nonInheritedData.m_position)
    return true;

  if (m_surround.get() != other.m_surround.get()) {
    if (m_surround->padding != other.m_surround->padding)
      return true;
  }

  if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
    if (m_rareNonInheritedData->m_alignContent !=
            other.m_rareNonInheritedData->m_alignContent ||
        m_rareNonInheritedData->m_alignItems !=
            other.m_rareNonInheritedData->m_alignItems ||
        m_rareNonInheritedData->m_alignSelf !=
            other.m_rareNonInheritedData->m_alignSelf ||
        m_rareNonInheritedData->m_justifyContent !=
            other.m_rareNonInheritedData->m_justifyContent ||
        m_rareNonInheritedData->m_justifyItems !=
            other.m_rareNonInheritedData->m_justifyItems ||
        m_rareNonInheritedData->m_justifySelf !=
            other.m_rareNonInheritedData->m_justifySelf ||
        m_rareNonInheritedData->m_contain !=
            other.m_rareNonInheritedData->m_contain)
      return true;
  }

  return false;
}

bool ComputedStyle::diffNeedsPaintInvalidationSubtree(
    const ComputedStyle& other) const {
  if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
    if (m_rareNonInheritedData->m_effectiveBlendMode !=
            other.m_rareNonInheritedData->m_effectiveBlendMode ||
        m_rareNonInheritedData->m_isolation !=
            other.m_rareNonInheritedData->m_isolation)
      return true;

    if (m_rareNonInheritedData->m_mask !=
            other.m_rareNonInheritedData->m_mask ||
        m_rareNonInheritedData->m_maskBoxImage !=
            other.m_rareNonInheritedData->m_maskBoxImage)
      return true;
  }

  return false;
}

bool ComputedStyle::diffNeedsPaintInvalidationObject(
    const ComputedStyle& other) const {
  if (visibility() != other.visibility() ||
      printColorAdjust() != other.printColorAdjust() ||
      m_inheritedData.m_insideLink != other.m_inheritedData.m_insideLink ||
      !m_surround->border.visuallyEqual(other.m_surround->border) ||
      *m_background != *other.m_background)
    return true;

  if (m_rareInheritedData.get() != other.m_rareInheritedData.get()) {
    if (m_rareInheritedData->userModify !=
            other.m_rareInheritedData->userModify ||
        m_rareInheritedData->userSelect !=
            other.m_rareInheritedData->userSelect ||
        m_rareInheritedData->m_imageRendering !=
            other.m_rareInheritedData->m_imageRendering)
      return true;
  }

  if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
    if (m_rareNonInheritedData->userDrag !=
            other.m_rareNonInheritedData->userDrag ||
        m_rareNonInheritedData->m_objectFit !=
            other.m_rareNonInheritedData->m_objectFit ||
        m_rareNonInheritedData->m_objectPosition !=
            other.m_rareNonInheritedData->m_objectPosition ||
        !m_rareNonInheritedData->shadowDataEquivalent(
            *other.m_rareNonInheritedData.get()) ||
        !m_rareNonInheritedData->shapeOutsideDataEquivalent(
            *other.m_rareNonInheritedData.get()) ||
        !m_rareNonInheritedData->clipPathDataEquivalent(
            *other.m_rareNonInheritedData.get()) ||
        !m_rareNonInheritedData->m_outline.visuallyEqual(
            other.m_rareNonInheritedData->m_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 (m_rareNonInheritedData->m_paintImages) {
    for (const auto& image : *m_rareNonInheritedData->m_paintImages) {
      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 propertyID : *value->nativeInvalidationProperties()) {
    // TODO(ikilpatrick): remove isInterpolableProperty check once
    // CSSPropertyEquality::propertiesEqual correctly handles all properties.
    if (!CSSPropertyMetadata::isInterpolableProperty(propertyID) ||
        !CSSPropertyEquality::propertiesEqual(propertyID, *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;
}

void ComputedStyle::updatePropertySpecificDifferences(
    const ComputedStyle& other,
    StyleDifference& diff) const {
  if (m_box->zIndex() != other.m_box->zIndex() ||
      isStackingContext() != other.isStackingContext())
    diff.setZIndexChanged();

  if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
    if (!transformDataEquivalent(other))
      diff.setTransformChanged();

    if (m_rareNonInheritedData->opacity !=
        other.m_rareNonInheritedData->opacity)
      diff.setOpacityChanged();

    if (m_rareNonInheritedData->m_filter !=
        other.m_rareNonInheritedData->m_filter)
      diff.setFilterChanged();

    if (!m_rareNonInheritedData->shadowDataEquivalent(
            *other.m_rareNonInheritedData.get()))
      diff.setNeedsRecomputeOverflow();

    if (m_rareNonInheritedData->m_backdropFilter !=
        other.m_rareNonInheritedData->m_backdropFilter)
      diff.setBackdropFilterChanged();

    if (!m_rareNonInheritedData->reflectionDataEquivalent(
            *other.m_rareNonInheritedData.get()))
      diff.setFilterChanged();

    if (!m_rareNonInheritedData->m_outline.visuallyEqual(
            other.m_rareNonInheritedData->m_outline))
      diff.setNeedsRecomputeOverflow();
  }

  if (!m_surround->border.visualOverflowEqual(other.m_surround->border))
    diff.setNeedsRecomputeOverflow();

  if (!diff.needsPaintInvalidation()) {
    if (m_styleInheritedData->color != other.m_styleInheritedData->color ||
        m_styleInheritedData->visitedLinkColor !=
            other.m_styleInheritedData->visitedLinkColor ||
        m_inheritedData.m_hasSimpleUnderline !=
            other.m_inheritedData.m_hasSimpleUnderline ||
        m_visual->textDecoration != other.m_visual->textDecoration) {
      diff.setTextDecorationOrColorChanged();
    } else if (m_rareNonInheritedData.get() !=
                   other.m_rareNonInheritedData.get() &&
               (m_rareNonInheritedData->m_textDecorationStyle !=
                    other.m_rareNonInheritedData->m_textDecorationStyle ||
                m_rareNonInheritedData->m_textDecorationColor !=
                    other.m_rareNonInheritedData->m_textDecorationColor ||
                m_rareNonInheritedData->m_visitedLinkTextDecorationColor !=
                    other.m_rareNonInheritedData
                        ->m_visitedLinkTextDecorationColor)) {
      diff.setTextDecorationOrColorChanged();
    } else if (m_rareInheritedData.get() != other.m_rareInheritedData.get() &&
               (m_rareInheritedData->textFillColor() !=
                    other.m_rareInheritedData->textFillColor() ||
                m_rareInheritedData->textStrokeColor() !=
                    other.m_rareInheritedData->textStrokeColor() ||
                m_rareInheritedData->textEmphasisColor() !=
                    other.m_rareInheritedData->textEmphasisColor() ||
                m_rareInheritedData->visitedLinkTextFillColor() !=
                    other.m_rareInheritedData->visitedLinkTextFillColor() ||
                m_rareInheritedData->visitedLinkTextStrokeColor() !=
                    other.m_rareInheritedData->visitedLinkTextStrokeColor() ||
                m_rareInheritedData->visitedLinkTextEmphasisColor() !=
                    other.m_rareInheritedData->visitedLinkTextEmphasisColor() ||
                m_rareInheritedData->textEmphasisFill !=
                    other.m_rareInheritedData->textEmphasisFill ||
                m_rareInheritedData->m_textDecorationSkip !=
                    other.m_rareInheritedData->m_textDecorationSkip ||
                m_rareInheritedData->appliedTextDecorations !=
                    other.m_rareInheritedData->appliedTextDecorations ||
                m_rareInheritedData->caretColor() !=
                    other.m_rareInheritedData->caretColor() ||
                m_rareInheritedData->visitedLinkCaretColor() !=
                    other.m_rareInheritedData->visitedLinkCaretColor())) {
      diff.setTextDecorationOrColorChanged();
    }
  }

  bool hasClip = hasOutOfFlowPosition() && !m_visual->hasAutoClip;
  bool otherHasClip =
      other.hasOutOfFlowPosition() && !other.m_visual->hasAutoClip;
  if (hasClip != otherHasClip ||
      (hasClip && m_visual->clip != other.m_visual->clip))
    diff.setCSSClipChanged();
}

void ComputedStyle::addPaintImage(StyleImage* image) {
  if (!m_rareNonInheritedData.access()->m_paintImages) {
    m_rareNonInheritedData.access()->m_paintImages =
        WTF::makeUnique<Vector<Persistent<StyleImage>>>();
  }
  m_rareNonInheritedData.access()->m_paintImages->append(image);
}

void ComputedStyle::addCursor(StyleImage* image,
                              bool hotSpotSpecified,
                              const IntPoint& hotSpot) {
  if (!m_rareInheritedData.access()->cursorData)
    m_rareInheritedData.access()->cursorData = new CursorList;
  m_rareInheritedData.access()->cursorData->append(
      CursorData(image, hotSpotSpecified, hotSpot));
}

void ComputedStyle::setCursorList(CursorList* other) {
  m_rareInheritedData.access()->cursorData = other;
}

void ComputedStyle::setQuotes(PassRefPtr<QuotesData> q) {
  m_rareInheritedData.access()->quotes = q;
}

void ComputedStyle::clearCursorList() {
  if (m_rareInheritedData->cursorData)
    m_rareInheritedData.access()->cursorData = 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 isDocumentElement,
                                            bool isInTopLayer) {
  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() == TransformStyle3DPreserve3D) {
    setIsStackingContext(true);
    return;
  }

  if (isDocumentElement || isInTopLayer || styleType() == PseudoIdBackdrop ||
      hasOpacity() || hasTransformRelatedProperty() || hasMask() ||
      clipPath() || boxReflect() || hasFilterInducingProperty() ||
      hasBackdropFilter() || hasBlendMode() || hasIsolation() ||
      hasViewportConstrainedPosition() ||
      hasPropertyThatCreatesStackingContext(willChangeProperties()) ||
      containsPaint()) {
    setIsStackingContext(true);
  }
}

void ComputedStyle::addCallbackSelector(const String& selector) {
  if (!m_rareNonInheritedData->m_callbackSelectors.contains(selector))
    m_rareNonInheritedData.access()->m_callbackSelectors.append(selector);
}

void ComputedStyle::setContent(ContentData* contentData) {
  SET_VAR(m_rareNonInheritedData, m_content, contentData);
}

bool ComputedStyle::hasWillChangeCompositingHint() const {
  for (size_t i = 0;
       i < m_rareNonInheritedData->m_willChange->m_properties.size(); ++i) {
    switch (m_rareNonInheritedData->m_willChange->m_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 :
       m_rareNonInheritedData->m_willChange->m_properties) {
    switch (property) {
      case CSSPropertyTransform:
      case CSSPropertyAliasWebkitTransform:
      case CSSPropertyPerspective:
      case CSSPropertyTranslate:
      case CSSPropertyScale:
      case CSSPropertyRotate:
        return true;
      default:
        break;
    }
  }
  return false;
}

bool ComputedStyle::requireTransformOrigin(
    ApplyTransformOrigin applyOrigin,
    ApplyMotionPath applyMotionPath) 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 (applyOrigin != IncludeTransformOrigin)
    return false;

  if (applyMotionPath == IncludeMotionPath)
    return true;

  for (const auto& operation : transform().operations()) {
    TransformOperation::OperationType type = operation->type();
    if (type != TransformOperation::TranslateX &&
        type != TransformOperation::TranslateY &&
        type != TransformOperation::Translate &&
        type != TransformOperation::TranslateZ &&
        type != TransformOperation::Translate3D)
      return true;
  }

  return scale() || rotate();
}

void ComputedStyle::applyTransform(
    TransformationMatrix& result,
    const LayoutSize& borderBoxSize,
    ApplyTransformOrigin applyOrigin,
    ApplyMotionPath applyMotionPath,
    ApplyIndependentTransformProperties applyIndependentTransformProperties)
    const {
  applyTransform(result, FloatRect(FloatPoint(), FloatSize(borderBoxSize)),
                 applyOrigin, applyMotionPath,
                 applyIndependentTransformProperties);
}

void ComputedStyle::applyTransform(
    TransformationMatrix& result,
    const FloatRect& boundingBox,
    ApplyTransformOrigin applyOrigin,
    ApplyMotionPath applyMotionPath,
    ApplyIndependentTransformProperties applyIndependentTransformProperties)
    const {
  if (!hasOffset())
    applyMotionPath = ExcludeMotionPath;
  bool applyTransformOrigin =
      requireTransformOrigin(applyOrigin, applyMotionPath);

  float originX = 0;
  float originY = 0;
  float originZ = 0;

  const FloatSize& boxSize = boundingBox.size();
  if (applyTransformOrigin ||
      // We need to calculate originX and originY for applying motion path.
      applyMotionPath == IncludeMotionPath) {
    float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
    originX =
        floatValueForLength(transformOriginX(), boxSize.width()) + offsetX;
    float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
    originY =
        floatValueForLength(transformOriginY(), boxSize.height()) + offsetY;
    if (applyTransformOrigin) {
      originZ = transformOriginZ();
      result.translate3d(originX, originY, originZ);
    }
  }

  if (applyIndependentTransformProperties ==
      IncludeIndependentTransformProperties) {
    if (translate())
      translate()->apply(result, boxSize);

    if (rotate())
      rotate()->apply(result, boxSize);

    if (scale())
      scale()->apply(result, boxSize);
  }

  if (applyMotionPath == IncludeMotionPath)
    applyMotionPathTransform(originX, originY, boundingBox, result);

  for (const auto& operation : transform().operations())
    operation->apply(result, boxSize);

  if (applyTransformOrigin) {
    result.translate3d(-originX, -originY, -originZ);
  }
}

void ComputedStyle::applyMotionPathTransform(
    float originX,
    float originY,
    const FloatRect& boundingBox,
    TransformationMatrix& transform) const {
  const StyleMotionData& motionData =
      m_rareNonInheritedData->m_transform->m_motion;
  // TODO(ericwilligers): crbug.com/638055 Apply offset-position.
  if (!motionData.m_path) {
    return;
  }
  const LengthPoint& position = offsetPosition();
  const LengthPoint& anchor = offsetAnchor();
  const StylePath& motionPath = *motionData.m_path;
  float pathLength = motionPath.length();
  float distance = floatValueForLength(motionData.m_distance, pathLength);
  float computedDistance;
  if (motionPath.isClosed() && pathLength > 0) {
    computedDistance = fmod(distance, pathLength);
    if (computedDistance < 0)
      computedDistance += pathLength;
  } else {
    computedDistance = clampTo<float>(distance, 0, pathLength);
  }

  FloatPoint point;
  float angle;
  motionPath.path().pointAndNormalAtLength(computedDistance, point, angle);

  if (motionData.m_rotation.type == OffsetRotationFixed)
    angle = 0;

  float originShiftX = 0;
  float originShiftY = 0;
  // If offset-Position and offset-anchor properties are not yet enabled,
  // they will have the default value, auto.
  if (position.x() != Length(Auto) || anchor.x() != Length(Auto)) {
    // Shift the origin from transform-origin to offset-anchor.
    originShiftX = floatValueForLength(anchor.x(), boundingBox.width()) -
                   floatValueForLength(transformOriginX(), boundingBox.width());
    originShiftY =
        floatValueForLength(anchor.y(), boundingBox.height()) -
        floatValueForLength(transformOriginY(), boundingBox.height());
  }

  transform.translate(point.x() - originX + originShiftX,
                      point.y() - originY + originShiftY);
  transform.rotate(angle + motionData.m_rotation.angle);

  if (position.x() != Length(Auto) || anchor.x() != Length(Auto))
    // Shift the origin back to transform-origin.
    transform.translate(-originShiftX, -originShiftY);
}

void ComputedStyle::setTextShadow(PassRefPtr<ShadowList> s) {
  m_rareInheritedData.access()->textShadow = s;
}

void ComputedStyle::setBoxShadow(PassRefPtr<ShadowList> s) {
  m_rareNonInheritedData.access()->m_boxShadow = s;
}

static FloatRoundedRect::Radii calcRadiiFor(const BorderData& border,
                                            LayoutSize size) {
  return FloatRoundedRect::Radii(
      FloatSize(
          floatValueForLength(border.topLeft().width(), size.width().toFloat()),
          floatValueForLength(border.topLeft().height(),
                              size.height().toFloat())),
      FloatSize(floatValueForLength(border.topRight().width(),
                                    size.width().toFloat()),
                floatValueForLength(border.topRight().height(),
                                    size.height().toFloat())),
      FloatSize(floatValueForLength(border.bottomLeft().width(),
                                    size.width().toFloat()),
                floatValueForLength(border.bottomLeft().height(),
                                    size.height().toFloat())),
      FloatSize(floatValueForLength(border.bottomRight().width(),
                                    size.width().toFloat()),
                floatValueForLength(border.bottomRight().height(),
                                    size.height().toFloat())));
}

StyleImage* ComputedStyle::listStyleImage() const {
  return m_rareInheritedData->listStyleImage.get();
}
void ComputedStyle::setListStyleImage(StyleImage* v) {
  if (m_rareInheritedData->listStyleImage != v)
    m_rareInheritedData.access()->listStyleImage = v;
}

Color ComputedStyle::color() const {
  return m_styleInheritedData->color;
}
Color ComputedStyle::visitedLinkColor() const {
  return m_styleInheritedData->visitedLinkColor;
}
void ComputedStyle::setColor(const Color& v) {
  SET_VAR(m_styleInheritedData, color, v);
}
void ComputedStyle::setVisitedLinkColor(const Color& v) {
  SET_VAR(m_styleInheritedData, visitedLinkColor, v);
}

short ComputedStyle::horizontalBorderSpacing() const {
  return m_styleInheritedData->horizontal_border_spacing;
}
short ComputedStyle::verticalBorderSpacing() const {
  return m_styleInheritedData->vertical_border_spacing;
}
void ComputedStyle::setHorizontalBorderSpacing(short v) {
  SET_VAR(m_styleInheritedData, horizontal_border_spacing, v);
}
void ComputedStyle::setVerticalBorderSpacing(short v) {
  SET_VAR(m_styleInheritedData, vertical_border_spacing, v);
}

FloatRoundedRect ComputedStyle::getRoundedBorderFor(
    const LayoutRect& borderRect,
    bool includeLogicalLeftEdge,
    bool includeLogicalRightEdge) const {
  FloatRoundedRect roundedRect(pixelSnappedIntRect(borderRect));
  if (hasBorderRadius()) {
    FloatRoundedRect::Radii radii =
        calcRadiiFor(m_surround->border, borderRect.size());
    roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(),
                                    includeLogicalLeftEdge,
                                    includeLogicalRightEdge);
    roundedRect.constrainRadii();
  }
  return roundedRect;
}

FloatRoundedRect ComputedStyle::getRoundedInnerBorderFor(
    const LayoutRect& borderRect,
    bool includeLogicalLeftEdge,
    bool includeLogicalRightEdge) const {
  bool horizontal = isHorizontalWritingMode();

  int leftWidth =
      (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
  int rightWidth =
      (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
  int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
  int bottomWidth =
      (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;

  return getRoundedInnerBorderFor(
      borderRect,
      LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth),
      includeLogicalLeftEdge, includeLogicalRightEdge);
}

FloatRoundedRect ComputedStyle::getRoundedInnerBorderFor(
    const LayoutRect& borderRect,
    const LayoutRectOutsets& insets,
    bool includeLogicalLeftEdge,
    bool includeLogicalRightEdge) const {
  LayoutRect innerRect(borderRect);
  innerRect.expand(insets);

  FloatRoundedRect roundedRect(pixelSnappedIntRect(innerRect));

  if (hasBorderRadius()) {
    FloatRoundedRect::Radii radii = getRoundedBorderFor(borderRect).getRadii();
    // Insets use negative values.
    radii.shrink(-insets.top().toFloat(), -insets.bottom().toFloat(),
                 -insets.left().toFloat(), -insets.right().toFloat());
    roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(),
                                    includeLogicalLeftEdge,
                                    includeLogicalRightEdge);
  }
  return roundedRect;
}

static bool allLayersAreFixed(const FillLayer& layer) {
  for (const FillLayer* currLayer = &layer; currLayer;
       currLayer = currLayer->next()) {
    if (!currLayer->image() ||
        currLayer->attachment() != FixedBackgroundAttachment)
      return false;
  }

  return true;
}

bool ComputedStyle::hasEntirelyFixedBackground() const {
  return allLayersAreFixed(backgroundLayers());
}

const CounterDirectiveMap* ComputedStyle::counterDirectives() const {
  return m_rareNonInheritedData->m_counterDirectives.get();
}

CounterDirectiveMap& ComputedStyle::accessCounterDirectives() {
  std::unique_ptr<CounterDirectiveMap>& map =
      m_rareNonInheritedData.access()->m_counterDirectives;
  if (!map)
    map = WTF::wrapUnique(new CounterDirectiveMap);
  return *map;
}

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

void ComputedStyle::clearIncrementDirectives() {
  if (!counterDirectives())
    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 (!counterDirectives())
    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() == HyphensAuto
             ? getFontDescription().localeOrDefault().getHyphenation()
             : nullptr;
}

const AtomicString& ComputedStyle::hyphenString() const {
  const AtomicString& hyphenationString =
      m_rareInheritedData.get()->hyphenationString;
  if (!hyphenationString.isNull())
    return hyphenationString;

  // FIXME: This should depend on locale.
  DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString,
                      (&hyphenMinusCharacter, 1));
  DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphenCharacter, 1));
  const SimpleFontData* primaryFont = font().primaryFont();
  DCHECK(primaryFont);
  return primaryFont && primaryFont->glyphForCharacter(hyphenCharacter)
             ? hyphenString
             : hyphenMinusString;
}

const AtomicString& ComputedStyle::textEmphasisMarkString() const {
  switch (getTextEmphasisMark()) {
    case TextEmphasisMarkNone:
      return nullAtom;
    case TextEmphasisMarkCustom:
      return textEmphasisCustomMark();
    case TextEmphasisMarkDot: {
      DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bulletCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, openDotString,
                          (&whiteBulletCharacter, 1));
      return getTextEmphasisFill() == TextEmphasisFillFilled ? filledDotString
                                                             : openDotString;
    }
    case TextEmphasisMarkCircle: {
      DEFINE_STATIC_LOCAL(AtomicString, filledCircleString,
                          (&blackCircleCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, openCircleString,
                          (&whiteCircleCharacter, 1));
      return getTextEmphasisFill() == TextEmphasisFillFilled
                 ? filledCircleString
                 : openCircleString;
    }
    case TextEmphasisMarkDoubleCircle: {
      DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString,
                          (&fisheyeCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString,
                          (&bullseyeCharacter, 1));
      return getTextEmphasisFill() == TextEmphasisFillFilled
                 ? filledDoubleCircleString
                 : openDoubleCircleString;
    }
    case TextEmphasisMarkTriangle: {
      DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString,
                          (&blackUpPointingTriangleCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, openTriangleString,
                          (&whiteUpPointingTriangleCharacter, 1));
      return getTextEmphasisFill() == TextEmphasisFillFilled
                 ? filledTriangleString
                 : openTriangleString;
    }
    case TextEmphasisMarkSesame: {
      DEFINE_STATIC_LOCAL(AtomicString, filledSesameString,
                          (&sesameDotCharacter, 1));
      DEFINE_STATIC_LOCAL(AtomicString, openSesameString,
                          (&whiteSesameDotCharacter, 1));
      return getTextEmphasisFill() == TextEmphasisFillFilled
                 ? filledSesameString
                 : openSesameString;
    }
    case TextEmphasisMarkAuto:
      ASSERT_NOT_REACHED();
      return nullAtom;
  }

  ASSERT_NOT_REACHED();
  return nullAtom;
}

CSSAnimationData& ComputedStyle::accessAnimations() {
  if (!m_rareNonInheritedData.access()->m_animations)
    m_rareNonInheritedData.access()->m_animations = CSSAnimationData::create();
  return *m_rareNonInheritedData->m_animations;
}

CSSTransitionData& ComputedStyle::accessTransitions() {
  if (!m_rareNonInheritedData.access()->m_transitions)
    m_rareNonInheritedData.access()->m_transitions =
        CSSTransitionData::create();
  return *m_rareNonInheritedData->m_transitions;
}

const Font& ComputedStyle::font() const {
  return m_styleInheritedData->font;
}
const FontDescription& ComputedStyle::getFontDescription() const {
  return m_styleInheritedData->font.getFontDescription();
}
float ComputedStyle::specifiedFontSize() const {
  return getFontDescription().specifiedSize();
}
float ComputedStyle::computedFontSize() const {
  return 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::fontWeight() const {
  return getFontDescription().weight();
}
FontStretch ComputedStyle::fontStretch() const {
  return getFontDescription().stretch();
}

TextDecoration ComputedStyle::textDecorationsInEffect() const {
  if (m_inheritedData.m_hasSimpleUnderline)
    return TextDecorationUnderline;
  if (!m_rareInheritedData->appliedTextDecorations)
    return TextDecorationNone;

  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 (m_inheritedData.m_hasSimpleUnderline) {
    DEFINE_STATIC_LOCAL(
        Vector<AppliedTextDecoration>, underline,
        (1, AppliedTextDecoration(
                TextDecorationUnderline, TextDecorationStyleSolid,
                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 (!m_rareInheritedData->appliedTextDecorations) {
    DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ());
    return empty;
  }

  return m_rareInheritedData->appliedTextDecorations->vector();
}

StyleInheritedVariables* ComputedStyle::inheritedVariables() const {
  return m_rareInheritedData->variables.get();
}

StyleNonInheritedVariables* ComputedStyle::nonInheritedVariables() const {
  return m_rareNonInheritedData->m_variables.get();
}

StyleInheritedVariables& ComputedStyle::mutableInheritedVariables() {
  RefPtr<StyleInheritedVariables>& variables =
      m_rareInheritedData.access()->variables;
  if (!variables)
    variables = StyleInheritedVariables::create();
  else if (!variables->hasOneRef())
    variables = variables->copy();
  return *variables;
}

StyleNonInheritedVariables& ComputedStyle::mutableNonInheritedVariables() {
  std::unique_ptr<StyleNonInheritedVariables>& variables =
      m_rareNonInheritedData.access()->m_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* parsedValue) {
  DCHECK(!!value == !!parsedValue);
  DCHECK(!(value && value->needsVariableResolution()));

  StyleInheritedVariables& variables = mutableInheritedVariables();
  variables.setVariable(name, std::move(value));
  variables.setRegisteredVariable(name, parsedValue);
}

void ComputedStyle::setResolvedNonInheritedVariable(
    const AtomicString& name,
    PassRefPtr<CSSVariableData> value,
    const CSSValue* parsedValue) {
  DCHECK(!!value == !!parsedValue);
  DCHECK(!(value && value->needsVariableResolution()));

  StyleNonInheritedVariables& variables = mutableNonInheritedVariables();
  variables.setVariable(name, std::move(value));
  variables.setRegisteredVariable(name, parsedValue);
}

void ComputedStyle::removeInheritedVariable(const AtomicString& name) {
  mutableInheritedVariables().removeVariable(name);
}

void ComputedStyle::removeNonInheritedVariable(const AtomicString& name) {
  mutableNonInheritedVariables().removeVariable(name);
}

CSSVariableData* ComputedStyle::getVariable(const AtomicString& name) const {
  if (inheritedVariables()) {
    if (CSSVariableData* variable = inheritedVariables()->getVariable(name))
      return variable;
  }
  if (nonInheritedVariables()) {
    if (CSSVariableData* variable = nonInheritedVariables()->getVariable(name))
      return variable;
  }
  return nullptr;
}

float ComputedStyle::wordSpacing() const {
  return getFontDescription().wordSpacing();
}
float ComputedStyle::letterSpacing() const {
  return getFontDescription().letterSpacing();
}

bool ComputedStyle::setFontDescription(const FontDescription& v) {
  if (m_styleInheritedData->font.getFontDescription() != v) {
    m_styleInheritedData.access()->font = Font(v);
    return true;
  }
  return false;
}

void ComputedStyle::setFont(const Font& font) {
  m_styleInheritedData.access()->font = font;
}

bool ComputedStyle::hasIdenticalAscentDescentAndLineGap(
    const ComputedStyle& other) const {
  const SimpleFontData* fontData = font().primaryFont();
  const SimpleFontData* otherFontData = other.font().primaryFont();
  return fontData && otherFontData &&
         fontData->getFontMetrics().hasIdenticalAscentDescentAndLineGap(
             otherFontData->getFontMetrics());
}

const Length& ComputedStyle::specifiedLineHeight() const {
  return m_styleInheritedData->line_height;
}
Length ComputedStyle::lineHeight() const {
  const Length& lh = m_styleInheritedData->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), Fixed);
  }

  return lh;
}

void ComputedStyle::setLineHeight(const Length& specifiedLineHeight) {
  SET_VAR(m_styleInheritedData, line_height, specifiedLineHeight);
}

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() && font().primaryFont())
    return font().primaryFont()->getFontMetrics().lineSpacing();

  if (lh.isPercentOrCalc())
    return minimumValueForLength(lh, LayoutUnit(computedFontSize())).toInt();

  return std::min(lh.value(), LayoutUnit::max().toFloat());
}

void ComputedStyle::setWordSpacing(float wordSpacing) {
  FontSelector* currentFontSelector = font().getFontSelector();
  FontDescription desc(getFontDescription());
  desc.setWordSpacing(wordSpacing);
  setFontDescription(desc);
  font().update(currentFontSelector);
}

void ComputedStyle::setLetterSpacing(float letterSpacing) {
  FontSelector* currentFontSelector = font().getFontSelector();
  FontDescription desc(getFontDescription());
  desc.setLetterSpacing(letterSpacing);
  setFontDescription(desc);
  font().update(currentFontSelector);
}

void ComputedStyle::setTextAutosizingMultiplier(float multiplier) {
  SET_VAR(m_styleInheritedData, textAutosizingMultiplier, multiplier);

  float size = specifiedFontSize();

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

  FontSelector* currentFontSelector = font().getFontSelector();
  FontDescription desc(getFontDescription());
  desc.setSpecifiedSize(size);
  desc.setComputedSize(size);

  float autosizedFontSize =
      TextAutosizer::computeAutosizedFontSize(size, multiplier);
  desc.setComputedSize(std::min(maximumAllowedFontSize, autosizedFontSize));

  setFontDescription(desc);
  font().update(currentFontSelector);
}

void ComputedStyle::addAppliedTextDecoration(
    const AppliedTextDecoration& decoration) {
  RefPtr<AppliedTextDecorationList>& list =
      m_rareInheritedData.access()->appliedTextDecorations;

  if (!list)
    list = AppliedTextDecorationList::create();
  else if (!list->hasOneRef())
    list = list->copy();

  list->append(decoration);
}

void ComputedStyle::overrideTextDecorationColors(Color overrideColor) {
  RefPtr<AppliedTextDecorationList>& list =
      m_rareInheritedData.access()->appliedTextDecorations;
  DCHECK(list);
  if (!list->hasOneRef())
    list = list->copy();

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

void ComputedStyle::applyTextDecorations(const Color& parentTextDecorationColor,
                                         bool overrideExistingColors) {
  if (getTextDecoration() == TextDecorationNone &&
      !m_inheritedData.m_hasSimpleUnderline &&
      !m_rareInheritedData->appliedTextDecorations)
    return;

  // If there are any color changes or decorations set by this element, stop
  // using m_hasSimpleUnderline.
  Color currentTextDecorationColor =
      visitedDependentColor(CSSPropertyTextDecorationColor);
  if (m_inheritedData.m_hasSimpleUnderline &&
      (getTextDecoration() != TextDecorationNone ||
       currentTextDecorationColor != parentTextDecorationColor)) {
    m_inheritedData.m_hasSimpleUnderline = false;
    addAppliedTextDecoration(AppliedTextDecoration(TextDecorationUnderline,
                                                   TextDecorationStyleSolid,
                                                   parentTextDecorationColor));
  }
  if (overrideExistingColors && m_rareInheritedData->appliedTextDecorations)
    overrideTextDecorationColors(currentTextDecorationColor);
  if (getTextDecoration() == TextDecorationNone)
    return;
  DCHECK(!m_inheritedData.m_hasSimpleUnderline);
  // To save memory, we don't use AppliedTextDecoration objects in the common
  // case of a single simple underline of currentColor.
  TextDecoration decorationLines = getTextDecoration();
  TextDecorationStyle decorationStyle = getTextDecorationStyle();
  bool isSimpleUnderline = decorationLines == TextDecorationUnderline &&
                           decorationStyle == TextDecorationStyleSolid &&
                           textDecorationColor().isCurrentColor();
  if (isSimpleUnderline && !m_rareInheritedData->appliedTextDecorations) {
    m_inheritedData.m_hasSimpleUnderline = true;
    return;
  }

  addAppliedTextDecoration(AppliedTextDecoration(
      decorationLines, decorationStyle, currentTextDecorationColor));
}

void ComputedStyle::clearAppliedTextDecorations() {
  m_inheritedData.m_hasSimpleUnderline = false;

  if (m_rareInheritedData->appliedTextDecorations)
    m_rareInheritedData.access()->appliedTextDecorations = nullptr;
}

void ComputedStyle::restoreParentTextDecorations(
    const ComputedStyle& parentStyle) {
  m_inheritedData.m_hasSimpleUnderline =
      parentStyle.m_inheritedData.m_hasSimpleUnderline;
  if (m_rareInheritedData->appliedTextDecorations !=
      parentStyle.m_rareInheritedData->appliedTextDecorations)
    m_rareInheritedData.access()->appliedTextDecorations =
        parentStyle.m_rareInheritedData->appliedTextDecorations;
}

void ComputedStyle::clearMultiCol() {
  m_rareNonInheritedData.access()->m_multiCol = nullptr;
  m_rareNonInheritedData.access()->m_multiCol.init();
}

StyleColor ComputedStyle::decorationColorIncludingFallback(
    bool visitedLink) const {
  StyleColor styleColor =
      visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();

  if (!styleColor.isCurrentColor())
    return styleColor;

  if (textStrokeWidth()) {
    // Prefer stroke color if possible, but not if it's fully transparent.
    StyleColor textStrokeStyleColor =
        visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
    if (!textStrokeStyleColor.isCurrentColor() &&
        textStrokeStyleColor.getColor().alpha())
      return textStrokeStyleColor;
  }

  return visitedLink ? visitedLinkTextFillColor() : textFillColor();
}

Color ComputedStyle::colorIncludingFallback(int colorProperty,
                                            bool visitedLink) const {
  StyleColor result(StyleColor::currentColor());
  EBorderStyle borderStyle = BorderStyleNone;
  switch (colorProperty) {
    case CSSPropertyBackgroundColor:
      result = visitedLink ? visitedLinkBackgroundColor() : backgroundColor();
      break;
    case CSSPropertyBorderLeftColor:
      result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
      borderStyle = borderLeftStyle();
      break;
    case CSSPropertyBorderRightColor:
      result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
      borderStyle = borderRightStyle();
      break;
    case CSSPropertyBorderTopColor:
      result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
      borderStyle = borderTopStyle();
      break;
    case CSSPropertyBorderBottomColor:
      result =
          visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
      borderStyle = borderBottomStyle();
      break;
    case CSSPropertyCaretColor: {
      StyleAutoColor autoColor =
          visitedLink ? 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 = autoColor.toStyleColor();
      break;
    }
    case CSSPropertyColor:
      result = visitedLink ? visitedLinkColor() : color();
      break;
    case CSSPropertyOutlineColor:
      result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
      break;
    case CSSPropertyColumnRuleColor:
      result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
      break;
    case CSSPropertyWebkitTextEmphasisColor:
      result =
          visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
      break;
    case CSSPropertyWebkitTextFillColor:
      result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
      break;
    case CSSPropertyWebkitTextStrokeColor:
      result = visitedLink ? 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(visitedLink);
      break;
    default:
      ASSERT_NOT_REACHED();
      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 (!visitedLink &&
      (borderStyle == BorderStyleInset || borderStyle == BorderStyleOutset ||
       borderStyle == BorderStyleRidge || borderStyle == BorderStyleGroove))
    return Color(238, 238, 238);
  return visitedLink ? visitedLinkColor() : color();
}

Color ComputedStyle::visitedDependentColor(int colorProperty) const {
  Color unvisitedColor = colorIncludingFallback(colorProperty, false);
  if (insideLink() != InsideVisitedLink)
    return unvisitedColor;

  Color visitedColor = colorIncludingFallback(colorProperty, 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 (colorProperty == CSSPropertyBackgroundColor &&
      visitedColor == Color::transparent)
    return unvisitedColor;

  // Take the alpha from the unvisited color, but get the RGB values from the
  // visited color.
  return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(),
               unvisitedColor.alpha());
}

const BorderValue& ComputedStyle::borderBefore() const {
  switch (getWritingMode()) {
    case TopToBottomWritingMode:
      return borderTop();
    case LeftToRightWritingMode:
      return borderLeft();
    case RightToLeftWritingMode:
      return borderRight();
  }
  ASSERT_NOT_REACHED();
  return borderTop();
}

const BorderValue& ComputedStyle::borderAfter() const {
  switch (getWritingMode()) {
    case TopToBottomWritingMode:
      return borderBottom();
    case LeftToRightWritingMode:
      return borderRight();
    case RightToLeftWritingMode:
      return borderLeft();
  }
  ASSERT_NOT_REACHED();
  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();
}

int ComputedStyle::borderBeforeWidth() const {
  switch (getWritingMode()) {
    case TopToBottomWritingMode:
      return borderTopWidth();
    case LeftToRightWritingMode:
      return borderLeftWidth();
    case RightToLeftWritingMode:
      return borderRightWidth();
  }
  ASSERT_NOT_REACHED();
  return borderTopWidth();
}

int ComputedStyle::borderAfterWidth() const {
  switch (getWritingMode()) {
    case TopToBottomWritingMode:
      return borderBottomWidth();
    case LeftToRightWritingMode:
      return borderRightWidth();
    case RightToLeftWritingMode:
      return borderLeftWidth();
  }
  ASSERT_NOT_REACHED();
  return borderBottomWidth();
}

int ComputedStyle::borderStartWidth() const {
  if (isHorizontalWritingMode())
    return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
  return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
}

int ComputedStyle::borderEndWidth() const {
  if (isHorizontalWritingMode())
    return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
  return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
}

int ComputedStyle::borderOverWidth() const {
  return isHorizontalWritingMode() ? borderTopWidth() : borderRightWidth();
}

int 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) {
  m_rareNonInheritedData.access()->m_transform.access()->m_motion.m_path = 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* otherStyle) const {
  return columnRuleStyle() == otherStyle->columnRuleStyle() &&
         columnRuleWidth() == otherStyle->columnRuleWidth() &&
         visitedDependentColor(CSSPropertyColumnRuleColor) ==
             otherStyle->visitedDependentColor(CSSPropertyColumnRuleColor);
}

TextEmphasisMark ComputedStyle::getTextEmphasisMark() const {
  TextEmphasisMark mark =
      static_cast<TextEmphasisMark>(m_rareInheritedData->textEmphasisMark);
  if (mark != TextEmphasisMarkAuto)
    return mark;

  if (isHorizontalWritingMode())
    return TextEmphasisMarkDot;

  return TextEmphasisMarkSesame;
}

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 (m_surround->border.m_image.image() == image)
    return;
  m_surround.access()->border.m_image.setImage(image);
}

void ComputedStyle::setBorderImageSlices(const LengthBox& slices) {
  if (m_surround->border.m_image.imageSlices() == slices)
    return;
  m_surround.access()->border.m_image.setImageSlices(slices);
}

void ComputedStyle::setBorderImageSlicesFill(bool fill) {
  if (m_surround->border.m_image.fill() == fill)
    return;
  m_surround.access()->border.m_image.setFill(fill);
}

void ComputedStyle::setBorderImageWidth(const BorderImageLengthBox& slices) {
  if (m_surround->border.m_image.borderSlices() == slices)
    return;
  m_surround.access()->border.m_image.setBorderSlices(slices);
}

void ComputedStyle::setBorderImageOutset(const BorderImageLengthBox& outset) {
  if (m_surround->border.m_image.outset() == outset)
    return;
  m_surround.access()->border.m_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().image())
    return false;

  BorderEdge edges[4];
  getBorderEdgeInfo(edges);

  for (int i = BSTop; i <= BSLeft; ++i) {
    const BorderEdge& currEdge = edges[i];
    if (!currEdge.obscuresBackground())
      return false;
  }

  return true;
}

void ComputedStyle::getBorderEdgeInfo(BorderEdge edges[],
                                      bool includeLogicalLeftEdge,
                                      bool includeLogicalRightEdge) const {
  bool horizontal = isHorizontalWritingMode();

  edges[BSTop] = BorderEdge(
      borderTopWidth(), visitedDependentColor(CSSPropertyBorderTopColor),
      borderTopStyle(), horizontal || includeLogicalLeftEdge);

  edges[BSRight] = BorderEdge(
      borderRightWidth(), visitedDependentColor(CSSPropertyBorderRightColor),
      borderRightStyle(), !horizontal || includeLogicalRightEdge);

  edges[BSBottom] = BorderEdge(
      borderBottomWidth(), visitedDependentColor(CSSPropertyBorderBottomColor),
      borderBottomStyle(), horizontal || includeLogicalRightEdge);

  edges[BSLeft] = BorderEdge(
      borderLeftWidth(), visitedDependentColor(CSSPropertyBorderLeftColor),
      borderLeftStyle(), !horizontal || includeLogicalLeftEdge);
}

void ComputedStyle::copyChildDependentFlagsFrom(const ComputedStyle& other) {
  setEmptyState(other.emptyState());
  if (other.hasExplicitlyInheritedProperties())
    setHasExplicitlyInheritedProperties();
}

bool ComputedStyle::shadowListHasCurrentColor(const ShadowList* shadowList) {
  if (!shadowList)
    return false;
  for (size_t i = shadowList->shadows().size(); i--;) {
    if (shadowList->shadows()[i].color().isCurrentColor())
      return true;
  }
  return false;
}

static inline Vector<GridTrackSize> initialGridAutoTracks() {
  Vector<GridTrackSize> trackSizeList;
  trackSizeList.reserveInitialCapacity(1);
  trackSizeList.uncheckedAppend(GridTrackSize(Length(Auto)));
  return trackSizeList;
}

Vector<GridTrackSize> ComputedStyle::initialGridAutoColumns() {
  return initialGridAutoTracks();
}

Vector<GridTrackSize> ComputedStyle::initialGridAutoRows() {
  return initialGridAutoTracks();
}

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

  return roundForImpreciseConversion<int>(fvalue / zoomFactor);
}

}  // namespace blink
