/*
 * 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[2];
  } 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->setUnicodeBidi(parentStyle.getUnicodeBidi());
  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_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_position = other.m_nonInheritedData.m_position;
  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->push_back(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() ||
      rtlOrdering() != other.rtlOrdering() ||
      textAlign() != other.textAlign() ||
      textTransform() != other.textTransform() ||
      direction() != other.direction() || whiteSpace() != other.whiteSpace() ||
      getWritingMode() != other.getWritingMode())
    return true;

  if (m_nonInheritedData.m_overflowX != other.m_nonInheritedData.m_overflowX ||
      m_nonInheritedData.m_overflowY != other.m_nonInheritedData.m_overflowY ||
      clear() != other.clear() || getUnicodeBidi() != other.getUnicodeBidi() ||
      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() ||
        tableLayout() != other.tableLayout())
      return true;

    // In the collapsing border model, 'hidden' suppresses other borders, while
    // 'none' does not, so these style differences can be width differences.
    if ((borderCollapse() == EBorderCollapse::kCollapse) &&
        ((borderTopStyle() == 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 (listStyleType() != other.listStyleType() ||
        listStylePosition() != other.listStylePosition())
      return true;
  }

  if ((visibility() == EVisibility::kCollapse) !=
      (other.visibility() == EVisibility::kCollapse))
    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) ||
        m_rareNonInheritedData->m_perspective !=
            other.m_rareNonInheritedData->m_perspective ||
        m_rareNonInheritedData->m_perspectiveOrigin !=
            other.m_rareNonInheritedData->m_perspectiveOrigin)
      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->push_back(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->push_back(
      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.push_back(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::removeVariable(const AtomicString& name,
                                   bool isInheritedProperty) {
  if (isInheritedProperty) {
    mutableInheritedVariables().removeVariable(name);
  } else {
    mutableNonInheritedVariables().removeVariable(name);
  }
}

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

CSSVariableData* ComputedStyle::getVariable(const AtomicString& name,
                                            bool isInheritedProperty) const {
  if (isInheritedProperty) {
    return inheritedVariables() ? inheritedVariables()->getVariable(name)
                                : nullptr;
  }
  return nonInheritedVariables() ? nonInheritedVariables()->getVariable(name)
                                 : nullptr;
}

const CSSValue* ComputedStyle::getRegisteredVariable(
    const AtomicString& name,
    bool isInheritedProperty) const {
  if (isInheritedProperty) {
    return inheritedVariables() ? inheritedVariables()->registeredVariable(name)
                                : nullptr;
  }
  return nonInheritedVariables()
             ? nonInheritedVariables()->registeredVariable(name)
             : 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.isAutoColor() ? StyleColor::currentColor()
                                       : 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() != EInsideLink::kInsideVisitedLink)
    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 WritingMode::kHorizontalTb:
      return borderTop();
    case WritingMode::kVerticalLr:
      return borderLeft();
    case WritingMode::kVerticalRl:
      return borderRight();
  }
  ASSERT_NOT_REACHED();
  return borderTop();
}

const BorderValue& ComputedStyle::borderAfter() const {
  switch (getWritingMode()) {
    case WritingMode::kHorizontalTb:
      return borderBottom();
    case WritingMode::kVerticalLr:
      return borderRight();
    case WritingMode::kVerticalRl:
      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 WritingMode::kHorizontalTb:
      return borderTopWidth();
    case WritingMode::kVerticalLr:
      return borderLeftWidth();
    case WritingMode::kVerticalRl:
      return borderRightWidth();
  }
  ASSERT_NOT_REACHED();
  return borderTopWidth();
}

int ComputedStyle::borderAfterWidth() const {
  switch (getWritingMode()) {
    case WritingMode::kHorizontalTb:
      return borderBottomWidth();
    case WritingMode::kVerticalLr:
      return borderRightWidth();
    case WritingMode::kVerticalRl:
      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
