/*
 * 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_bitfield;
};

ASSERT_SIZE(BorderValue, SameSizeAsBorderValue);

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

  void* dataRefs[7];
  void* ownPtrs[1];
  void* dataRefSvgStyle;

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

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

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

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

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

PassRefPtr<ComputedStyle> ComputedStyle::createAnonymousStyleWithDisplay(
    const ComputedStyle& 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.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_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;
  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.
  setOriginalDisplay(
      other.originalDisplay());  // Not generated in ComputedStyleBase.
  setVerticalAlign(
      other.verticalAlign());  // Not generated in ComputedStyleBase
  m_nonInheritedData.m_hasViewportUnits =
      other.m_nonInheritedData.m_hasViewportUnits;
  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.unique());

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

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

  DCHECK_GT(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->erase(i);
      return;
    }
  }
}

bool ComputedStyle::inheritedEqual(const ComputedStyle& other) const {
  return independentInheritedEqual(other) &&
         nonIndependentInheritedEqual(other);
}

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

bool ComputedStyle::nonIndependentInheritedEqual(
    const ComputedStyle& other) const {
  return ComputedStyleBase::nonIndependentInheritedEqual(other) &&
         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) &&
         originalDisplay() ==
             other.originalDisplay() &&  // Not generated in ComputedStyleBase
         verticalAlign() ==
             other.verticalAlign() &&  // Not generated in ComputedStyleBase
         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_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.needsFullPaintInvalidation()) &&
      diffNeedsFullLayoutAndPaintInvalidation(other)) {
    diff.setNeedsFullLayout();
    diff.setNeedsPaintInvalidationObject();
  }

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

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

  if (!diff.needsFullLayout() && position() != EPosition::kStatic &&
      !offsetEqual(other)) {
    // Optimize for the case where a positioned layer is moving but not changing
    // size.
    if (dependenceOnContentHeightHasChanged(*this, other))
      diff.setNeedsFullLayout();
    else
      diff.setNeedsPositionedMovementLayout();
  }

  if (diffNeedsPaintInvalidationSubtree(other))
    diff.setNeedsPaintInvalidationSubtree();
  else if (diffNeedsPaintInvalidationObject(other))
    diff.setNeedsPaintInvalidationObject();

  if (diffNeedsVisualRectUpdate(other))
    diff.setNeedsVisualRectUpdate();

  updatePropertySpecificDifferences(other, diff);

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

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

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

  return diff;
}

bool ComputedStyle::scrollAnchorDisablingPropertyChanged(
    const ComputedStyle& other,
    const StyleDifference& diff) const {
  if (position() != other.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->m_margin != other.m_surround->m_margin ||
        !offsetEqual(other) ||
        m_surround->m_padding != other.m_surround->m_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_surround->m_padding != other.m_surround->m_padding)
      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_lineHeightStep !=
            other.m_rareInheritedData->m_lineHeightStep ||
        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 (overflowX() != other.overflowX() || overflowY() != other.overflowY() ||
      clear() != other.clear() || getUnicodeBidi() != other.getUnicodeBidi() ||
      floating() != other.floating() ||
      originalDisplay() != other.originalDisplay())
    return true;

  if (isDisplayTableType(display())) {
    if (borderCollapse() != other.borderCollapse() ||
        emptyCells() != other.emptyCells() ||
        captionSide() != other.captionSide() ||
        tableLayout() != other.tableLayout())
      return true;

    // In the collapsing border model, 'hidden' suppresses other borders, while
    // 'none' does not, so these style differences can be width differences.
    if ((borderCollapse() == EBorderCollapse::kCollapse) &&
        ((borderTopStyle() == 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::kListItem) {
    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 (verticalAlign() != other.verticalAlign() ||
      position() != other.position())
    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() ||
      insideLink() != other.insideLink() ||
      !m_surround->m_border.visuallyEqual(other.m_surround->m_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;
}

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

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

  return false;
}

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

  if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
    // It's possible for the old and new style transform data to be equivalent
    // while hasTransform() differs, as it checks a number of conditions aside
    // from just the matrix, including but not limited to animation state.
    if (hasTransform() != other.hasTransform() ||
        !transformDataEquivalent(other) ||
        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->m_border.visualOverflowEqual(other.m_surround->m_border))
    diff.setNeedsRecomputeOverflow();

  if (!diff.needsFullPaintInvalidation()) {
    if (m_styleInheritedData->color != other.m_styleInheritedData->color ||
        m_styleInheritedData->visitedLinkColor !=
            other.m_styleInheritedData->visitedLinkColor ||
        m_hasSimpleUnderline != other.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 = std::move(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:
      case CSSPropertyOffsetPath:
      case CSSPropertyOffsetPosition:
        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) {
    originX = floatValueForLength(transformOriginX(), boxSize.width()) +
              boundingBox.x();
    originY = floatValueForLength(transformOriginY(), boxSize.height()) +
              boundingBox.y();
    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 = std::move(s);
}

void ComputedStyle::setBoxShadow(PassRefPtr<ShadowList> s) {
  m_rareNonInheritedData.access()->m_boxShadow = std::move(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->m_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) ? roundf(borderLeftWidth()) : 0;
  int rightWidth =
      (!horizontal || includeLogicalRightEdge) ? roundf(borderRightWidth()) : 0;
  int topWidth =
      (horizontal || includeLogicalLeftEdge) ? roundf(borderTopWidth()) : 0;
  int bottomWidth =
      (horizontal || includeLogicalRightEdge) ? roundf(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);
  LayoutSize innerRectSize = innerRect.size();
  innerRectSize.clampNegativeToZero();
  innerRect.setSize(innerRectSize);

  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->at(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:
      NOTREACHED();
      return nullAtom;
  }

  NOTREACHED();
  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();
}
LayoutUnit ComputedStyle::computedFontSizeAsFixed() const {
  return LayoutUnit::fromFloatRound(getFontDescription().computedSize());
}
int ComputedStyle::fontSize() const {
  return getFontDescription().computedPixelSize();
}
float ComputedStyle::fontSizeAdjust() const {
  return getFontDescription().sizeAdjust();
}
bool ComputedStyle::hasFontSizeAdjust() const {
  return getFontDescription().hasSizeAdjust();
}
FontWeight ComputedStyle::fontWeight() const {
  return getFontDescription().weight();
}
FontStretch ComputedStyle::fontStretch() const {
  return getFontDescription().stretch();
}

TextDecoration ComputedStyle::textDecorationsInEffect() const {
  if (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_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;
}

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

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

bool ComputedStyle::setFontDescription(const FontDescription& v) {
  if (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());
}

LayoutUnit ComputedStyle::computedLineHeightAsFixed() const {
  const Length& lh = lineHeight();

  // Negative value means the line height is not set. Use the font's built-in
  // spacing, if avalible.
  if (lh.isNegative() && font().primaryFont())
    return font().primaryFont()->getFontMetrics().fixedLineSpacing();

  if (lh.isPercentOrCalc())
    return minimumValueForLength(lh, computedFontSizeAsFixed());

  return LayoutUnit::fromFloatRound(lh.value());
}

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();

  DCHECK(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->push_back(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_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_hasSimpleUnderline &&
      (getTextDecoration() != TextDecorationNone ||
       currentTextDecorationColor != parentTextDecorationColor)) {
    m_hasSimpleUnderline = false;
    addAppliedTextDecoration(AppliedTextDecoration(TextDecorationUnderline,
                                                   TextDecorationStyleSolid,
                                                   parentTextDecorationColor));
  }
  if (overrideExistingColors && m_rareInheritedData->appliedTextDecorations)
    overrideTextDecorationColors(currentTextDecorationColor);
  if (getTextDecoration() == TextDecorationNone)
    return;
  DCHECK(!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_hasSimpleUnderline = true;
    return;
  }

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

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

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

void ComputedStyle::restoreParentTextDecorations(
    const ComputedStyle& parentStyle) {
  m_hasSimpleUnderline = parentStyle.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:
      NOTREACHED();
      break;
  }

  if (!result.isCurrentColor())
    return result.getColor();

  // FIXME: Treating styled borders with initial color differently causes
  // problems, see crbug.com/316559, crbug.com/276231
  if (!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();
  }
  NOTREACHED();
  return borderTop();
}

const BorderValue& ComputedStyle::borderAfter() const {
  switch (getWritingMode()) {
    case WritingMode::kHorizontalTb:
      return borderBottom();
    case WritingMode::kVerticalLr:
      return borderRight();
    case WritingMode::kVerticalRl:
      return borderLeft();
  }
  NOTREACHED();
  return borderBottom();
}

const BorderValue& ComputedStyle::borderStart() const {
  if (isHorizontalWritingMode())
    return isLeftToRightDirection() ? borderLeft() : borderRight();
  return isLeftToRightDirection() ? borderTop() : borderBottom();
}

const BorderValue& ComputedStyle::borderEnd() const {
  if (isHorizontalWritingMode())
    return isLeftToRightDirection() ? borderRight() : borderLeft();
  return isLeftToRightDirection() ? borderBottom() : borderTop();
}

float ComputedStyle::borderBeforeWidth() const {
  switch (getWritingMode()) {
    case WritingMode::kHorizontalTb:
      return borderTopWidth();
    case WritingMode::kVerticalLr:
      return borderLeftWidth();
    case WritingMode::kVerticalRl:
      return borderRightWidth();
  }
  NOTREACHED();
  return borderTopWidth();
}

float ComputedStyle::borderAfterWidth() const {
  switch (getWritingMode()) {
    case WritingMode::kHorizontalTb:
      return borderBottomWidth();
    case WritingMode::kVerticalLr:
      return borderRightWidth();
    case WritingMode::kVerticalRl:
      return borderLeftWidth();
  }
  NOTREACHED();
  return borderBottomWidth();
}

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

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

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

float ComputedStyle::borderUnderWidth() const {
  return isHorizontalWritingMode() ? borderBottomWidth() : borderLeftWidth();
}

void ComputedStyle::setMarginStart(const Length& margin) {
  if (isHorizontalWritingMode()) {
    if (isLeftToRightDirection())
      setMarginLeft(margin);
    else
      setMarginRight(margin);
  } else {
    if (isLeftToRightDirection())
      setMarginTop(margin);
    else
      setMarginBottom(margin);
  }
}

void ComputedStyle::setMarginEnd(const Length& margin) {
  if (isHorizontalWritingMode()) {
    if (isLeftToRightDirection())
      setMarginRight(margin);
    else
      setMarginLeft(margin);
  } else {
    if (isLeftToRightDirection())
      setMarginBottom(margin);
    else
      setMarginTop(margin);
  }
}

void ComputedStyle::setOffsetPath(PassRefPtr<StylePath> path) {
  m_rareNonInheritedData.access()->m_transform.access()->m_motion.m_path =
      std::move(path);
}

int ComputedStyle::outlineOutsetExtent() const {
  if (!hasOutline())
    return 0;
  if (outlineStyleIsAuto()) {
    return GraphicsContext::focusRingOutsetExtent(
        outlineOffset(), std::ceil(getOutlineStrokeWidthForFocusRing()));
  }
  return std::max(0, SaturatedAddition(outlineWidth(), outlineOffset()));
}

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

bool ComputedStyle::columnRuleEquivalent(
    const ComputedStyle* 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->m_border.m_image.image() == image)
    return;
  m_surround.access()->m_border.m_image.setImage(image);
}

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

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

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

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