/*
 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
 *           (C) 2000 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
 * rights reserved.
 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
 *
 * 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.
 *
 */

#ifndef ComputedStyle_h
#define ComputedStyle_h

#include <memory>
#include "core/CSSPropertyNames.h"
#include "core/ComputedStyleBase.h"
#include "core/CoreExport.h"
#include "core/css/StyleAutoColor.h"
#include "core/css/StyleColor.h"
#include "core/layout/LayoutTheme.h"
#include "core/style/AppliedTextDecoration.h"
#include "core/style/AppliedTextDecorationList.h"
#include "core/style/BorderValue.h"
#include "core/style/ComputedStyleConstants.h"
#include "core/style/ContentData.h"
#include "core/style/CounterDirectives.h"
#include "core/style/CursorData.h"
#include "core/style/CursorList.h"
#include "core/style/DataRef.h"
#include "core/style/LineClampValue.h"
#include "core/style/NinePieceImage.h"
#include "core/style/QuotesData.h"
#include "core/style/SVGComputedStyle.h"
#include "core/style/ShadowData.h"
#include "core/style/ShadowList.h"
#include "core/style/StyleContentAlignmentData.h"
#include "core/style/StyleDifference.h"
#include "core/style/StyleFilterData.h"
#include "core/style/StyleImage.h"
#include "core/style/StyleInheritedVariables.h"
#include "core/style/StyleOffsetRotation.h"
#include "core/style/StyleReflection.h"
#include "core/style/StyleSelfAlignmentData.h"
#include "core/style/TextSizeAdjust.h"
#include "core/style/TransformOrigin.h"
#include "platform/Length.h"
#include "platform/LengthBox.h"
#include "platform/LengthPoint.h"
#include "platform/LengthSize.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/ThemeTypes.h"
#include "platform/fonts/Font.h"
#include "platform/fonts/FontDescription.h"
#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/LayoutRectOutsets.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/TouchAction.h"
#include "platform/heap/Handle.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/text/TabSize.h"
#include "platform/text/TextDirection.h"
#include "platform/text/UnicodeBidi.h"
#include "platform/transforms/TransformOperations.h"
#include "platform/wtf/Forward.h"
#include "platform/wtf/LeakAnnotations.h"
#include "platform/wtf/RefCounted.h"
#include "platform/wtf/RefVector.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/text/AtomicString.h"

template <typename T, typename U>
inline bool compareEqual(const T& t, const U& u) {
  return t == static_cast<T>(u);
}

template <typename T>
inline bool compareEqual(const T& a, const T& b) {
  return a == b;
}

#define SET_VAR(group, variable, value)      \
  if (!compareEqual(group->variable, value)) \
  group.Access()->variable = value

#define SET_NESTED_VAR(group, base, variable, value) \
  if (!compareEqual(group->base->variable, value))   \
  group.Access()->base.Access()->variable = value

#define SET_VAR_WITH_SETTER(group, getter, setter, value) \
  if (!compareEqual(group->getter(), value))              \
  group.Access()->setter(value)

#define SET_BORDERVALUE_COLOR(group, variable, value)   \
  if (!compareEqual(group->variable.GetColor(), value)) \
  group.Access()->variable.SetColor(value)

#define SET_BORDER_WIDTH(group, variable, value) \
  if (!group->variable.WidthEquals(value))       \
  group.Access()->variable.SetWidth(value)

#define SET_NESTED_BORDER_WIDTH(group, base, variable, value) \
  if (!group->base->variable.WidthEquals(value))              \
  group.Access()->base.Access()->variable.SetWidth(value)

namespace blink {

using std::max;

class FilterOperations;

class AppliedTextDecoration;
struct BorderEdge;
class CSSAnimationData;
class CSSTransitionData;
class CSSVariableData;
class Font;
class Hyphenation;
class RotateTransformOperation;
class ScaleTransformOperation;
class ShadowList;
class ShapeValue;
class StyleImage;
class StylePath;
class StyleResolver;
class TransformationMatrix;
class TranslateTransformOperation;

class ContentData;

typedef Vector<RefPtr<ComputedStyle>, 4> PseudoStyleCache;

// ComputedStyle stores the computed value [1] for every CSS property on an
// element and provides the interface between the style engine and the rest of
// Blink. It acts as a container where the computed value of every CSS property
// can be stored and retrieved:
//
//   auto style = ComputedStyle::Create();
//   style->SetDisplay(EDisplay::kNone); //'display' keyword property
//   style->Display();
//
// In addition to storing the computed value of every CSS property,
// ComputedStyle also contains various internal style information. Examples
// include cached_pseudo_styles_ (for storing pseudo element styles), unique_
// (for style sharing) and has_simple_underline_ (cached indicator flag of
// text-decoration). These are stored on ComputedStyle for two reasons:
//
//  1) They share the same lifetime as ComputedStyle, so it is convenient to
//  store them in the same object rather than a separate object that have to be
//  passed around as well.
//
//  2) Many of these data members can be packed as bit fields, so we use less
//  memory by packing them in this object with other bit fields.
//
// STORAGE:
//
// ComputedStyle is optimized for memory and performance. The data is not
// actually stored directly in ComputedStyle, but rather in a generated parent
// class ComputedStyleBase. This separation of concerns allows us to optimise
// the memory layout without affecting users of ComputedStyle. ComputedStyle
// inherits from ComputedStyleBase. For more about the memory layout, there is
// documentation in ComputedStyleBase and make_computed_style_base.py.
//
// INTERFACE:
//
// For most CSS properties, ComputedStyle provides a consistent interface which
// includes a getter, setter, initial method (the computed value when the
// property is to 'initial'), and resetter (that resets the computed value to
// its initial value). Exceptions include vertical-align, which has a separate
// set of accessors for its length and its keyword components. Apart from
// accessors, ComputedStyle also has a wealth of helper functions.
//
// Because ComputedStyleBase defines simple accessors to every CSS property,
// ComputedStyle inherits these and so they are not redeclared in this file.
// This means that the interface to ComputedStyle is split between this file and
// ComputedStyleBase.h.
//
// [1] https://developer.mozilla.org/en-US/docs/Web/CSS/computed_value
//
// NOTE:
//
// Currently, some properties are stored in ComputedStyle and some in
// ComputedStyleBase. Eventually, the storage of all properties (except SVG
// ones) will be in ComputedStyleBase.
class CORE_EXPORT ComputedStyle : public ComputedStyleBase,
                                  public RefCounted<ComputedStyle> {
  // Needed to allow access to private/protected getters of fields to allow diff
  // generation
  friend class ComputedStyleBase;
  // Used by Web Animations CSS. Sets the color styles.
  friend class AnimatedStyleBuilder;
  // Used by Web Animations CSS. Gets visited and unvisited colors separately.
  friend class CSSAnimatableValueFactory;
  // Used by CSS animations. We can't allow them to animate based off visited
  // colors.
  friend class CSSPropertyEquality;
  // Editing has to only reveal unvisited info.
  friend class ApplyStyleCommand;
  // Editing has to only reveal unvisited info.
  friend class EditingStyle;
  // Needs to be able to see visited and unvisited colors for devtools.
  friend class ComputedStyleCSSValueMapping;
  // Sets color styles
  friend class StyleBuilderFunctions;
  // Saves Border/Background information for later comparison.
  friend class CachedUAStyle;
  // Accesses visited and unvisited colors.
  friend class ColorPropertyFunctions;

  // FIXME: When we stop resolving currentColor at style time, these can be
  // removed.
  friend class CSSToStyleMap;
  friend class FilterOperationResolver;
  friend class StyleBuilderConverter;
  friend class StyleResolverState;
  friend class StyleResolver;

 protected:
  // list of associated pseudo styles
  std::unique_ptr<PseudoStyleCache> cached_pseudo_styles_;

  DataRef<SVGComputedStyle> svg_style_;

 private:
  // TODO(sashab): Move these private members to the bottom of ComputedStyle.
  ALWAYS_INLINE ComputedStyle();
  ALWAYS_INLINE ComputedStyle(const ComputedStyle&);

  static RefPtr<ComputedStyle> CreateInitialStyle();
  // TODO(shend): Remove this. Initial style should not be mutable.
  static ComputedStyle& MutableInitialStyle();

 public:
  static RefPtr<ComputedStyle> Create();
  static RefPtr<ComputedStyle> CreateAnonymousStyleWithDisplay(
      const ComputedStyle& parent_style,
      EDisplay);
  static RefPtr<ComputedStyle> Clone(const ComputedStyle&);
  static const ComputedStyle& InitialStyle() { return MutableInitialStyle(); }
  static void InvalidateInitialStyle();

  // Computes how the style change should be propagated down the tree.
  static StyleRecalcChange StylePropagationDiff(const ComputedStyle* old_style,
                                                const ComputedStyle* new_style);

  // Copies the values of any independent inherited properties from the parent
  // that are not explicitly set in this style.
  void PropagateIndependentInheritedProperties(
      const ComputedStyle& parent_style);

  ContentPosition ResolvedJustifyContentPosition(
      const StyleContentAlignmentData& normal_value_behavior) const;
  ContentDistributionType ResolvedJustifyContentDistribution(
      const StyleContentAlignmentData& normal_value_behavior) const;
  ContentPosition ResolvedAlignContentPosition(
      const StyleContentAlignmentData& normal_value_behavior) const;
  ContentDistributionType ResolvedAlignContentDistribution(
      const StyleContentAlignmentData& normal_value_behavior) const;
  StyleSelfAlignmentData ResolvedAlignItems(
      ItemPosition normal_value_behaviour) const;
  StyleSelfAlignmentData ResolvedAlignSelf(
      ItemPosition normal_value_behaviour,
      const ComputedStyle* parent_style = nullptr) const;
  StyleSelfAlignmentData ResolvedJustifyItems(
      ItemPosition normal_value_behaviour) const;
  StyleSelfAlignmentData ResolvedJustifySelf(
      ItemPosition normal_value_behaviour,
      const ComputedStyle* parent_style = nullptr) const;

  StyleDifference VisualInvalidationDiff(const ComputedStyle&) const;

  void InheritFrom(const ComputedStyle& inherit_parent,
                   IsAtShadowBoundary = kNotAtShadowBoundary);
  void CopyNonInheritedFromCached(const ComputedStyle&);

  PseudoId StyleType() const { return StyleTypeInternal(); }
  void SetStyleType(PseudoId style_type) { SetStyleTypeInternal(style_type); }

  ComputedStyle* GetCachedPseudoStyle(PseudoId) const;
  ComputedStyle* AddCachedPseudoStyle(RefPtr<ComputedStyle>);
  void RemoveCachedPseudoStyle(PseudoId);

  const PseudoStyleCache* CachedPseudoStyles() const {
    return cached_pseudo_styles_.get();
  }

  /**
     * ComputedStyle properties
     *
     * Each property stored in ComputedStyle is made up of fields. Fields have
     * initial value functions, getters and setters. A field is preferably a
     * basic data type or enum, but can be any type. A set of fields should be
     * preceded by the property the field is stored for.
     *
     * Field method naming should be done like so:
     *   // name-of-property
     *   static int initialNameOfProperty();
     *   int nameOfProperty() const;
     *   void setNameOfProperty(int);
     * If the property has multiple fields, add the field name to the end of the
     * method name.
     *
     * Avoid nested types by splitting up fields where possible, e.g.:
     *  int getBorderTopWidth();
     *  int getBorderBottomWidth();
     *  int getBorderLeftWidth();
     *  int getBorderRightWidth();
     * is preferable to:
     *  BorderWidths getBorderWidths();
     *
     * Utility functions should go in a separate section at the end of the
     * class, and be kept to a minimum.
     */

  // Non-Inherited properties.

  // Content alignment properties.
  static StyleContentAlignmentData InitialContentAlignment() {
    return StyleContentAlignmentData(kContentPositionNormal,
                                     kContentDistributionDefault,
                                     kOverflowAlignmentDefault);
  }

  // align-content (aka -webkit-align-content)
  const StyleContentAlignmentData& AlignContent() const {
    return rare_non_inherited_data_->align_content_;
  }
  void SetAlignContent(const StyleContentAlignmentData& data) {
    SET_VAR(rare_non_inherited_data_, align_content_, data);
  }

  // justify-content (aka -webkit-justify-content)
  const StyleContentAlignmentData& JustifyContent() const {
    return rare_non_inherited_data_->justify_content_;
  }
  void SetJustifyContent(const StyleContentAlignmentData& data) {
    SET_VAR(rare_non_inherited_data_, justify_content_, data);
  }

  // Default-Alignment properties.
  static StyleSelfAlignmentData InitialDefaultAlignment() {
    return StyleSelfAlignmentData(RuntimeEnabledFeatures::CSSGridLayoutEnabled()
                                      ? kItemPositionNormal
                                      : kItemPositionStretch,
                                  kOverflowAlignmentDefault);
  }

  // align-items (aka -webkit-align-items)
  const StyleSelfAlignmentData& AlignItems() const {
    return rare_non_inherited_data_->align_items_;
  }
  void SetAlignItems(const StyleSelfAlignmentData& data) {
    SET_VAR(rare_non_inherited_data_, align_items_, data);
  }

  // justify-items
  const StyleSelfAlignmentData& JustifyItems() const {
    return rare_non_inherited_data_->justify_items_;
  }
  void SetJustifyItems(const StyleSelfAlignmentData& data) {
    SET_VAR(rare_non_inherited_data_, justify_items_, data);
  }

  // Self-Alignment properties.
  static StyleSelfAlignmentData InitialSelfAlignment() {
    return StyleSelfAlignmentData(kItemPositionAuto, kOverflowAlignmentDefault);
  }

  // align-self (aka -webkit-align-self)
  const StyleSelfAlignmentData& AlignSelf() const {
    return rare_non_inherited_data_->align_self_;
  }
  void SetAlignSelf(const StyleSelfAlignmentData& data) {
    SET_VAR(rare_non_inherited_data_, align_self_, data);
  }

  // justify-self
  const StyleSelfAlignmentData& JustifySelf() const {
    return rare_non_inherited_data_->justify_self_;
  }
  void SetJustifySelf(const StyleSelfAlignmentData& data) {
    SET_VAR(rare_non_inherited_data_, justify_self_, data);
  }

  // Filter properties.

  // backdrop-filter
  static const FilterOperations& InitialBackdropFilter();
  const FilterOperations& BackdropFilter() const {
    return rare_non_inherited_data_->backdrop_filter_->operations_;
  }
  FilterOperations& MutableBackdropFilter() {
    return rare_non_inherited_data_.Access()
        ->backdrop_filter_.Access()
        ->operations_;
  }
  bool HasBackdropFilter() const {
    return !rare_non_inherited_data_->backdrop_filter_->operations_.Operations()
                .IsEmpty();
  }
  void SetBackdropFilter(const FilterOperations& ops) {
    SET_NESTED_VAR(rare_non_inherited_data_, backdrop_filter_, operations_,
                   ops);
  }

  // filter (aka -webkit-filter)
  static const FilterOperations& InitialFilter();
  FilterOperations& MutableFilter() {
    return rare_non_inherited_data_.Access()->filter_.Access()->operations_;
  }
  const FilterOperations& Filter() const {
    return rare_non_inherited_data_->filter_->operations_;
  }
  bool HasFilter() const {
    return !rare_non_inherited_data_->filter_->operations_.Operations()
                .IsEmpty();
  }
  void SetFilter(const FilterOperations& ops) {
    SET_NESTED_VAR(rare_non_inherited_data_, filter_, operations_, ops);
  }

  // backface-visibility (aka -webkit-backface-visibility)
  static EBackfaceVisibility InitialBackfaceVisibility() {
    return kBackfaceVisibilityVisible;
  }
  EBackfaceVisibility BackfaceVisibility() const {
    return static_cast<EBackfaceVisibility>(
        rare_non_inherited_data_->backface_visibility_);
  }
  void SetBackfaceVisibility(EBackfaceVisibility b) {
    SET_VAR(rare_non_inherited_data_, backface_visibility_, b);
  }

  // Background properties.
  // background-color
  static Color InitialBackgroundColor() { return Color::kTransparent; }
  void SetBackgroundColor(const StyleColor& v) {
    SetBackgroundColorInternal(v);
  }

  // background-image
  bool HasBackgroundImage() const { return BackgroundInternal().HasImage(); }
  bool HasFixedBackgroundImage() const {
    return BackgroundInternal().HasFixedImage();
  }
  bool HasEntirelyFixedBackground() const;

  // background-clip
  EFillBox BackgroundClip() const {
    return static_cast<EFillBox>(BackgroundInternal().Clip());
  }

  // Border properties.
  // border-image-slice
  const LengthBox& BorderImageSlices() const {
    return BorderImage().ImageSlices();
  }
  void SetBorderImageSlices(const LengthBox&);

  // border-image-source
  static StyleImage* InitialBorderImageSource() { return 0; }
  StyleImage* BorderImageSource() const { return BorderImage().GetImage(); }
  void SetBorderImageSource(StyleImage*);

  // border-image-width
  const BorderImageLengthBox& BorderImageWidth() const {
    return BorderImage().BorderSlices();
  }
  void SetBorderImageWidth(const BorderImageLengthBox&);

  // border-image-outset
  const BorderImageLengthBox& BorderImageOutset() const {
    return BorderImage().Outset();
  }
  void SetBorderImageOutset(const BorderImageLengthBox&);

  // Border width properties.
  static float InitialBorderWidth() { return 3; }

  // TODO(nainar): Move all fixed point logic to a separate class.
  // border-top-width
  float BorderTopWidth() const {
    if (BorderTopStyle() == EBorderStyle::kNone ||
        BorderTopStyle() == EBorderStyle::kHidden)
      return 0;
    return BorderTopWidthInternal().ToFloat();
  }
  void SetBorderTopWidth(float v) { SetBorderTopWidthInternal(LayoutUnit(v)); }
  bool BorderTopNonZero() const {
    return BorderTopWidth() && (BorderTopStyle() != EBorderStyle::kNone);
  }

  // border-bottom-width
  float BorderBottomWidth() const {
    if (BorderBottomStyle() == EBorderStyle::kNone ||
        BorderBottomStyle() == EBorderStyle::kHidden)
      return 0;
    return BorderBottomWidthInternal().ToFloat();
  }
  void SetBorderBottomWidth(float v) {
    SetBorderBottomWidthInternal(LayoutUnit(v));
  }
  bool BorderBottomNonZero() const {
    return BorderBottomWidth() && (BorderBottomStyle() != EBorderStyle::kNone);
  }

  // border-left-width
  float BorderLeftWidth() const {
    if (BorderLeftStyle() == EBorderStyle::kNone ||
        BorderLeftStyle() == EBorderStyle::kHidden)
      return 0;
    return BorderLeftWidthInternal().ToFloat();
  }
  void SetBorderLeftWidth(float v) {
    SetBorderLeftWidthInternal(LayoutUnit(v));
  }
  bool BorderLeftNonZero() const {
    return BorderLeftWidth() && (BorderLeftStyle() != EBorderStyle::kNone);
  }

  // border-right-width
  float BorderRightWidth() const {
    if (BorderRightStyle() == EBorderStyle::kNone ||
        BorderRightStyle() == EBorderStyle::kHidden)
      return 0;
    return BorderRightWidthInternal().ToFloat();
  }
  void SetBorderRightWidth(float v) {
    SetBorderRightWidthInternal(LayoutUnit(v));
  }
  bool BorderRightNonZero() const {
    return BorderRightWidth() && (BorderRightStyle() != EBorderStyle::kNone);
  }

  static EBorderStyle InitialColumnRuleStyle() { return EBorderStyle::kNone; }

  // Border color properties.
  // border-left-color
  void SetBorderLeftColor(const StyleColor& color) {
    if (!compareEqual(BorderLeftColor(), color)) {
      SetBorderLeftColorInternal(color.Resolve(Color()));
      SetBorderLeftColorIsCurrentColor(color.IsCurrentColor());
    }
  }

  // border-right-color
  void SetBorderRightColor(const StyleColor& color) {
    if (!compareEqual(BorderRightColor(), color)) {
      SetBorderRightColorInternal(color.Resolve(Color()));
      SetBorderRightColorIsCurrentColor(color.IsCurrentColor());
    }
  }

  // border-top-color
  void SetBorderTopColor(const StyleColor& color) {
    if (!compareEqual(BorderTopColor(), color)) {
      SetBorderTopColorInternal(color.Resolve(Color()));
      SetBorderTopColorIsCurrentColor(color.IsCurrentColor());
    }
  }

  // border-bottom-color
  void SetBorderBottomColor(const StyleColor& color) {
    if (!compareEqual(BorderBottomColor(), color)) {
      SetBorderBottomColorInternal(color.Resolve(Color()));
      SetBorderBottomColorIsCurrentColor(color.IsCurrentColor());
    }
  }

  // box-shadow (aka -webkit-box-shadow)
  static ShadowList* InitialBoxShadow() { return 0; }
  ShadowList* BoxShadow() const {
    return rare_non_inherited_data_->box_shadow_.Get();
  }
  void SetBoxShadow(RefPtr<ShadowList>);
  bool BoxShadowDataEquivalent(const ComputedStyle& other) const {
    return DataEquivalent(BoxShadow(), other.BoxShadow());
  }

  // clip
  static LengthBox InitialClip() { return LengthBox(); }
  const LengthBox& Clip() const { return ClipInternal(); }
  void SetClip(const LengthBox& box) {
    SetHasAutoClipInternal(false);
    SetClipInternal(box);
  }
  bool HasAutoClip() const { return HasAutoClipInternal(); }
  void SetHasAutoClip() {
    SetHasAutoClipInternal(true);
    SetClipInternal(ComputedStyle::InitialClip());
  }

  // Column properties.
  // column-count (aka -webkit-column-count)
  static unsigned short InitialColumnCount() { return 1; }
  unsigned short ColumnCount() const {
    return rare_non_inherited_data_->multi_col_data_->column_count_;
  }
  void SetColumnCount(unsigned short c) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_auto_count_, false);
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_count_, c);
  }
  bool HasAutoColumnCount() const {
    return rare_non_inherited_data_->multi_col_data_->column_auto_count_;
  }
  void SetHasAutoColumnCount() {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_auto_count_, true);
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_count_,
                   InitialColumnCount());
  }

  // column-fill
  static ColumnFill InitialColumnFill() { return kColumnFillBalance; }
  ColumnFill GetColumnFill() const {
    return static_cast<ColumnFill>(
        rare_non_inherited_data_->multi_col_data_->column_fill_);
  }
  void SetColumnFill(ColumnFill column_fill) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_fill_,
                   column_fill);
  }

  // column-gap (aka -webkit-column-gap)
  float ColumnGap() const {
    return rare_non_inherited_data_->multi_col_data_->column_gap_;
  }
  void SetColumnGap(float f) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_normal_gap_, false);
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_gap_, f);
  }
  bool HasNormalColumnGap() const {
    return rare_non_inherited_data_->multi_col_data_->column_normal_gap_;
  }
  void SetHasNormalColumnGap() {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_normal_gap_, true);
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_gap_, 0);
  }

  // column-rule-color (aka -webkit-column-rule-color)
  void SetColumnRuleColor(const StyleColor& c) {
    SET_BORDERVALUE_COLOR(rare_non_inherited_data_.Access()->multi_col_data_,
                          column_rule_, c);
  }

  // column-rule-style (aka -webkit-column-rule-style)
  EBorderStyle ColumnRuleStyle() const {
    return rare_non_inherited_data_->multi_col_data_->column_rule_.Style();
  }
  void SetColumnRuleStyle(EBorderStyle b) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_rule_.style_, static_cast<unsigned>(b));
  }

  // column-rule-width (aka -webkit-column-rule-width)
  static unsigned short InitialColumnRuleWidth() { return 3; }
  unsigned short ColumnRuleWidth() const {
    const BorderValue& rule =
        rare_non_inherited_data_->multi_col_data_->column_rule_;
    if (rule.Style() == EBorderStyle::kNone ||
        rule.Style() == EBorderStyle::kHidden)
      return 0;
    return rule.Width();
  }
  void SetColumnRuleWidth(unsigned short w) {
    SET_NESTED_BORDER_WIDTH(rare_non_inherited_data_, multi_col_data_,
                            column_rule_, w);
  }

  // column-span (aka -webkit-column-span)
  static ColumnSpan InitialColumnSpan() { return kColumnSpanNone; }
  ColumnSpan GetColumnSpan() const {
    return static_cast<ColumnSpan>(
        rare_non_inherited_data_->multi_col_data_->column_span_);
  }
  void SetColumnSpan(ColumnSpan column_span) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_span_,
                   column_span);
  }

  // column-width (aka -webkit-column-width)
  float ColumnWidth() const {
    return rare_non_inherited_data_->multi_col_data_->column_width_;
  }
  void SetColumnWidth(float f) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_auto_width_, false);
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_width_, f);
  }
  bool HasAutoColumnWidth() const {
    return rare_non_inherited_data_->multi_col_data_->column_auto_width_;
  }
  void SetHasAutoColumnWidth() {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   column_auto_width_, true);
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_width_, 0);
  }

  // contain
  static Containment InitialContain() { return kContainsNone; }
  Containment Contain() const {
    return static_cast<Containment>(rare_non_inherited_data_->contain_);
  }
  void SetContain(Containment contain) {
    SET_VAR(rare_non_inherited_data_, contain_, contain);
  }

  // content
  ContentData* GetContentData() const {
    return rare_non_inherited_data_->content_.Get();
  }
  void SetContent(ContentData*);

  // Flex properties.
  // flex-basis (aka -webkit-flex-basis)
  static Length InitialFlexBasis() { return Length(kAuto); }
  const Length& FlexBasis() const {
    return rare_non_inherited_data_->flexible_box_data_->flex_basis_;
  }
  void SetFlexBasis(const Length& length) {
    SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_, flex_basis_,
                   length);
  }

  // flex-direction (aka -webkit-flex-direction)
  static EFlexDirection InitialFlexDirection() { return kFlowRow; }
  EFlexDirection FlexDirection() const {
    return static_cast<EFlexDirection>(
        rare_non_inherited_data_->flexible_box_data_->flex_direction_);
  }
  void SetFlexDirection(EFlexDirection direction) {
    SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_,
                   flex_direction_, direction);
  }

  // flex-grow (aka -webkit-flex-grow)
  static float InitialFlexGrow() { return 0; }
  float FlexGrow() const {
    return rare_non_inherited_data_->flexible_box_data_->flex_grow_;
  }
  void SetFlexGrow(float f) {
    SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_, flex_grow_, f);
  }

  // flex-shrink (aka -webkit-flex-shrink)
  static float InitialFlexShrink() { return 1; }
  float FlexShrink() const {
    return rare_non_inherited_data_->flexible_box_data_->flex_shrink_;
  }
  void SetFlexShrink(float f) {
    SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_, flex_shrink_,
                   f);
  }

  // flex-wrap (aka -webkit-flex-wrap)
  static EFlexWrap InitialFlexWrap() { return kFlexNoWrap; }
  EFlexWrap FlexWrap() const {
    return static_cast<EFlexWrap>(
        rare_non_inherited_data_->flexible_box_data_->flex_wrap_);
  }
  void SetFlexWrap(EFlexWrap w) {
    SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_, flex_wrap_, w);
  }

  // -webkit-box-align
  // For valid values of box-align see
  // http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment
  static EBoxAlignment InitialBoxAlign() { return BSTRETCH; }
  EBoxAlignment BoxAlign() const {
    return static_cast<EBoxAlignment>(
        rare_non_inherited_data_->deprecated_flexible_box_data_->box_align_);
  }
  void SetBoxAlign(EBoxAlignment a) {
    SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
                   box_align_, a);
  }

  // -webkit-box-lines
  static EBoxLines InitialBoxLines() { return SINGLE; }
  EBoxLines BoxLines() const {
    return static_cast<EBoxLines>(
        rare_non_inherited_data_->deprecated_flexible_box_data_->box_lines_);
  }
  void SetBoxLines(EBoxLines lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
                   box_lines_, lines);
  }

  // -webkit-box-ordinal-group
  static unsigned InitialBoxOrdinalGroup() { return 1; }
  unsigned BoxOrdinalGroup() const {
    return rare_non_inherited_data_->deprecated_flexible_box_data_
        ->box_ordinal_group_;
  }
  void SetBoxOrdinalGroup(unsigned og) {
    SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
                   box_ordinal_group_,
                   std::min(std::numeric_limits<unsigned>::max() - 1, og));
  }

  // -webkit-box-orient
  static EBoxOrient InitialBoxOrient() { return HORIZONTAL; }
  EBoxOrient BoxOrient() const {
    return static_cast<EBoxOrient>(
        rare_non_inherited_data_->deprecated_flexible_box_data_->box_orient_);
  }
  void SetBoxOrient(EBoxOrient o) {
    SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
                   box_orient_, o);
  }

  // -webkit-box-pack
  static EBoxPack InitialBoxPack() { return kBoxPackStart; }
  EBoxPack BoxPack() const {
    return static_cast<EBoxPack>(
        rare_non_inherited_data_->deprecated_flexible_box_data_->box_pack_);
  }
  void SetBoxPack(EBoxPack p) {
    SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
                   box_pack_, p);
  }

  // -webkit-box-reflect
  static StyleReflection* InitialBoxReflect() { return 0; }
  StyleReflection* BoxReflect() const {
    return rare_non_inherited_data_->box_reflect_.Get();
  }
  void SetBoxReflect(RefPtr<StyleReflection> reflect) {
    if (rare_non_inherited_data_->box_reflect_ != reflect)
      rare_non_inherited_data_.Access()->box_reflect_ = std::move(reflect);
  }

  // Grid properties.
  static Vector<GridTrackSize> InitialGridAutoRepeatTracks() {
    return Vector<GridTrackSize>(); /* none */
  }
  static size_t InitialGridAutoRepeatInsertionPoint() { return 0; }
  static AutoRepeatType InitialGridAutoRepeatType() { return kNoAutoRepeat; }
  static NamedGridLinesMap InitialNamedGridColumnLines() {
    return NamedGridLinesMap();
  }
  static NamedGridLinesMap InitialNamedGridRowLines() {
    return NamedGridLinesMap();
  }
  static OrderedNamedGridLines InitialOrderedNamedGridColumnLines() {
    return OrderedNamedGridLines();
  }
  static OrderedNamedGridLines InitialOrderedNamedGridRowLines() {
    return OrderedNamedGridLines();
  }
  static NamedGridAreaMap InitialNamedGridArea() { return NamedGridAreaMap(); }
  static size_t InitialNamedGridAreaCount() { return 0; }

  // grid-auto-columns
  static Vector<GridTrackSize> InitialGridAutoColumns();
  const Vector<GridTrackSize>& GridAutoColumns() const {
    return rare_non_inherited_data_->grid_data_->grid_auto_columns_;
  }
  void SetGridAutoColumns(const Vector<GridTrackSize>& track_size_list) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_columns_,
                   track_size_list);
  }

  // grid-auto-flow
  static GridAutoFlow InitialGridAutoFlow() { return kAutoFlowRow; }
  void SetGridAutoFlow(GridAutoFlow flow) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_flow_, flow);
  }

  // grid-auto-rows
  static Vector<GridTrackSize> InitialGridAutoRows();
  const Vector<GridTrackSize>& GridAutoRows() const {
    return rare_non_inherited_data_->grid_data_->grid_auto_rows_;
  }
  void SetGridAutoRows(const Vector<GridTrackSize>& track_size_list) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_rows_,
                   track_size_list);
  }

  // grid-column-gap
  static Length InitialGridColumnGap() { return Length(kFixed); }
  const Length& GridColumnGap() const {
    return rare_non_inherited_data_->grid_data_->grid_column_gap_;
  }
  void SetGridColumnGap(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_column_gap_, v);
  }

  // grid-column-start
  static GridPosition InitialGridColumnStart() {
    return GridPosition(); /* auto */
  }
  const GridPosition& GridColumnStart() const {
    return rare_non_inherited_data_->grid_item_data_->grid_column_start_;
  }
  void SetGridColumnStart(const GridPosition& column_start_position) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_,
                   grid_column_start_, column_start_position);
  }

  // grid-column-end
  static GridPosition InitialGridColumnEnd() {
    return GridPosition(); /* auto */
  }
  const GridPosition& GridColumnEnd() const {
    return rare_non_inherited_data_->grid_item_data_->grid_column_end_;
  }
  void SetGridColumnEnd(const GridPosition& column_end_position) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_, grid_column_end_,
                   column_end_position);
  }

  // grid-row-gap
  static Length InitialGridRowGap() { return Length(kFixed); }
  const Length& GridRowGap() const {
    return rare_non_inherited_data_->grid_data_->grid_row_gap_;
  }
  void SetGridRowGap(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_row_gap_, v);
  }

  // grid-row-start
  static GridPosition InitialGridRowStart() {
    return GridPosition(); /* auto */
  }
  const GridPosition& GridRowStart() const {
    return rare_non_inherited_data_->grid_item_data_->grid_row_start_;
  }
  void SetGridRowStart(const GridPosition& row_start_position) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_, grid_row_start_,
                   row_start_position);
  }

  // grid-row-end
  static GridPosition InitialGridRowEnd() { return GridPosition(); /* auto */ }
  const GridPosition& GridRowEnd() const {
    return rare_non_inherited_data_->grid_item_data_->grid_row_end_;
  }
  void SetGridRowEnd(const GridPosition& row_end_position) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_, grid_row_end_,
                   row_end_position);
  }

  // grid-template-columns
  static Vector<GridTrackSize> InitialGridTemplateColumns() {
    return Vector<GridTrackSize>(); /* none */
  }
  const Vector<GridTrackSize>& GridTemplateColumns() const {
    return rare_non_inherited_data_->grid_data_->grid_template_columns_;
  }
  void SetGridTemplateColumns(const Vector<GridTrackSize>& lengths) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_template_columns_,
                   lengths);
  }

  // grid-template-rows
  static Vector<GridTrackSize> InitialGridTemplateRows() {
    return Vector<GridTrackSize>(); /* none */
  }
  const Vector<GridTrackSize>& GridTemplateRows() const {
    return rare_non_inherited_data_->grid_data_->grid_template_rows_;
  }
  void SetGridTemplateRows(const Vector<GridTrackSize>& lengths) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_template_rows_,
                   lengths);
  }

  // mix-blend-mode
  static WebBlendMode InitialBlendMode() { return kWebBlendModeNormal; }
  WebBlendMode BlendMode() const {
    return static_cast<WebBlendMode>(
        rare_non_inherited_data_->effective_blend_mode_);
  }
  void SetBlendMode(WebBlendMode v) {
    rare_non_inherited_data_.Access()->effective_blend_mode_ = v;
  }

  // offset-anchor
  static LengthPoint InitialOffsetAnchor() {
    return LengthPoint(Length(kAuto), Length(kAuto));
  }
  const LengthPoint& OffsetAnchor() const {
    return rare_non_inherited_data_->transform_data_->motion_.anchor_;
  }
  void SetOffsetAnchor(const LengthPoint& offset_anchor) {
    SET_NESTED_VAR(rare_non_inherited_data_, transform_data_, motion_.anchor_,
                   offset_anchor);
  }

  // offset-distance
  static Length InitialOffsetDistance() { return Length(0, kFixed); }
  const Length& OffsetDistance() const {
    return rare_non_inherited_data_->transform_data_->motion_.distance_;
  }
  void SetOffsetDistance(const Length& offset_distance) {
    SET_NESTED_VAR(rare_non_inherited_data_, transform_data_, motion_.distance_,
                   offset_distance);
  }

  // offset-path
  static BasicShape* InitialOffsetPath() { return nullptr; }
  BasicShape* OffsetPath() const {
    return rare_non_inherited_data_->transform_data_->motion_.path_.Get();
  }
  void SetOffsetPath(RefPtr<BasicShape>);

  // offset-position
  static LengthPoint InitialOffsetPosition() {
    return LengthPoint(Length(kAuto), Length(kAuto));
  }
  const LengthPoint& OffsetPosition() const {
    return rare_non_inherited_data_->transform_data_->motion_.position_;
  }
  void SetOffsetPosition(const LengthPoint& offset_position) {
    SET_NESTED_VAR(rare_non_inherited_data_, transform_data_, motion_.position_,
                   offset_position);
  }

  // offset-rotate
  static StyleOffsetRotation InitialOffsetRotate() {
    return StyleOffsetRotation(0, kOffsetRotationAuto);
  }
  const StyleOffsetRotation& OffsetRotate() const {
    return rare_non_inherited_data_->transform_data_->motion_.rotation_;
  }
  void SetOffsetRotate(const StyleOffsetRotation& offset_rotate) {
    SET_NESTED_VAR(rare_non_inherited_data_, transform_data_, motion_.rotation_,
                   offset_rotate);
  }

  // opacity (aka -webkit-opacity)
  static float InitialOpacity() { return 1.0f; }
  float Opacity() const { return rare_non_inherited_data_->opacity_; }
  void SetOpacity(float f) {
    float v = clampTo<float>(f, 0, 1);
    SET_VAR(rare_non_inherited_data_, opacity_, v);
  }

  bool OpacityChangedStackingContext(const ComputedStyle& other) const {
    // 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() ||
        HasOpacity() == other.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;
    }
    return false;
  }

  // order (aka -webkit-order)
  static int InitialOrder() { return 0; }
  int Order() const { return rare_non_inherited_data_->order_; }
  // We restrict the smallest value to int min + 2 because we use int min and
  // int min + 1 as special values in a hash set.
  void SetOrder(int o) {
    SET_VAR(rare_non_inherited_data_, order_,
            max(std::numeric_limits<int>::min() + 2, o));
  }

  // Outline properties.

  bool OutlineVisuallyEqual(const ComputedStyle& other) const {
    return rare_non_inherited_data_->outline_.VisuallyEqual(
        other.rare_non_inherited_data_->outline_);
  }

  // outline-color
  void SetOutlineColor(const StyleColor& v) {
    SET_BORDERVALUE_COLOR(rare_non_inherited_data_, outline_, v);
  }

  // outline-style
  EBorderStyle OutlineStyle() const {
    return rare_non_inherited_data_->outline_.Style();
  }
  void SetOutlineStyle(EBorderStyle v) {
    SET_VAR(rare_non_inherited_data_, outline_.style_,
            static_cast<unsigned>(v));
  }
  static OutlineIsAuto InitialOutlineStyleIsAuto() { return kOutlineIsAutoOff; }
  OutlineIsAuto OutlineStyleIsAuto() const {
    return static_cast<OutlineIsAuto>(
        rare_non_inherited_data_->outline_.IsAuto());
  }
  void SetOutlineStyleIsAuto(OutlineIsAuto is_auto) {
    SET_VAR(rare_non_inherited_data_, outline_.is_auto_, is_auto);
  }

  // outline-width
  static unsigned short InitialOutlineWidth() { return 3; }
  unsigned short OutlineWidth() const {
    if (rare_non_inherited_data_->outline_.Style() == EBorderStyle::kNone)
      return 0;
    return rare_non_inherited_data_->outline_.Width();
  }
  void SetOutlineWidth(unsigned short v) {
    SET_BORDER_WIDTH(rare_non_inherited_data_, outline_, v);
  }

  // outline-offset
  static int InitialOutlineOffset() { return 0; }
  int OutlineOffset() const {
    if (rare_non_inherited_data_->outline_.Style() == EBorderStyle::kNone)
      return 0;
    return rare_non_inherited_data_->outline_.Offset();
  }
  void SetOutlineOffset(int v) {
    SET_VAR(rare_non_inherited_data_, outline_.offset_, v);
  }

  // perspective (aka -webkit-perspective)
  static float InitialPerspective() { return 0; }
  float Perspective() const { return rare_non_inherited_data_->perspective_; }
  void SetPerspective(float p) {
    SET_VAR(rare_non_inherited_data_, perspective_, p);
  }

  // perspective-origin (aka -webkit-perspective-origin)
  static LengthPoint InitialPerspectiveOrigin() {
    return LengthPoint(Length(50.0, kPercent), Length(50.0, kPercent));
  }
  const LengthPoint& PerspectiveOrigin() const {
    return rare_non_inherited_data_->perspective_origin_;
  }
  void SetPerspectiveOrigin(const LengthPoint& p) {
    SET_VAR(rare_non_inherited_data_, perspective_origin_, p);
  }

  // -webkit-perspective-origin-x
  static Length InitialPerspectiveOriginX() { return Length(50.0, kPercent); }
  const Length& PerspectiveOriginX() const { return PerspectiveOrigin().X(); }
  void SetPerspectiveOriginX(const Length& v) {
    SetPerspectiveOrigin(LengthPoint(v, PerspectiveOriginY()));
  }

  // -webkit-perspective-origin-y
  static Length InitialPerspectiveOriginY() { return Length(50.0, kPercent); }
  const Length& PerspectiveOriginY() const { return PerspectiveOrigin().Y(); }
  void SetPerspectiveOriginY(const Length& v) {
    SetPerspectiveOrigin(LengthPoint(PerspectiveOriginX(), v));
  }

  // resize
  static EResize InitialResize() { return RESIZE_NONE; }
  EResize Resize() const {
    return static_cast<EResize>(rare_non_inherited_data_->resize_);
  }
  void SetResize(EResize r) { SET_VAR(rare_non_inherited_data_, resize_, r); }

  // Transform properties.
  // transform (aka -webkit-transform)
  static EmptyTransformOperations InitialTransform() {
    return EmptyTransformOperations();
  }
  const TransformOperations& Transform() const {
    return rare_non_inherited_data_->transform_data_->transform_operations_;
  }
  void SetTransform(const TransformOperations& ops) {
    SET_NESTED_VAR(rare_non_inherited_data_, transform_data_,
                   transform_operations_, ops);
  }

  // transform-origin (aka -webkit-transform-origin)
  static TransformOrigin InitialTransformOrigin() {
    return TransformOrigin(Length(50.0, kPercent), Length(50.0, kPercent), 0);
  }
  const TransformOrigin& GetTransformOrigin() const {
    return rare_non_inherited_data_->transform_data_->transform_origin_;
  }
  void SetTransformOrigin(const TransformOrigin& o) {
    SET_NESTED_VAR(rare_non_inherited_data_, transform_data_, transform_origin_,
                   o);
  }

  // transform-style (aka -webkit-transform-style)
  static ETransformStyle3D InitialTransformStyle3D() {
    return ETransformStyle3D::kFlat;
  }
  ETransformStyle3D TransformStyle3D() const {
    return static_cast<ETransformStyle3D>(
        rare_non_inherited_data_->transform_style_3d_);
  }
  void SetTransformStyle3D(ETransformStyle3D b) {
    SET_VAR(rare_non_inherited_data_, transform_style_3d_,
            static_cast<unsigned>(b));
  }

  // -webkit-transform-origin-x
  static Length InitialTransformOriginX() { return Length(50.0, kPercent); }
  const Length& TransformOriginX() const { return GetTransformOrigin().X(); }
  void SetTransformOriginX(const Length& v) {
    SetTransformOrigin(
        TransformOrigin(v, TransformOriginY(), TransformOriginZ()));
  }

  // -webkit-transform-origin-y
  static Length InitialTransformOriginY() { return Length(50.0, kPercent); }
  const Length& TransformOriginY() const { return GetTransformOrigin().Y(); }
  void SetTransformOriginY(const Length& v) {
    SetTransformOrigin(
        TransformOrigin(TransformOriginX(), v, TransformOriginZ()));
  }

  // -webkit-transform-origin-z
  static float InitialTransformOriginZ() { return 0; }
  float TransformOriginZ() const { return GetTransformOrigin().Z(); }
  void SetTransformOriginZ(float f) {
    SetTransformOrigin(
        TransformOrigin(TransformOriginX(), TransformOriginY(), f));
  }

  // Independent transform properties.
  // translate
  static RefPtr<TranslateTransformOperation> InitialTranslate() {
    return nullptr;
  }
  TranslateTransformOperation* Translate() const {
    return rare_non_inherited_data_->transform_data_->translate_.Get();
  }
  void SetTranslate(RefPtr<TranslateTransformOperation> v) {
    rare_non_inherited_data_.Access()->transform_data_.Access()->translate_ =
        std::move(v);
  }

  // rotate
  static RefPtr<RotateTransformOperation> InitialRotate() { return nullptr; }
  RotateTransformOperation* Rotate() const {
    return rare_non_inherited_data_->transform_data_->rotate_.Get();
  }
  void SetRotate(RefPtr<RotateTransformOperation> v) {
    rare_non_inherited_data_.Access()->transform_data_.Access()->rotate_ =
        std::move(v);
  }

  // scale
  static RefPtr<ScaleTransformOperation> InitialScale() { return nullptr; }
  ScaleTransformOperation* Scale() const {
    return rare_non_inherited_data_->transform_data_->scale_.Get();
  }
  void SetScale(RefPtr<ScaleTransformOperation> v) {
    rare_non_inherited_data_.Access()->transform_data_.Access()->scale_ =
        std::move(v);
  }

  // Scroll properties.
  // scroll-behavior
  static ScrollBehavior InitialScrollBehavior() { return kScrollBehaviorAuto; }
  ScrollBehavior GetScrollBehavior() const {
    return static_cast<ScrollBehavior>(
        rare_non_inherited_data_->scroll_behavior_);
  }
  void SetScrollBehavior(ScrollBehavior b) {
    SET_VAR(rare_non_inherited_data_, scroll_behavior_, b);
  }

  // scroll-snap-type
  static ScrollSnapType InitialScrollSnapType() { return ScrollSnapType(); }
  ScrollSnapType GetScrollSnapType() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_type_;
  }
  void SetScrollSnapType(const ScrollSnapType& b) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_snap_type_, b);
  }

  // Scroll Padding properties
  static Length InitialScrollPadding() { return Length(); }

  // scroll-padding-top
  const Length& ScrollPaddingTop() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.top;
  }
  void SetScrollPaddingTop(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_padding_.top, v);
  }

  // scroll-padding-bottom
  const Length& ScrollPaddingBottom() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.bottom;
  }
  void SetScrollPaddingBottom(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_padding_.bottom, v);
  }

  // scroll-padding-left
  const Length& ScrollPaddingLeft() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.left;
  }
  void SetScrollPaddingLeft(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_padding_.left, v);
  }

  // scroll-padding-right
  const Length& ScrollPaddingRight() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.right;
  }
  void SetScrollPaddingRight(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_padding_.right, v);
  }

  // scroll-padding-block-start
  const Length& ScrollPaddingBlockStart() const {
    return IsHorizontalWritingMode() ? ScrollPaddingTop() : ScrollPaddingLeft();
  }
  void SetScrollPaddingBlockStart(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollPaddingTop(v);
    else
      SetScrollPaddingLeft(v);
  }

  // scroll-padding-block-end
  const Length& ScrollPaddingBlockEnd() const {
    return IsHorizontalWritingMode() ? ScrollPaddingBottom()
                                     : ScrollPaddingRight();
  }
  void SetScrollPaddingBlockEnd(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollPaddingBottom(v);
    else
      SetScrollPaddingRight(v);
  }

  // scroll-padding-inline-start
  const Length& ScrollPaddingInlineStart() const {
    return IsHorizontalWritingMode() ? ScrollPaddingLeft() : ScrollPaddingTop();
  }
  void SetScrollPaddingInlineStart(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollPaddingLeft(v);
    else
      SetScrollPaddingTop(v);
  }

  // scroll-padding-inline-end
  const Length& ScrollPaddingInlineEnd() const {
    return IsHorizontalWritingMode() ? ScrollPaddingRight()
                                     : ScrollPaddingBottom();
  }
  void SetScrollPaddingInlineEnd(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollPaddingRight(v);
    else
      SetScrollPaddingBottom(v);
  }

  // scroll-snap-margin
  static Length InitialScrollSnapMargin() { return Length(); }

  // scroll-snap-margin-top
  const Length& ScrollSnapMarginTop() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_.top;
  }
  void SetScrollSnapMarginTop(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_snap_margin_.top, v);
  }

  // scroll-snap-margin-bottom
  const Length& ScrollSnapMarginBottom() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_
        .bottom;
  }
  void SetScrollSnapMarginBottom(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_snap_margin_.bottom, v);
  }

  // scroll-snap-margin-left
  const Length& ScrollSnapMarginLeft() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_
        .left;
  }
  void SetScrollSnapMarginLeft(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_snap_margin_.left, v);
  }

  // scroll-snap-margin-right
  const Length& ScrollSnapMarginRight() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_
        .right;
  }
  void SetScrollSnapMarginRight(const Length& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_snap_margin_.right, v);
  }

  // scroll-snap-margin-block-start
  const Length& ScrollSnapMarginBlockStart() const {
    return IsHorizontalWritingMode() ? ScrollSnapMarginTop()
                                     : ScrollSnapMarginLeft();
  }
  void SetScrollSnapMarginBlockStart(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollSnapMarginTop(v);
    else
      SetScrollSnapMarginLeft(v);
  }

  // scroll-snap-margin-block-end
  const Length& ScrollSnapMarginBlockEnd() const {
    return IsHorizontalWritingMode() ? ScrollSnapMarginBottom()
                                     : ScrollSnapMarginRight();
  }
  void SetScrollSnapMarginBlockEnd(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollSnapMarginBottom(v);
    else
      SetScrollSnapMarginRight(v);
  }

  // scroll-snap-margin-inline-start
  const Length& ScrollSnapMarginInlineStart() const {
    return IsHorizontalWritingMode() ? ScrollSnapMarginLeft()
                                     : ScrollSnapMarginTop();
  }
  void SetScrollSnapMarginInlineStart(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollSnapMarginLeft(v);
    else
      SetScrollSnapMarginTop(v);
  }

  // scroll-snap-margin-inline-end
  const Length& ScrollSnapMarginInlineEnd() const {
    return IsHorizontalWritingMode() ? ScrollSnapMarginRight()
                                     : ScrollSnapMarginBottom();
  }
  void SetScrollSnapMarginInlineEnd(const Length& v) {
    if (IsHorizontalWritingMode())
      SetScrollSnapMarginRight(v);
    else
      SetScrollSnapMarginBottom(v);
  }

  // scroll-snap-align
  static ScrollSnapAlign InitialScrollSnapAlign() { return ScrollSnapAlign(); }
  ScrollSnapAlign GetScrollSnapAlign() const {
    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_align_;
  }
  void SetScrollSnapAlign(const ScrollSnapAlign& b) {
    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
                   scroll_snap_align_, b);
  }

  // shape-image-threshold (aka -webkit-shape-image-threshold)
  static float InitialShapeImageThreshold() { return 0; }
  float ShapeImageThreshold() const {
    return rare_non_inherited_data_->shape_image_threshold_;
  }
  void SetShapeImageThreshold(float shape_image_threshold) {
    float clamped_shape_image_threshold =
        clampTo<float>(shape_image_threshold, 0, 1);
    SET_VAR(rare_non_inherited_data_, shape_image_threshold_,
            clamped_shape_image_threshold);
  }

  // shape-outside (aka -webkit-shape-outside)
  static ShapeValue* InitialShapeOutside() { return 0; }
  ShapeValue* ShapeOutside() const {
    return rare_non_inherited_data_->shape_outside_.Get();
  }
  void SetShapeOutside(ShapeValue* value) {
    if (rare_non_inherited_data_->shape_outside_ == value)
      return;
    rare_non_inherited_data_.Access()->shape_outside_ = value;
  }
  bool ShapeOutsideDataEquivalent(const ComputedStyle& other) const {
    return DataEquivalent(ShapeOutside(), other.ShapeOutside());
  }

  // size
  const FloatSize& PageSize() const {
    return rare_non_inherited_data_->page_size_;
  }
  PageSizeType GetPageSizeType() const {
    return static_cast<PageSizeType>(rare_non_inherited_data_->page_size_type_);
  }
  void SetPageSize(const FloatSize& s) {
    SET_VAR(rare_non_inherited_data_, page_size_, s);
  }
  void SetPageSizeType(PageSizeType t) {
    SET_VAR(rare_non_inherited_data_, page_size_type_,
            static_cast<unsigned>(t));
  }

  // Text decoration properties.
  // text-decoration-line
  static TextDecoration InitialTextDecoration() {
    return TextDecoration::kNone;
  }
  TextDecoration GetTextDecoration() const {
    return static_cast<TextDecoration>(TextDecorationInternal());
  }
  void SetTextDecoration(TextDecoration v) { SetTextDecorationInternal(v); }

  // text-decoration-color
  void SetTextDecorationColor(const StyleColor& c) {
    SET_VAR(rare_non_inherited_data_, text_decoration_color_, c);
  }

  // text-decoration-style
  static TextDecorationStyle InitialTextDecorationStyle() {
    return kTextDecorationStyleSolid;
  }
  TextDecorationStyle GetTextDecorationStyle() const {
    return static_cast<TextDecorationStyle>(
        rare_non_inherited_data_->text_decoration_style_);
  }
  void SetTextDecorationStyle(TextDecorationStyle v) {
    SET_VAR(rare_non_inherited_data_, text_decoration_style_, v);
  }

  // text-decoration-skip
  static TextDecorationSkip InitialTextDecorationSkip() {
    return TextDecorationSkip::kObjects;
  }
  TextDecorationSkip GetTextDecorationSkip() const {
    return TextDecorationSkipInternal();
  }
  void SetTextDecorationSkip(TextDecorationSkip v) {
    SetTextDecorationSkipInternal(v);
  }

  // text-overflow
  static TextOverflow InitialTextOverflow() { return kTextOverflowClip; }
  TextOverflow GetTextOverflow() const {
    return static_cast<TextOverflow>(rare_non_inherited_data_->text_overflow_);
  }
  void SetTextOverflow(TextOverflow overflow) {
    SET_VAR(rare_non_inherited_data_, text_overflow_, overflow);
  }

  // touch-action
  static TouchAction InitialTouchAction() {
    return TouchAction::kTouchActionAuto;
  }
  TouchAction GetTouchAction() const {
    return static_cast<TouchAction>(rare_non_inherited_data_->touch_action_);
  }
  void SetTouchAction(TouchAction t) {
    SET_VAR(rare_non_inherited_data_, touch_action_, t);
  }

  // vertical-align
  static EVerticalAlign InitialVerticalAlign() {
    return EVerticalAlign::kBaseline;
  }
  EVerticalAlign VerticalAlign() const { return VerticalAlignInternal(); }
  const Length& GetVerticalAlignLength() const {
    return VerticalAlignLengthInternal();
  }
  void SetVerticalAlign(EVerticalAlign v) { SetVerticalAlignInternal(v); }
  void SetVerticalAlignLength(const Length& length) {
    SetVerticalAlignInternal(EVerticalAlign::kLength);
    SetVerticalAlignLengthInternal(length);
  }

  // z-index
  int ZIndex() const { return ZIndexInternal(); }
  bool HasAutoZIndex() const { return HasAutoZIndexInternal(); }
  void SetZIndex(int v) {
    SetHasAutoZIndexInternal(false);
    SetZIndexInternal(v);
  }
  void SetHasAutoZIndex() {
    SetHasAutoZIndexInternal(true);
    SetZIndexInternal(0);
  }

  // zoom
  static float InitialZoom() { return 1.0f; }
  float Zoom() const { return ZoomInternal(); }
  float EffectiveZoom() const { return EffectiveZoomInternal(); }
  bool SetZoom(float);
  bool SetEffectiveZoom(float);

  // -webkit-app-region
  DraggableRegionMode GetDraggableRegionMode() const {
    return static_cast<DraggableRegionMode>(
        rare_non_inherited_data_->draggable_region_mode_);
  }
  void SetDraggableRegionMode(DraggableRegionMode v) {
    SET_VAR(rare_non_inherited_data_, draggable_region_mode_,
            static_cast<unsigned>(v));
  }

  // -webkit-appearance
  static ControlPart InitialAppearance() { return kNoControlPart; }
  ControlPart Appearance() const {
    return static_cast<ControlPart>(rare_non_inherited_data_->appearance_);
  }
  void SetAppearance(ControlPart a) {
    SET_VAR(rare_non_inherited_data_, appearance_, a);
  }

  // -webkit-clip-path
  static ClipPathOperation* InitialClipPath() { return 0; }
  ClipPathOperation* ClipPath() const {
    return rare_non_inherited_data_->clip_path_.Get();
  }
  void SetClipPath(RefPtr<ClipPathOperation> operation) {
    if (rare_non_inherited_data_->clip_path_ != operation)
      rare_non_inherited_data_.Access()->clip_path_ = std::move(operation);
  }
  bool ClipPathDataEquivalent(const ComputedStyle& other) const {
    return DataEquivalent(ClipPath(), other.ClipPath());
  }

  // Mask properties.
  // -webkit-mask-box-image-outset
  const BorderImageLengthBox& MaskBoxImageOutset() const {
    return rare_non_inherited_data_->mask_box_image_.Outset();
  }
  void SetMaskBoxImageOutset(const BorderImageLengthBox& outset) {
    rare_non_inherited_data_.Access()->mask_box_image_.SetOutset(outset);
  }

  // -webkit-mask-box-image-slice
  const LengthBox& MaskBoxImageSlices() const {
    return rare_non_inherited_data_->mask_box_image_.ImageSlices();
  }
  void SetMaskBoxImageSlices(const LengthBox& slices) {
    rare_non_inherited_data_.Access()->mask_box_image_.SetImageSlices(slices);
  }

  // -webkit-mask-box-image-source
  static StyleImage* InitialMaskBoxImageSource() { return 0; }
  StyleImage* MaskBoxImageSource() const {
    return rare_non_inherited_data_->mask_box_image_.GetImage();
  }
  void SetMaskBoxImageSource(StyleImage* v) {
    rare_non_inherited_data_.Access()->mask_box_image_.SetImage(v);
  }

  // -webkit-mask-box-image-width
  const BorderImageLengthBox& MaskBoxImageWidth() const {
    return rare_non_inherited_data_->mask_box_image_.BorderSlices();
  }
  void SetMaskBoxImageWidth(const BorderImageLengthBox& slices) {
    rare_non_inherited_data_.Access()->mask_box_image_.SetBorderSlices(slices);
  }

  // Inherited properties.

  // color
  static Color InitialColor() { return Color::kBlack; }
  void SetColor(const Color&);

  // line-height
  static Length InitialLineHeight() { return Length(-100.0, kPercent); }
  Length LineHeight() const;
  void SetLineHeight(const Length& specified_line_height);

  // List style properties.
  // list-style-image
  static StyleImage* InitialListStyleImage() { return 0; }
  StyleImage* ListStyleImage() const;
  void SetListStyleImage(StyleImage*);

  // quotes
  static QuotesData* InitialQuotes() { return 0; }
  QuotesData* Quotes() const { return QuotesInternal().Get(); }
  void SetQuotes(RefPtr<QuotesData>);

  bool QuotesDataEquivalent(const ComputedStyle&) const;

  // text-shadow
  static ShadowList* InitialTextShadow() { return 0; }
  ShadowList* TextShadow() const { return TextShadowInternal().Get(); }
  void SetTextShadow(RefPtr<ShadowList>);

  bool TextShadowDataEquivalent(const ComputedStyle&) const;

  // Text emphasis properties.
  static TextEmphasisMark InitialTextEmphasisMark() {
    return TextEmphasisMark::kNone;
  }
  TextEmphasisMark GetTextEmphasisMark() const;
  void SetTextEmphasisMark(TextEmphasisMark mark) {
    SetTextEmphasisMarkInternal(mark);
  }
  const AtomicString& TextEmphasisMarkString() const;

  // -webkit-text-emphasis-color (aka -epub-text-emphasis-color)
  void SetTextEmphasisColor(const StyleColor& color) {
    SetTextEmphasisColorInternal(color.Resolve(Color()));
    SetTextEmphasisColorIsCurrentColorInternal(color.IsCurrentColor());
  }

  // -webkit-line-clamp
  static LineClampValue InitialLineClamp() { return LineClampValue(); }
  const LineClampValue& LineClamp() const {
    return rare_non_inherited_data_->line_clamp_;
  }
  void SetLineClamp(LineClampValue c) {
    SET_VAR(rare_non_inherited_data_, line_clamp_, c);
  }

  // -webkit-text-fill-color
  void SetTextFillColor(const StyleColor& color) {
    SetTextFillColorInternal(color.Resolve(Color()));
    SetTextFillColorIsCurrentColorInternal(color.IsCurrentColor());
  }

  // -webkit-text-stroke-color
  void SetTextStrokeColor(const StyleColor& color) {
    SetTextStrokeColorInternal(color.Resolve(Color()));
    SetTextStrokeColorIsCurrentColorInternal(color.IsCurrentColor());
  }

  // caret-color
  void SetCaretColor(const StyleAutoColor& color) {
    SetCaretColorInternal(color.Resolve(Color()));
    SetCaretColorIsCurrentColorInternal(color.IsCurrentColor());
    SetCaretColorIsAutoInternal(color.IsAutoColor());
  }

  // Font properties.
  const Font& GetFont() const;
  void SetFont(const Font&);
  const FontDescription& GetFontDescription() const;
  bool SetFontDescription(const FontDescription&);
  bool HasIdenticalAscentDescentAndLineGap(const ComputedStyle& other) const;

  // font-size
  int FontSize() const;
  float SpecifiedFontSize() const;
  float ComputedFontSize() const;
  LayoutUnit ComputedFontSizeAsFixed() const;

  // font-size-adjust
  float FontSizeAdjust() const;
  bool HasFontSizeAdjust() const;

  // font-weight
  FontWeight GetFontWeight() const;

  // font-stretch
  FontStretch GetFontStretch() const;

  // -webkit-locale
  const AtomicString& Locale() const {
    return LayoutLocale::LocaleString(GetFontDescription().Locale());
  }
  AtomicString LocaleForLineBreakIterator() const;

  // FIXME: Remove letter-spacing/word-spacing and replace them with respective
  // FontBuilder calls.  letter-spacing
  static float InitialLetterWordSpacing() { return 0.0f; }
  float LetterSpacing() const;
  void SetLetterSpacing(float);

  // word-spacing
  float WordSpacing() const;
  void SetWordSpacing(float);

  // SVG properties.
  const SVGComputedStyle& SvgStyle() const { return *svg_style_.Get(); }
  SVGComputedStyle& AccessSVGStyle() { return *svg_style_.Access(); }

  // baseline-shift
  EBaselineShift BaselineShift() const { return SvgStyle().BaselineShift(); }
  const Length& BaselineShiftValue() const {
    return SvgStyle().BaselineShiftValue();
  }
  void SetBaselineShiftValue(const Length& value) {
    SVGComputedStyle& svg_style = AccessSVGStyle();
    svg_style.SetBaselineShift(BS_LENGTH);
    svg_style.SetBaselineShiftValue(value);
  }

  // cx
  void SetCx(const Length& cx) { AccessSVGStyle().SetCx(cx); }

  // cy
  void SetCy(const Length& cy) { AccessSVGStyle().SetCy(cy); }

  // d
  void SetD(RefPtr<StylePath> d) { AccessSVGStyle().SetD(std::move(d)); }

  // x
  void SetX(const Length& x) { AccessSVGStyle().SetX(x); }

  // y
  void SetY(const Length& y) { AccessSVGStyle().SetY(y); }

  // r
  void SetR(const Length& r) { AccessSVGStyle().SetR(r); }

  // rx
  void SetRx(const Length& rx) { AccessSVGStyle().SetRx(rx); }

  // ry
  void SetRy(const Length& ry) { AccessSVGStyle().SetRy(ry); }

  // fill-opacity
  float FillOpacity() const { return SvgStyle().FillOpacity(); }
  void SetFillOpacity(float f) { AccessSVGStyle().SetFillOpacity(f); }

  // Fill utiltiy functions.
  const SVGPaintType& FillPaintType() const {
    return SvgStyle().FillPaintType();
  }
  Color FillPaintColor() const { return SvgStyle().FillPaintColor(); }

  // stop-color
  void SetStopColor(const Color& c) { AccessSVGStyle().SetStopColor(c); }

  // flood-color
  void SetFloodColor(const Color& c) { AccessSVGStyle().SetFloodColor(c); }

  // lighting-color
  void SetLightingColor(const Color& c) {
    AccessSVGStyle().SetLightingColor(c);
  }

  // flood-opacity
  float FloodOpacity() const { return SvgStyle().FloodOpacity(); }
  void SetFloodOpacity(float f) { AccessSVGStyle().SetFloodOpacity(f); }

  // stop-opacity
  float StopOpacity() const { return SvgStyle().StopOpacity(); }
  void SetStopOpacity(float f) { AccessSVGStyle().SetStopOpacity(f); }

  // stroke
  const SVGPaintType& StrokePaintType() const {
    return SvgStyle().StrokePaintType();
  }
  Color StrokePaintColor() const { return SvgStyle().StrokePaintColor(); }

  // stroke-dasharray
  SVGDashArray* StrokeDashArray() const { return SvgStyle().StrokeDashArray(); }
  void SetStrokeDashArray(RefPtr<SVGDashArray> array) {
    AccessSVGStyle().SetStrokeDashArray(std::move(array));
  }

  // stroke-dashoffset
  const Length& StrokeDashOffset() const {
    return SvgStyle().StrokeDashOffset();
  }
  void SetStrokeDashOffset(const Length& d) {
    AccessSVGStyle().SetStrokeDashOffset(d);
  }

  // stroke-miterlimit
  float StrokeMiterLimit() const { return SvgStyle().StrokeMiterLimit(); }
  void SetStrokeMiterLimit(float f) { AccessSVGStyle().SetStrokeMiterLimit(f); }

  // stroke-opacity
  float StrokeOpacity() const { return SvgStyle().StrokeOpacity(); }
  void SetStrokeOpacity(float f) { AccessSVGStyle().SetStrokeOpacity(f); }

  // stroke-width
  const UnzoomedLength& StrokeWidth() const { return SvgStyle().StrokeWidth(); }
  void SetStrokeWidth(const UnzoomedLength& w) {
    AccessSVGStyle().SetStrokeWidth(w);
  }

  // Comparison operators
  // TODO(shend): Replace callers of operator== wth a named method instead, e.g.
  // inheritedEquals().
  bool operator==(const ComputedStyle& other) const;
  bool operator!=(const ComputedStyle& other) const {
    return !(*this == other);
  }

  bool InheritedEqual(const ComputedStyle&) const;
  bool NonInheritedEqual(const ComputedStyle&) const;
  inline bool IndependentInheritedEqual(const ComputedStyle&) const;
  inline bool NonIndependentInheritedEqual(const ComputedStyle&) const;
  bool LoadingCustomFontsEqual(const ComputedStyle&) const;
  bool InheritedDataShared(const ComputedStyle&) const;

  bool HasChildDependentFlags() const {
    return EmptyStateInternal() || HasExplicitlyInheritedProperties();
  }
  void CopyChildDependentFlagsFrom(const ComputedStyle&);

  // Counters.
  const CounterDirectiveMap* GetCounterDirectives() const;
  CounterDirectiveMap& AccessCounterDirectives();
  const CounterDirectives GetCounterDirectives(
      const AtomicString& identifier) const;
  void ClearIncrementDirectives();
  void ClearResetDirectives();

  // Variables.
  static StyleInheritedVariables* InitialInheritedVariables() {
    return nullptr;
  }
  static StyleNonInheritedVariables* InitialNonInheritedVariables() {
    return nullptr;
  }

  StyleInheritedVariables* InheritedVariables() const;
  StyleNonInheritedVariables* NonInheritedVariables() const;

  void SetUnresolvedInheritedVariable(const AtomicString&,
                                      RefPtr<CSSVariableData>);
  void SetUnresolvedNonInheritedVariable(const AtomicString&,
                                         RefPtr<CSSVariableData>);

  void SetResolvedUnregisteredVariable(const AtomicString&,
                                       RefPtr<CSSVariableData>);
  void SetResolvedInheritedVariable(const AtomicString&,
                                    RefPtr<CSSVariableData>,
                                    const CSSValue*);
  void SetResolvedNonInheritedVariable(const AtomicString&,
                                       RefPtr<CSSVariableData>,
                                       const CSSValue*);

  void RemoveVariable(const AtomicString&, bool is_inherited_property);

  // Handles both inherited and non-inherited variables
  CSSVariableData* GetVariable(const AtomicString&) const;

  CSSVariableData* GetVariable(const AtomicString&,
                               bool is_inherited_property) const;

  const CSSValue* GetRegisteredVariable(const AtomicString&,
                                        bool is_inherited_property) const;

  const CSSValue* GetRegisteredVariable(const AtomicString&) const;

  // Animations.
  CSSAnimationData& AccessAnimations();
  const CSSAnimationData* Animations() const {
    return rare_non_inherited_data_->animations_.get();
  }

  // Transitions.
  const CSSTransitionData* Transitions() const {
    return rare_non_inherited_data_->transitions_.get();
  }
  CSSTransitionData& AccessTransitions();

  // Callback selectors.
  const Vector<String>& CallbackSelectors() const {
    return rare_non_inherited_data_->callback_selectors_;
  }
  void AddCallbackSelector(const String& selector);

  // Non-property flags.
  bool EmptyState() const { return EmptyStateInternal(); }
  void SetEmptyState(bool b) {
    SetUnique();
    SetEmptyStateInternal(b);
  }

  bool HasInlineTransform() const {
    return rare_non_inherited_data_->has_inline_transform_;
  }
  void SetHasInlineTransform(bool b) {
    SET_VAR(rare_non_inherited_data_, has_inline_transform_, b);
  }

  bool HasCompositorProxy() const {
    return rare_non_inherited_data_->has_compositor_proxy_;
  }
  void SetHasCompositorProxy(bool b) {
    SET_VAR(rare_non_inherited_data_, has_compositor_proxy_, b);
  }

  bool RequiresAcceleratedCompositingForExternalReasons(bool b) {
    return rare_non_inherited_data_
        ->requires_accelerated_compositing_for_external_reasons_;
  }
  void SetRequiresAcceleratedCompositingForExternalReasons(bool b) {
    SET_VAR(rare_non_inherited_data_,
            requires_accelerated_compositing_for_external_reasons_, b);
  }

  bool HasAuthorBackground() const {
    return rare_non_inherited_data_->has_author_background_;
  };
  void SetHasAuthorBackground(bool author_background) {
    SET_VAR(rare_non_inherited_data_, has_author_background_,
            author_background);
  }

  bool HasAuthorBorder() const {
    return rare_non_inherited_data_->has_author_border_;
  };
  void SetHasAuthorBorder(bool author_border) {
    SET_VAR(rare_non_inherited_data_, has_author_border_, author_border);
  }

  // A stacking context is painted atomically and defines a stacking order,
  // whereas a containing stacking context defines in which order the stacking
  // contexts below are painted.
  // See CSS 2.1, Appendix E (https://www.w3.org/TR/CSS21/zindex.html) for more
  // details.
  bool IsStackingContext() const {
    return rare_non_inherited_data_->is_stacking_context_;
  }
  void SetIsStackingContext(bool b) {
    SET_VAR(rare_non_inherited_data_, is_stacking_context_, b);
  }

  float TextAutosizingMultiplier() const {
    return TextAutosizingMultiplierInternal();
  }
  void SetTextAutosizingMultiplier(float);

  bool SelfOrAncestorHasDirAutoAttribute() const {
    return SelfOrAncestorHasDirAutoAttributeInternal();
  }
  void SetSelfOrAncestorHasDirAutoAttribute(bool v) {
    SetSelfOrAncestorHasDirAutoAttributeInternal(v);
  }

  // Animation flags.
  bool HasCurrentOpacityAnimation() const {
    return rare_non_inherited_data_->has_current_opacity_animation_;
  }
  void SetHasCurrentOpacityAnimation(bool b = true) {
    SET_VAR(rare_non_inherited_data_, has_current_opacity_animation_, b);
  }

  bool HasCurrentTransformAnimation() const {
    return rare_non_inherited_data_->has_current_transform_animation_;
  }
  void SetHasCurrentTransformAnimation(bool b = true) {
    SET_VAR(rare_non_inherited_data_, has_current_transform_animation_, b);
  }

  bool HasCurrentFilterAnimation() const {
    return rare_non_inherited_data_->has_current_filter_animation_;
  }
  void SetHasCurrentFilterAnimation(bool b = true) {
    SET_VAR(rare_non_inherited_data_, has_current_filter_animation_, b);
  }

  bool HasCurrentBackdropFilterAnimation() const {
    return rare_non_inherited_data_->has_current_backdrop_filter_animation_;
  }
  void SetHasCurrentBackdropFilterAnimation(bool b = true) {
    SET_VAR(rare_non_inherited_data_, has_current_backdrop_filter_animation_,
            b);
  }

  bool IsRunningOpacityAnimationOnCompositor() const {
    return rare_non_inherited_data_->running_opacity_animation_on_compositor_;
  }
  void SetIsRunningOpacityAnimationOnCompositor(bool b = true) {
    SET_VAR(rare_non_inherited_data_, running_opacity_animation_on_compositor_,
            b);
  }

  bool IsRunningTransformAnimationOnCompositor() const {
    return rare_non_inherited_data_->running_transform_animation_on_compositor_;
  }
  void SetIsRunningTransformAnimationOnCompositor(bool b = true) {
    SET_VAR(rare_non_inherited_data_,
            running_transform_animation_on_compositor_, b);
  }

  bool IsRunningFilterAnimationOnCompositor() const {
    return rare_non_inherited_data_->running_filter_animation_on_compositor_;
  }
  void SetIsRunningFilterAnimationOnCompositor(bool b = true) {
    SET_VAR(rare_non_inherited_data_, running_filter_animation_on_compositor_,
            b);
  }

  bool IsRunningBackdropFilterAnimationOnCompositor() const {
    return rare_non_inherited_data_
        ->running_backdrop_filter_animation_on_compositor_;
  }
  void SetIsRunningBackdropFilterAnimationOnCompositor(bool b = true) {
    SET_VAR(rare_non_inherited_data_,
            running_backdrop_filter_animation_on_compositor_, b);
  }

  // Column utility functions.
  void ClearMultiCol();
  bool SpecifiesColumns() const {
    return !HasAutoColumnCount() || !HasAutoColumnWidth();
  }
  bool ColumnRuleIsTransparent() const {
    return rare_non_inherited_data_->multi_col_data_->column_rule_
        .IsTransparent();
  }
  bool ColumnRuleEquivalent(const ComputedStyle* other_style) const;
  void InheritColumnPropertiesFrom(const ComputedStyle& parent) {
    rare_non_inherited_data_.Access()->multi_col_data_ =
        parent.rare_non_inherited_data_->multi_col_data_;
  }

  // Flex utility functions.
  bool IsColumnFlexDirection() const {
    return FlexDirection() == kFlowColumn ||
           FlexDirection() == kFlowColumnReverse;
  }
  bool IsReverseFlexDirection() const {
    return FlexDirection() == kFlowRowReverse ||
           FlexDirection() == kFlowColumnReverse;
  }
  bool HasBoxReflect() const { return BoxReflect(); }
  bool ReflectionDataEquivalent(const ComputedStyle& other) const {
    return DataEquivalent(BoxReflect(), other.BoxReflect());
  }

  // Mask utility functions.
  bool HasMask() const {
    return rare_non_inherited_data_->mask_.HasImage() ||
           rare_non_inherited_data_->mask_box_image_.HasImage();
  }
  StyleImage* MaskImage() const {
    return rare_non_inherited_data_->mask_.GetImage();
  }
  FillLayer& AccessMaskLayers() {
    return rare_non_inherited_data_.Access()->mask_;
  }
  const FillLayer& MaskLayers() const {
    return rare_non_inherited_data_->mask_;
  }
  const NinePieceImage& MaskBoxImage() const {
    return rare_non_inherited_data_->mask_box_image_;
  }
  bool MaskBoxImageSlicesFill() const {
    return rare_non_inherited_data_->mask_box_image_.Fill();
  }
  void AdjustMaskLayers() {
    if (MaskLayers().Next()) {
      AccessMaskLayers().CullEmptyLayers();
      AccessMaskLayers().FillUnsetProperties();
    }
  }
  void SetMaskBoxImage(const NinePieceImage& b) {
    SET_VAR(rare_non_inherited_data_, mask_box_image_, b);
  }
  void SetMaskBoxImageSlicesFill(bool fill) {
    rare_non_inherited_data_.Access()->mask_box_image_.SetFill(fill);
  }

  // Text-combine utility functions.
  bool HasTextCombine() const { return TextCombine() != ETextCombine::kNone; }

  // Grid utility functions.
  const Vector<GridTrackSize>& GridAutoRepeatColumns() const {
    return rare_non_inherited_data_->grid_data_->grid_auto_repeat_columns_;
  }
  const Vector<GridTrackSize>& GridAutoRepeatRows() const {
    return rare_non_inherited_data_->grid_data_->grid_auto_repeat_rows_;
  }
  size_t GridAutoRepeatColumnsInsertionPoint() const {
    return rare_non_inherited_data_->grid_data_
        ->auto_repeat_columns_insertion_point_;
  }
  size_t GridAutoRepeatRowsInsertionPoint() const {
    return rare_non_inherited_data_->grid_data_
        ->auto_repeat_rows_insertion_point_;
  }
  AutoRepeatType GridAutoRepeatColumnsType() const {
    return static_cast<AutoRepeatType>(
        rare_non_inherited_data_->grid_data_->auto_repeat_columns_type_);
  }
  AutoRepeatType GridAutoRepeatRowsType() const {
    return static_cast<AutoRepeatType>(
        rare_non_inherited_data_->grid_data_->auto_repeat_rows_type_);
  }
  const NamedGridLinesMap& NamedGridColumnLines() const {
    return rare_non_inherited_data_->grid_data_->named_grid_column_lines_;
  }
  const NamedGridLinesMap& NamedGridRowLines() const {
    return rare_non_inherited_data_->grid_data_->named_grid_row_lines_;
  }
  const OrderedNamedGridLines& OrderedNamedGridColumnLines() const {
    return rare_non_inherited_data_->grid_data_
        ->ordered_named_grid_column_lines_;
  }
  const OrderedNamedGridLines& OrderedNamedGridRowLines() const {
    return rare_non_inherited_data_->grid_data_->ordered_named_grid_row_lines_;
  }
  const NamedGridLinesMap& AutoRepeatNamedGridColumnLines() const {
    return rare_non_inherited_data_->grid_data_
        ->auto_repeat_named_grid_column_lines_;
  }
  const NamedGridLinesMap& AutoRepeatNamedGridRowLines() const {
    return rare_non_inherited_data_->grid_data_
        ->auto_repeat_named_grid_row_lines_;
  }
  const OrderedNamedGridLines& AutoRepeatOrderedNamedGridColumnLines() const {
    return rare_non_inherited_data_->grid_data_
        ->auto_repeat_ordered_named_grid_column_lines_;
  }
  const OrderedNamedGridLines& AutoRepeatOrderedNamedGridRowLines() const {
    return rare_non_inherited_data_->grid_data_
        ->auto_repeat_ordered_named_grid_row_lines_;
  }
  const NamedGridAreaMap& NamedGridArea() const {
    return rare_non_inherited_data_->grid_data_->named_grid_area_;
  }
  size_t NamedGridAreaRowCount() const {
    return rare_non_inherited_data_->grid_data_->named_grid_area_row_count_;
  }
  size_t NamedGridAreaColumnCount() const {
    return rare_non_inherited_data_->grid_data_->named_grid_area_column_count_;
  }
  GridAutoFlow GetGridAutoFlow() const {
    return static_cast<GridAutoFlow>(
        rare_non_inherited_data_->grid_data_->grid_auto_flow_);
  }
  bool IsGridAutoFlowDirectionRow() const {
    return (rare_non_inherited_data_->grid_data_->grid_auto_flow_ &
            kInternalAutoFlowDirectionRow) == kInternalAutoFlowDirectionRow;
  }
  bool IsGridAutoFlowDirectionColumn() const {
    return (rare_non_inherited_data_->grid_data_->grid_auto_flow_ &
            kInternalAutoFlowDirectionColumn) ==
           kInternalAutoFlowDirectionColumn;
  }
  bool IsGridAutoFlowAlgorithmSparse() const {
    return (rare_non_inherited_data_->grid_data_->grid_auto_flow_ &
            kInternalAutoFlowAlgorithmSparse) ==
           kInternalAutoFlowAlgorithmSparse;
  }
  bool IsGridAutoFlowAlgorithmDense() const {
    return (rare_non_inherited_data_->grid_data_->grid_auto_flow_ &
            kInternalAutoFlowAlgorithmDense) == kInternalAutoFlowAlgorithmDense;
  }
  void SetGridAutoRepeatColumns(const Vector<GridTrackSize>& track_sizes) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   grid_auto_repeat_columns_, track_sizes);
  }
  void SetGridAutoRepeatRows(const Vector<GridTrackSize>& track_sizes) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_repeat_rows_,
                   track_sizes);
  }
  void SetGridAutoRepeatColumnsInsertionPoint(const size_t insertion_point) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_columns_insertion_point_, insertion_point);
  }
  void SetGridAutoRepeatRowsInsertionPoint(const size_t insertion_point) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_rows_insertion_point_, insertion_point);
  }
  void SetGridAutoRepeatColumnsType(const AutoRepeatType auto_repeat_type) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_columns_type_, auto_repeat_type);
  }
  void SetGridAutoRepeatRowsType(const AutoRepeatType auto_repeat_type) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, auto_repeat_rows_type_,
                   auto_repeat_type);
  }
  void SetNamedGridColumnLines(
      const NamedGridLinesMap& named_grid_column_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   named_grid_column_lines_, named_grid_column_lines);
  }
  void SetNamedGridRowLines(const NamedGridLinesMap& named_grid_row_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, named_grid_row_lines_,
                   named_grid_row_lines);
  }
  void SetOrderedNamedGridColumnLines(
      const OrderedNamedGridLines& ordered_named_grid_column_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   ordered_named_grid_column_lines_,
                   ordered_named_grid_column_lines);
  }
  void SetOrderedNamedGridRowLines(
      const OrderedNamedGridLines& ordered_named_grid_row_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   ordered_named_grid_row_lines_, ordered_named_grid_row_lines);
  }
  void SetAutoRepeatNamedGridColumnLines(
      const NamedGridLinesMap& named_grid_column_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_named_grid_column_lines_,
                   named_grid_column_lines);
  }
  void SetAutoRepeatNamedGridRowLines(
      const NamedGridLinesMap& named_grid_row_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_named_grid_row_lines_, named_grid_row_lines);
  }
  void SetAutoRepeatOrderedNamedGridColumnLines(
      const OrderedNamedGridLines& ordered_named_grid_column_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_ordered_named_grid_column_lines_,
                   ordered_named_grid_column_lines);
  }
  void SetAutoRepeatOrderedNamedGridRowLines(
      const OrderedNamedGridLines& ordered_named_grid_row_lines) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   auto_repeat_ordered_named_grid_row_lines_,
                   ordered_named_grid_row_lines);
  }
  void SetNamedGridArea(const NamedGridAreaMap& named_grid_area) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, named_grid_area_,
                   named_grid_area);
  }
  void SetNamedGridAreaRowCount(size_t row_count) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   named_grid_area_row_count_, row_count);
  }
  void SetNamedGridAreaColumnCount(size_t column_count) {
    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
                   named_grid_area_column_count_, column_count);
  }

  // align-content utility functions.
  ContentPosition AlignContentPosition() const {
    return rare_non_inherited_data_->align_content_.GetPosition();
  }
  ContentDistributionType AlignContentDistribution() const {
    return rare_non_inherited_data_->align_content_.Distribution();
  }
  OverflowAlignment AlignContentOverflowAlignment() const {
    return rare_non_inherited_data_->align_content_.Overflow();
  }
  void SetAlignContentPosition(ContentPosition position) {
    rare_non_inherited_data_.Access()->align_content_.SetPosition(position);
  }
  void SetAlignContentDistribution(ContentDistributionType distribution) {
    rare_non_inherited_data_.Access()->align_content_.SetDistribution(
        distribution);
  }
  void SetAlignContentOverflow(OverflowAlignment overflow) {
    rare_non_inherited_data_.Access()->align_content_.SetOverflow(overflow);
  }

  // justify-content utility functions.
  ContentPosition JustifyContentPosition() const {
    return rare_non_inherited_data_->justify_content_.GetPosition();
  }
  ContentDistributionType JustifyContentDistribution() const {
    return rare_non_inherited_data_->justify_content_.Distribution();
  }
  OverflowAlignment JustifyContentOverflowAlignment() const {
    return rare_non_inherited_data_->justify_content_.Overflow();
  }
  void SetJustifyContentPosition(ContentPosition position) {
    rare_non_inherited_data_.Access()->justify_content_.SetPosition(position);
  }
  void SetJustifyContentDistribution(ContentDistributionType distribution) {
    rare_non_inherited_data_.Access()->justify_content_.SetDistribution(
        distribution);
  }
  void SetJustifyContentOverflow(OverflowAlignment overflow) {
    rare_non_inherited_data_.Access()->justify_content_.SetOverflow(overflow);
  }

  // align-items utility functions.
  ItemPosition AlignItemsPosition() const {
    return rare_non_inherited_data_->align_items_.GetPosition();
  }
  OverflowAlignment AlignItemsOverflowAlignment() const {
    return rare_non_inherited_data_->align_items_.Overflow();
  }
  void SetAlignItemsPosition(ItemPosition position) {
    rare_non_inherited_data_.Access()->align_items_.SetPosition(position);
  }
  void SetAlignItemsOverflow(OverflowAlignment overflow) {
    rare_non_inherited_data_.Access()->align_items_.SetOverflow(overflow);
  }

  // justify-items utility functions.
  ItemPosition JustifyItemsPosition() const {
    return rare_non_inherited_data_->justify_items_.GetPosition();
  }
  OverflowAlignment JustifyItemsOverflowAlignment() const {
    return rare_non_inherited_data_->justify_items_.Overflow();
  }
  ItemPositionType JustifyItemsPositionType() const {
    return rare_non_inherited_data_->justify_items_.PositionType();
  }
  void SetJustifyItemsPosition(ItemPosition position) {
    rare_non_inherited_data_.Access()->justify_items_.SetPosition(position);
  }
  void SetJustifyItemsOverflow(OverflowAlignment overflow) {
    rare_non_inherited_data_.Access()->justify_items_.SetOverflow(overflow);
  }
  void SetJustifyItemsPositionType(ItemPositionType position_type) {
    rare_non_inherited_data_.Access()->justify_items_.SetPositionType(
        position_type);
  }

  // align-self utility functions.
  ItemPosition AlignSelfPosition() const {
    return rare_non_inherited_data_->align_self_.GetPosition();
  }
  OverflowAlignment AlignSelfOverflowAlignment() const {
    return rare_non_inherited_data_->align_self_.Overflow();
  }
  void SetAlignSelfPosition(ItemPosition position) {
    rare_non_inherited_data_.Access()->align_self_.SetPosition(position);
  }
  void SetAlignSelfOverflow(OverflowAlignment overflow) {
    rare_non_inherited_data_.Access()->align_self_.SetOverflow(overflow);
  }

  // justify-self utility functions.
  ItemPosition JustifySelfPosition() const {
    return rare_non_inherited_data_->justify_self_.GetPosition();
  }
  OverflowAlignment JustifySelfOverflowAlignment() const {
    return rare_non_inherited_data_->justify_self_.Overflow();
  }
  void SetJustifySelfPosition(ItemPosition position) {
    rare_non_inherited_data_.Access()->justify_self_.SetPosition(position);
  }
  void SetJustifySelfOverflow(OverflowAlignment overflow) {
    rare_non_inherited_data_.Access()->justify_self_.SetOverflow(overflow);
  }

  // Writing mode utility functions.
  bool IsHorizontalWritingMode() const {
    return blink::IsHorizontalWritingMode(GetWritingMode());
  }
  bool IsFlippedLinesWritingMode() const {
    return blink::IsFlippedLinesWritingMode(GetWritingMode());
  }
  bool IsFlippedBlocksWritingMode() const {
    return blink::IsFlippedBlocksWritingMode(GetWritingMode());
  }

  // Will-change utility functions.
  bool HasWillChangeCompositingHint() const;
  bool HasWillChangeOpacityHint() const {
    return WillChangeProperties().Contains(CSSPropertyOpacity);
  }
  bool HasWillChangeTransformHint() const;

  // Hyphen utility functions.
  Hyphenation* GetHyphenation() const;
  const AtomicString& HyphenString() const;

  // text-align utility functions.
  using ComputedStyleBase::GetTextAlign;
  ETextAlign GetTextAlign(bool is_last_line) const;

  // Line-height utility functions.
  const Length& SpecifiedLineHeight() const;
  int ComputedLineHeight() const;
  LayoutUnit ComputedLineHeightAsFixed() const;

  // Width/height utility functions.
  const Length& LogicalWidth() const {
    return IsHorizontalWritingMode() ? Width() : Height();
  }
  const Length& LogicalHeight() const {
    return IsHorizontalWritingMode() ? Height() : Width();
  }
  void SetLogicalWidth(const Length& v) {
    if (IsHorizontalWritingMode()) {
      SetWidth(v);
    } else {
      SetHeight(v);
    }
  }

  void SetLogicalHeight(const Length& v) {
    if (IsHorizontalWritingMode()) {
      SetHeight(v);
    } else {
      SetWidth(v);
    }
  }
  const Length& LogicalMaxWidth() const {
    return IsHorizontalWritingMode() ? MaxWidth() : MaxHeight();
  }
  const Length& LogicalMaxHeight() const {
    return IsHorizontalWritingMode() ? MaxHeight() : MaxWidth();
  }
  const Length& LogicalMinWidth() const {
    return IsHorizontalWritingMode() ? MinWidth() : MinHeight();
  }
  const Length& LogicalMinHeight() const {
    return IsHorizontalWritingMode() ? MinHeight() : MinWidth();
  }

  // Margin utility functions.
  bool HasMargin() const {
    return !MarginLeft().IsZero() || !MarginRight().IsZero() ||
           !MarginTop().IsZero() || !MarginBottom().IsZero();
  }
  bool HasMarginBeforeQuirk() const { return MarginBefore().Quirk(); }
  bool HasMarginAfterQuirk() const { return MarginAfter().Quirk(); }
  const Length& MarginBefore() const { return MarginBeforeUsing(this); }
  const Length& MarginAfter() const { return MarginAfterUsing(this); }
  const Length& MarginStart() const { return MarginStartUsing(this); }
  const Length& MarginEnd() const { return MarginEndUsing(this); }
  const Length& MarginOver() const {
    return LengthBox::Over(GetWritingMode(), MarginTop(), MarginRight());
  }
  const Length& MarginUnder() const {
    return LengthBox::Under(GetWritingMode(), MarginBottom(), MarginLeft());
  }
  const Length& MarginStartUsing(const ComputedStyle* other) const {
    return LengthBox::Start(other->GetWritingMode(), other->Direction(),
                            MarginTop(), MarginLeft(), MarginRight(),
                            MarginBottom());
  }
  const Length& MarginEndUsing(const ComputedStyle* other) const {
    return LengthBox::End(other->GetWritingMode(), other->Direction(),
                          MarginTop(), MarginLeft(), MarginRight(),
                          MarginBottom());
  }
  const Length& MarginBeforeUsing(const ComputedStyle* other) const {
    return LengthBox::Before(other->GetWritingMode(), MarginTop(), MarginLeft(),
                             MarginRight());
  }
  const Length& MarginAfterUsing(const ComputedStyle* other) const {
    return LengthBox::After(other->GetWritingMode(), MarginBottom(),
                            MarginLeft(), MarginRight());
  }
  void SetMarginStart(const Length&);
  void SetMarginEnd(const Length&);
  bool MarginEqual(const ComputedStyle& other) const {
    return MarginTop() == other.MarginTop() &&
           MarginLeft() == other.MarginLeft() &&
           MarginRight() == other.MarginRight() &&
           MarginBottom() == other.MarginBottom();
  }

  // Padding utility functions.
  const Length& PaddingBefore() const {
    return LengthBox::Before(GetWritingMode(), PaddingTop(), PaddingLeft(),
                             PaddingRight());
  }
  const Length& PaddingAfter() const {
    return LengthBox::After(GetWritingMode(), PaddingBottom(), PaddingLeft(),
                            PaddingRight());
  }
  const Length& PaddingStart() const {
    return LengthBox::Start(GetWritingMode(), Direction(), PaddingTop(),
                            PaddingLeft(), PaddingRight(), PaddingBottom());
  }
  const Length& PaddingEnd() const {
    return LengthBox::End(GetWritingMode(), Direction(), PaddingTop(),
                          PaddingLeft(), PaddingRight(), PaddingBottom());
  }
  const Length& PaddingOver() const {
    return LengthBox::Over(GetWritingMode(), PaddingTop(), PaddingRight());
  }
  const Length& PaddingUnder() const {
    return LengthBox::Under(GetWritingMode(), PaddingBottom(), PaddingLeft());
  }
  bool HasPadding() const {
    return !PaddingLeft().IsZero() || !PaddingRight().IsZero() ||
           !PaddingTop().IsZero() || !PaddingBottom().IsZero();
  }
  void ResetPadding() {
    SetPaddingTop(kFixed);
    SetPaddingBottom(kFixed);
    SetPaddingLeft(kFixed);
    SetPaddingRight(kFixed);
  }
  void SetPadding(const LengthBox& b) {
    SetPaddingTop(b.top_);
    SetPaddingBottom(b.bottom_);
    SetPaddingLeft(b.left_);
    SetPaddingRight(b.right_);
  }
  bool PaddingEqual(const ComputedStyle& other) const {
    return PaddingTop() == other.PaddingTop() &&
           PaddingLeft() == other.PaddingLeft() &&
           PaddingRight() == other.PaddingRight() &&
           PaddingBottom() == other.PaddingBottom();
  }
  bool PaddingEqual(const LengthBox& other) const {
    return PaddingTop() == other.Top() && PaddingLeft() == other.Left() &&
           PaddingRight() == other.Right() && PaddingBottom() == other.Bottom();
  }

  // Border utility functions
  LayoutRectOutsets ImageOutsets(const NinePieceImage&) const;
  bool HasBorderImageOutsets() const {
    return BorderImage().HasImage() && BorderImage().Outset().NonZero();
  }
  LayoutRectOutsets BorderImageOutsets() const {
    return ImageOutsets(BorderImage());
  }
  bool BorderImageSlicesFill() const { return BorderImage().Fill(); }

  void SetBorderImageSlicesFill(bool);
  const BorderValue BorderLeft() const {
    return BorderValue(BorderLeftStyle(), BorderLeftColor(),
                       BorderLeftWidthInternal().ToFloat(),
                       OutlineStyleIsAuto());
  }
  const BorderValue BorderRight() const {
    return BorderValue(BorderRightStyle(), BorderRightColor(),
                       BorderRightWidthInternal().ToFloat(),
                       OutlineStyleIsAuto());
  }
  const BorderValue BorderTop() const {
    return BorderValue(BorderTopStyle(), BorderTopColor(),
                       BorderTopWidthInternal().ToFloat(),
                       OutlineStyleIsAuto());
  }
  const BorderValue BorderBottom() const {
    return BorderValue(BorderBottomStyle(), BorderBottomColor(),
                       BorderBottomWidthInternal().ToFloat(),
                       OutlineStyleIsAuto());
  }

  bool BorderSizeEquals(const ComputedStyle& o) const {
    return BorderLeftWidthInternal() == o.BorderLeftWidthInternal() &&
           BorderTopWidthInternal() == o.BorderTopWidthInternal() &&
           BorderRightWidthInternal() == o.BorderRightWidthInternal() &&
           BorderBottomWidthInternal() == o.BorderBottomWidthInternal();
  }

  BorderValue BorderBefore() const;
  BorderValue BorderAfter() const;
  BorderValue BorderStart() const;
  BorderValue BorderEnd() const;

  float BorderAfterWidth() const;
  float BorderBeforeWidth() const;
  float BorderEndWidth() const;
  float BorderStartWidth() const;
  float BorderOverWidth() const;
  float BorderUnderWidth() const;

  EBorderStyle BorderAfterStyle() const;
  EBorderStyle BorderBeforeStyle() const;
  EBorderStyle BorderEndStyle() const;
  EBorderStyle BorderStartStyle() const;

  bool HasBorderFill() const {
    return BorderImage().HasImage() && BorderImage().Fill();
  }
  bool HasBorder() const {
    return BorderLeftNonZero() || BorderRightNonZero() || BorderTopNonZero() ||
           BorderBottomNonZero();
  }
  bool HasBorderDecoration() const { return HasBorder() || HasBorderFill(); }
  bool HasBorderRadius() const {
    if (!BorderTopLeftRadius().Width().IsZero())
      return true;
    if (!BorderTopRightRadius().Width().IsZero())
      return true;
    if (!BorderBottomLeftRadius().Width().IsZero())
      return true;
    if (!BorderBottomRightRadius().Width().IsZero())
      return true;
    return false;
  }
  bool HasBorderColorReferencingCurrentColor() const {
    return (BorderLeftNonZero() && BorderLeftColor().IsCurrentColor()) ||
           (BorderRightNonZero() && BorderRightColor().IsCurrentColor()) ||
           (BorderTopNonZero() && BorderTopColor().IsCurrentColor()) ||
           (BorderBottomNonZero() && BorderBottomColor().IsCurrentColor());
  }

  bool RadiiEqual(const ComputedStyle& o) const {
    return BorderTopLeftRadius() == o.BorderTopLeftRadius() &&
           BorderTopRightRadius() == o.BorderTopRightRadius() &&
           BorderBottomLeftRadius() == o.BorderBottomLeftRadius() &&
           BorderBottomRightRadius() == o.BorderBottomRightRadius();
  }

  bool BorderLeftEquals(const ComputedStyle& o) const {
    return BorderLeftWidthInternal() == o.BorderLeftWidthInternal() &&
           BorderLeftStyle() == o.BorderLeftStyle() &&
           BorderLeftColor() == o.BorderLeftColor() &&
           BorderLeftColorIsCurrentColor() == o.BorderLeftColorIsCurrentColor();
  }
  bool BorderLeftEquals(const BorderValue& o) const {
    return BorderLeftWidthInternal().ToFloat() == o.Width() &&
           BorderLeftStyle() == o.Style() &&
           BorderLeftColor() == o.GetColor() &&
           BorderLeftColorIsCurrentColor() == o.ColorIsCurrentColor();
  }

  bool BorderLeftVisuallyEqual(const ComputedStyle& o) const {
    if (BorderLeftStyle() == EBorderStyle::kNone &&
        o.BorderLeftStyle() == EBorderStyle::kNone)
      return true;
    if (BorderLeftStyle() == EBorderStyle::kHidden &&
        o.BorderLeftStyle() == EBorderStyle::kHidden)
      return true;
    return BorderLeftEquals(o);
  }

  bool BorderRightEquals(const ComputedStyle& o) const {
    return BorderRightWidthInternal() == o.BorderRightWidthInternal() &&
           BorderRightStyle() == o.BorderRightStyle() &&
           BorderRightColor() == o.BorderRightColor() &&
           BorderRightColorIsCurrentColor() ==
               o.BorderRightColorIsCurrentColor();
  }
  bool BorderRightEquals(const BorderValue& o) const {
    return BorderRightWidthInternal().ToFloat() == o.Width() &&
           BorderRightStyle() == o.Style() &&
           BorderRightColor() == o.GetColor() &&
           BorderRightColorIsCurrentColor() == o.ColorIsCurrentColor();
  }

  bool BorderRightVisuallyEqual(const ComputedStyle& o) const {
    if (BorderRightStyle() == EBorderStyle::kNone &&
        o.BorderRightStyle() == EBorderStyle::kNone)
      return true;
    if (BorderRightStyle() == EBorderStyle::kHidden &&
        o.BorderRightStyle() == EBorderStyle::kHidden)
      return true;
    return BorderRightEquals(o);
  }

  bool BorderTopVisuallyEqual(const ComputedStyle& o) const {
    if (BorderTopStyle() == EBorderStyle::kNone &&
        o.BorderTopStyle() == EBorderStyle::kNone)
      return true;
    if (BorderTopStyle() == EBorderStyle::kHidden &&
        o.BorderTopStyle() == EBorderStyle::kHidden)
      return true;
    return BorderTopEquals(o);
  }

  bool BorderTopEquals(const ComputedStyle& o) const {
    return BorderTopWidthInternal() == o.BorderTopWidthInternal() &&
           BorderTopStyle() == o.BorderTopStyle() &&
           BorderTopColor() == o.BorderTopColor() &&
           BorderTopColorIsCurrentColor() == o.BorderTopColorIsCurrentColor();
  }
  bool BorderTopEquals(const BorderValue& o) const {
    return BorderTopWidthInternal().ToFloat() == o.Width() &&
           BorderTopStyle() == o.Style() && BorderTopColor() == o.GetColor() &&
           BorderTopColorIsCurrentColor() == o.ColorIsCurrentColor();
  }

  bool BorderBottomVisuallyEqual(const ComputedStyle& o) const {
    if (BorderBottomStyle() == EBorderStyle::kNone &&
        o.BorderBottomStyle() == EBorderStyle::kNone)
      return true;
    if (BorderBottomStyle() == EBorderStyle::kHidden &&
        o.BorderBottomStyle() == EBorderStyle::kHidden)
      return true;
    return BorderBottomEquals(o);
  }

  bool BorderBottomEquals(const ComputedStyle& o) const {
    return BorderBottomWidthInternal() == o.BorderBottomWidthInternal() &&
           BorderBottomStyle() == o.BorderBottomStyle() &&
           BorderBottomColor() == o.BorderBottomColor() &&
           BorderBottomColorIsCurrentColor() ==
               o.BorderBottomColorIsCurrentColor();
  }
  bool BorderBottomEquals(const BorderValue& o) const {
    return BorderBottomWidthInternal().ToFloat() == o.Width() &&
           BorderBottomStyle() == o.Style() &&
           BorderBottomColor() == o.GetColor() &&
           BorderBottomColorIsCurrentColor() == o.ColorIsCurrentColor();
  }

  bool BorderEquals(const ComputedStyle& o) const {
    return BorderLeftEquals(o) && BorderRightEquals(o) && BorderTopEquals(o) &&
           BorderBottomEquals(o) && BorderImage() == o.BorderImage();
  }

  bool BorderVisuallyEqual(const ComputedStyle& o) const {
    return BorderLeftVisuallyEqual(o) && BorderRightVisuallyEqual(o) &&
           BorderTopVisuallyEqual(o) && BorderBottomVisuallyEqual(o) &&
           BorderImage() == o.BorderImage();
  }

  bool BorderVisualOverflowEqual(const ComputedStyle& o) const {
    return BorderImage().Outset() == o.BorderImage().Outset();
  }

  void ResetBorder() {
    ResetBorderImage();
    ResetBorderTop();
    ResetBorderRight();
    ResetBorderBottom();
    ResetBorderLeft();
    ResetBorderTopLeftRadius();
    ResetBorderTopRightRadius();
    ResetBorderBottomLeftRadius();
    ResetBorderBottomRightRadius();
  }

  void ResetBorderTop() {
    SetBorderTopStyle(EBorderStyle::kNone);
    SetBorderTopWidth(3);
    SetBorderTopColorInternal(0);
    SetBorderTopColorIsCurrentColor(true);
  }
  void ResetBorderRight() {
    SetBorderRightStyle(EBorderStyle::kNone);
    SetBorderRightWidth(3);
    SetBorderRightColorInternal(0);
    SetBorderRightColorIsCurrentColor(true);
  }
  void ResetBorderBottom() {
    SetBorderBottomStyle(EBorderStyle::kNone);
    SetBorderBottomWidth(3);
    SetBorderBottomColorInternal(0);
    SetBorderBottomColorIsCurrentColor(true);
  }
  void ResetBorderLeft() {
    SetBorderLeftStyle(EBorderStyle::kNone);
    SetBorderLeftWidth(3);
    SetBorderLeftColorInternal(0);
    SetBorderLeftColorIsCurrentColor(true);
  }

  void SetBorderRadius(const LengthSize& s) {
    SetBorderTopLeftRadius(s);
    SetBorderTopRightRadius(s);
    SetBorderBottomLeftRadius(s);
    SetBorderBottomRightRadius(s);
  }
  void SetBorderRadius(const IntSize& s) {
    SetBorderRadius(
        LengthSize(Length(s.Width(), kFixed), Length(s.Height(), kFixed)));
  }

  FloatRoundedRect GetRoundedBorderFor(
      const LayoutRect& border_rect,
      bool include_logical_left_edge = true,
      bool include_logical_right_edge = true) const;
  FloatRoundedRect GetRoundedInnerBorderFor(
      const LayoutRect& border_rect,
      bool include_logical_left_edge = true,
      bool include_logical_right_edge = true) const;
  FloatRoundedRect GetRoundedInnerBorderFor(
      const LayoutRect& border_rect,
      const LayoutRectOutsets& insets,
      bool include_logical_left_edge,
      bool include_logical_right_edge) const;

  // Float utility functions.
  bool IsFloating() const { return Floating() != EFloat::kNone; }

  // Mix-blend-mode utility functions.
  bool HasBlendMode() const { return BlendMode() != kWebBlendModeNormal; }

  // Motion utility functions.
  bool HasOffset() const {
    return (OffsetPosition().X() != Length(kAuto)) || OffsetPath();
  }

  // Direction utility functions.
  bool IsLeftToRightDirection() const {
    return Direction() == TextDirection::kLtr;
  }

  // Perspective utility functions.
  bool HasPerspective() const {
    return rare_non_inherited_data_->perspective_ > 0;
  }

  // Page size utility functions.
  void ResetPageSizeType() {
    SET_VAR(rare_non_inherited_data_, page_size_type_,
            static_cast<unsigned>(PageSizeType::kAuto));
  }

  // Outline utility functions.
  bool HasOutline() const {
    return OutlineWidth() > 0 && OutlineStyle() > EBorderStyle::kHidden;
  }
  int OutlineOutsetExtent() const;
  float GetOutlineStrokeWidthForFocusRing() const;
  bool HasOutlineWithCurrentColor() const {
    return HasOutline() && OutlineColor().IsCurrentColor();
  }

  // Position utility functions.
  bool HasOutOfFlowPosition() const {
    return GetPosition() == EPosition::kAbsolute ||
           GetPosition() == EPosition::kFixed;
  }
  bool HasInFlowPosition() const {
    return GetPosition() == EPosition::kRelative ||
           GetPosition() == EPosition::kSticky;
  }
  bool HasViewportConstrainedPosition() const {
    return GetPosition() == EPosition::kFixed ||
           GetPosition() == EPosition::kSticky;
  }

  // Clip utility functions.
  const Length& ClipLeft() const { return ClipInternal().Left(); }
  const Length& ClipRight() const { return ClipInternal().Right(); }
  const Length& ClipTop() const { return ClipInternal().Top(); }
  const Length& ClipBottom() const { return ClipInternal().Bottom(); }

  // Offset utility functions.
  // Accessors for positioned object edges that take into account writing mode.
  const Length& LogicalLeft() const {
    return LengthBox::LogicalLeft(GetWritingMode(), Left(), Top());
  }
  const Length& LogicalRight() const {
    return LengthBox::LogicalRight(GetWritingMode(), Right(), Bottom());
  }
  const Length& LogicalTop() const {
    return LengthBox::Before(GetWritingMode(), Top(), Left(), Right());
  }
  const Length& LogicalBottom() const {
    return LengthBox::After(GetWritingMode(), Bottom(), Left(), Right());
  }
  bool OffsetEqual(const ComputedStyle& other) const {
    return Left() == other.Left() && Right() == other.Right() &&
           Top() == other.Top() && Bottom() == other.Bottom();
  }

  // Whether or not a positioned element requires normal flow x/y to be computed
  // to determine its position.
  bool HasAutoLeftAndRight() const {
    return Left().IsAuto() && Right().IsAuto();
  }
  bool HasAutoTopAndBottom() const {
    return Top().IsAuto() && Bottom().IsAuto();
  }
  bool HasStaticInlinePosition(bool horizontal) const {
    return horizontal ? HasAutoLeftAndRight() : HasAutoTopAndBottom();
  }
  bool HasStaticBlockPosition(bool horizontal) const {
    return horizontal ? HasAutoTopAndBottom() : HasAutoLeftAndRight();
  }

  // Content utility functions.
  bool ContentDataEquivalent(const ComputedStyle& other) const {
    return DataEquivalent(GetContentData(), other.GetContentData());
  }

  // Contain utility functions.
  bool ContainsPaint() const {
    return rare_non_inherited_data_->contain_ & kContainsPaint;
  }
  bool ContainsStyle() const {
    return rare_non_inherited_data_->contain_ & kContainsStyle;
  }
  bool ContainsLayout() const {
    return rare_non_inherited_data_->contain_ & kContainsLayout;
  }
  bool ContainsSize() const {
    return rare_non_inherited_data_->contain_ & kContainsSize;
  }

  // Display utility functions.
  bool IsDisplayReplacedType() const {
    return IsDisplayReplacedType(Display());
  }
  bool IsDisplayInlineType() const { return IsDisplayInlineType(Display()); }
  bool IsOriginalDisplayInlineType() const {
    return IsDisplayInlineType(OriginalDisplay());
  }
  bool IsDisplayBlockContainer() const {
    return IsDisplayBlockContainer(Display());
  }
  bool IsDisplayFlexibleOrGridBox() const {
    return IsDisplayFlexibleBox(Display()) || IsDisplayGridBox(Display());
  }
  bool IsDisplayFlexibleBox() const { return IsDisplayFlexibleBox(Display()); }

  // Isolation utility functions.
  bool HasIsolation() const { return Isolation() != EIsolation::kAuto; }

  // Content utility functions.
  bool HasContent() const { return GetContentData(); }

  // Cursor utility functions.
  CursorList* Cursors() const { return CursorDataInternal().Get(); }
  void AddCursor(StyleImage*,
                 bool hot_spot_specified,
                 const IntPoint& hot_spot = IntPoint());
  void SetCursorList(CursorList*);
  void ClearCursorList();

  // Text decoration utility functions.
  void ApplyTextDecorations(const Color& parent_text_decoration_color,
                            bool override_existing_colors);
  void ClearAppliedTextDecorations();
  void RestoreParentTextDecorations(const ComputedStyle& parent_style);
  const Vector<AppliedTextDecoration>& AppliedTextDecorations() const;
  TextDecoration TextDecorationsInEffect() const;

  // Overflow utility functions.

  EOverflow OverflowInlineDirection() const {
    return IsHorizontalWritingMode() ? OverflowX() : OverflowY();
  }
  EOverflow OverflowBlockDirection() const {
    return IsHorizontalWritingMode() ? OverflowY() : OverflowX();
  }

  // It's sufficient to just check one direction, since it's illegal to have
  // visible on only one overflow value.
  bool IsOverflowVisible() const {
    DCHECK(OverflowX() != EOverflow::kVisible || OverflowX() == OverflowY());
    return OverflowX() == EOverflow::kVisible;
  }
  bool IsOverflowPaged() const {
    return OverflowY() == EOverflow::kWebkitPagedX ||
           OverflowY() == EOverflow::kWebkitPagedY;
  }

  // Visibility utility functions.
  bool VisibleToHitTesting() const {
    return Visibility() == EVisibility::kVisible &&
           PointerEvents() != EPointerEvents::kNone;
  }

  // Animation utility functions.
  bool ShouldCompositeForCurrentAnimations() const {
    return HasCurrentOpacityAnimation() || HasCurrentTransformAnimation() ||
           HasCurrentFilterAnimation() || HasCurrentBackdropFilterAnimation();
  }
  bool IsRunningAnimationOnCompositor() const {
    return IsRunningOpacityAnimationOnCompositor() ||
           IsRunningTransformAnimationOnCompositor() ||
           IsRunningFilterAnimationOnCompositor() ||
           IsRunningBackdropFilterAnimationOnCompositor();
  }

  // Opacity utility functions.
  bool HasOpacity() const { return Opacity() < 1.0f; }

  // Table layout utility functions.
  bool IsFixedTableLayout() const {
    return TableLayout() == ETableLayout::kFixed && !LogicalWidth().IsAuto();
  }

  // Filter/transform utility functions.
  bool Has3DTransform() const {
    return rare_non_inherited_data_->transform_data_->transform_operations_
               .Has3DOperation() ||
           (Translate() && Translate()->Z() != 0) ||
           (Rotate() && (Rotate()->X() != 0 || Rotate()->Y() != 0)) ||
           (Scale() && Scale()->Z() != 1);
  }
  bool HasTransform() const {
    return HasTransformOperations() || HasOffset() ||
           HasCurrentTransformAnimation() || Translate() || Rotate() || Scale();
  }
  bool HasTransformOperations() const {
    return !rare_non_inherited_data_->transform_data_->transform_operations_
                .Operations()
                .IsEmpty();
  }
  ETransformStyle3D UsedTransformStyle3D() const {
    return HasGroupingProperty() ? ETransformStyle3D::kFlat
                                 : TransformStyle3D();
  }
  // Returns whether the transform operations for |otherStyle| differ from the
  // operations for this style instance. Note that callers may want to also
  // check hasTransform(), as it is possible for two styles to have matching
  // transform operations but differ in other transform-impacting style
  // respects.
  bool TransformDataEquivalent(const ComputedStyle& other) const {
    return rare_non_inherited_data_->transform_data_ ==
           other.rare_non_inherited_data_->transform_data_;
  }
  bool Preserves3D() const {
    return UsedTransformStyle3D() != ETransformStyle3D::kFlat;
  }
  enum ApplyTransformOrigin {
    kIncludeTransformOrigin,
    kExcludeTransformOrigin
  };
  enum ApplyMotionPath { kIncludeMotionPath, kExcludeMotionPath };
  enum ApplyIndependentTransformProperties {
    kIncludeIndependentTransformProperties,
    kExcludeIndependentTransformProperties
  };
  void ApplyTransform(TransformationMatrix&,
                      const LayoutSize& border_box_data_size,
                      ApplyTransformOrigin,
                      ApplyMotionPath,
                      ApplyIndependentTransformProperties) const;
  void ApplyTransform(TransformationMatrix&,
                      const FloatRect& bounding_box,
                      ApplyTransformOrigin,
                      ApplyMotionPath,
                      ApplyIndependentTransformProperties) const;

  bool HasFilters() const;

  // Returns |true| if any property that renders using filter operations is
  // used (including, but not limited to, 'filter' and 'box-reflect').
  bool HasFilterInducingProperty() const {
    return HasFilter() || HasBoxReflect();
  }

  // Returns |true| if opacity should be considered to have non-initial value
  // for the purpose of creating stacking contexts.
  bool HasNonInitialOpacity() const {
    return HasOpacity() || HasWillChangeOpacityHint() ||
           HasCurrentOpacityAnimation();
  }

  // Returns whether this style contains any grouping property as defined by
  // [css-transforms].  The main purpose of this is to adjust the used value of
  // transform-style property.
  // Note: We currently don't include every grouping property on the spec to
  // maintain backward compatibility.  [css-transforms]
  // https://drafts.csswg.org/css-transforms/#grouping-property-values
  bool HasGroupingProperty() const {
    return !IsOverflowVisible() || HasFilterInducingProperty() ||
           HasNonInitialOpacity();
  }

  // Return true if any transform related property (currently
  // transform/motionPath, transformStyle3D, perspective, or
  // will-change:transform) indicates that we are transforming.
  // will-change:transform should result in the same rendering behavior as
  // having a transform, including the creation of a containing block for fixed
  // position descendants.
  bool HasTransformRelatedProperty() const {
    return HasTransform() || Preserves3D() || HasPerspective() ||
           HasWillChangeTransformHint();
  }

  // Paint utility functions.
  void AddPaintImage(StyleImage*);

  // FIXME: reflections should belong to this helper function but they are
  // currently handled through their self-painting layers. So the layout code
  // doesn't account for them.
  bool HasVisualOverflowingEffect() const {
    return BoxShadow() || HasBorderImageOutsets() || HasOutline();
  }

  // Stacking contexts and positioned elements[1] are stacked (sorted in
  // negZOrderList
  // and posZOrderList) in their enclosing stacking contexts.
  //
  // [1] According to CSS2.1, Appendix E.2.8
  // (https://www.w3.org/TR/CSS21/zindex.html),
  // positioned elements with 'z-index: auto' are "treated as if it created a
  // new stacking context" and z-ordered together with other elements with
  // 'z-index: 0'.  The difference of them from normal stacking contexts is that
  // they don't determine the stacking of the elements underneath them.  (Note:
  // There are also other elements treated as stacking context during painting,
  // but not managed in stacks. See ObjectPainter::PaintAllPhasesAtomically().)
  void UpdateIsStackingContext(bool is_document_element, bool is_in_top_layer);
  bool IsStacked() const {
    return IsStackingContext() || GetPosition() != EPosition::kStatic;
  }

  // Pseudo-styles
  bool HasAnyPublicPseudoStyles() const;
  bool HasPseudoStyle(PseudoId) const;
  void SetHasPseudoStyle(PseudoId);
  bool HasUniquePseudoStyle() const;
  bool HasPseudoElementStyle() const;

  // Note: CanContainAbsolutePositionObjects should return true if
  // CanContainFixedPositionObjects.  We currently never use this value
  // directly, always OR'ing it with CanContainFixedPositionObjects.
  bool CanContainAbsolutePositionObjects() const {
    return GetPosition() != EPosition::kStatic;
  }
  bool CanContainFixedPositionObjects() const {
    return HasTransformRelatedProperty() || ContainsPaint();
  }

  // Whitespace utility functions.
  static bool AutoWrap(EWhiteSpace ws) {
    // Nowrap and pre don't automatically wrap.
    return ws != EWhiteSpace::kNowrap && ws != EWhiteSpace::kPre;
  }

  bool AutoWrap() const { return AutoWrap(WhiteSpace()); }

  static bool PreserveNewline(EWhiteSpace ws) {
    // Normal and nowrap do not preserve newlines.
    return ws != EWhiteSpace::kNormal && ws != EWhiteSpace::kNowrap;
  }

  bool PreserveNewline() const { return PreserveNewline(WhiteSpace()); }

  static bool BorderStyleIsVisible(EBorderStyle style) {
    return style != EBorderStyle::kNone && style != EBorderStyle::kHidden;
  }

  static bool CollapseWhiteSpace(EWhiteSpace ws) {
    // Pre and prewrap do not collapse whitespace.
    return ws != EWhiteSpace::kPre && ws != EWhiteSpace::kPreWrap;
  }

  bool CollapseWhiteSpace() const { return CollapseWhiteSpace(WhiteSpace()); }

  bool IsCollapsibleWhiteSpace(UChar c) const {
    switch (c) {
      case ' ':
      case '\t':
        return CollapseWhiteSpace();
      case '\n':
        return !PreserveNewline();
    }
    return false;
  }
  bool BreakOnlyAfterWhiteSpace() const {
    return WhiteSpace() == EWhiteSpace::kPreWrap ||
           GetLineBreak() == LineBreak::kAfterWhiteSpace;
  }

  bool BreakWords() const {
    return (WordBreak() == EWordBreak::kBreakWord ||
            OverflowWrap() == EOverflowWrap::kBreakWord) &&
           WhiteSpace() != EWhiteSpace::kPre &&
           WhiteSpace() != EWhiteSpace::kNowrap;
  }

  // Text direction utility functions.
  bool ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const {
    return !IsLeftToRightDirection() && IsHorizontalWritingMode();
  }
  bool HasInlinePaginationAxis() const {
    // If the pagination axis is parallel with the writing mode inline axis,
    // columns may be laid out along the inline axis, just like for regular
    // multicol. Otherwise, we need to lay out along the block axis.
    if (IsOverflowPaged()) {
      return (OverflowY() == EOverflow::kWebkitPagedX) ==
             IsHorizontalWritingMode();
    }
    return false;
  }

  // Border utility functions.
  bool BorderObscuresBackground() const;
  void GetBorderEdgeInfo(BorderEdge edges[],
                         bool include_logical_left_edge = true,
                         bool include_logical_right_edge = true) const;

  bool HasBoxDecorations() const {
    return HasBorderDecoration() || HasBorderRadius() || HasOutline() ||
           HasAppearance() || BoxShadow() || HasFilterInducingProperty() ||
           HasBackdropFilter() || Resize() != RESIZE_NONE;
  }

  // "Box decoration background" includes all box decorations and backgrounds
  // that are painted as the background of the object. It includes borders,
  // box-shadows, background-color and background-image, etc.
  bool HasBoxDecorationBackground() const {
    return HasBackground() || HasBorderDecoration() || HasAppearance() ||
           BoxShadow();
  }

  // Background utility functions.
  FillLayer& AccessBackgroundLayers() { return MutableBackgroundInternal(); }
  const FillLayer& BackgroundLayers() const { return BackgroundInternal(); }
  void AdjustBackgroundLayers() {
    if (BackgroundLayers().Next()) {
      AccessBackgroundLayers().CullEmptyLayers();
      AccessBackgroundLayers().FillUnsetProperties();
    }
  }
  bool HasBackgroundRelatedColorReferencingCurrentColor() const {
    if (BackgroundColor().IsCurrentColor() ||
        VisitedLinkBackgroundColor().IsCurrentColor())
      return true;
    if (!BoxShadow())
      return false;
    return ShadowListHasCurrentColor(BoxShadow());
  }
  bool HasBackground() const {
    Color color = VisitedDependentColor(CSSPropertyBackgroundColor);
    if (color.Alpha())
      return true;
    return HasBackgroundImage();
  }

  // Color utility functions.
  // TODO(sashab): Rename this to just getColor(), and add a comment explaining
  // how it works.
  Color VisitedDependentColor(int color_property) const;

  // -webkit-appearance utility functions.
  bool HasAppearance() const { return Appearance() != kNoControlPart; }

  // Other utility functions.
  bool IsStyleAvailable() const;
  bool IsSharable() const;

  bool RequireTransformOrigin(ApplyTransformOrigin apply_origin,
                              ApplyMotionPath) const;

 private:
  void SetVisitedLinkBackgroundColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_background_color_, v);
  }
  void SetVisitedLinkBorderLeftColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_border_left_color_, v);
  }
  void SetVisitedLinkBorderRightColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_border_right_color_, v);
  }
  void SetVisitedLinkBorderBottomColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_border_bottom_color_, v);
  }
  void SetVisitedLinkBorderTopColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_border_top_color_, v);
  }
  void SetVisitedLinkOutlineColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_outline_color_, v);
  }
  void SetVisitedLinkColumnRuleColor(const StyleColor& v) {
    SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_,
                   visited_link_column_rule_color_, v);
  }
  void SetVisitedLinkTextDecorationColor(const StyleColor& v) {
    SET_VAR(rare_non_inherited_data_, visited_link_text_decoration_color_, v);
  }
  void SetVisitedLinkTextEmphasisColor(const StyleColor& color) {
    SetVisitedLinkTextEmphasisColorInternal(color.Resolve(Color()));
    SetVisitedLinkTextEmphasisColorIsCurrentColorInternal(
        color.IsCurrentColor());
  }
  void SetVisitedLinkTextFillColor(const StyleColor& color) {
    SetVisitedLinkTextFillColorInternal(color.Resolve(Color()));
    SetVisitedLinkTextFillColorIsCurrentColorInternal(color.IsCurrentColor());
  }
  void SetVisitedLinkTextStrokeColor(const StyleColor& color) {
    SetVisitedLinkTextStrokeColorInternal(color.Resolve(Color()));
    SetVisitedLinkTextStrokeColorIsCurrentColorInternal(color.IsCurrentColor());
  }
  void SetVisitedLinkCaretColor(const StyleAutoColor& color) {
    SetVisitedLinkCaretColorInternal(color.Resolve(Color()));
    SetVisitedLinkCaretColorIsCurrentColorInternal(color.IsCurrentColor());
    SetVisitedLinkCaretColorIsAutoInternal(color.IsAutoColor());
  }

  static bool IsDisplayBlockContainer(EDisplay display) {
    return display == EDisplay::kBlock || display == EDisplay::kListItem ||
           display == EDisplay::kInlineBlock ||
           display == EDisplay::kFlowRoot || display == EDisplay::kTableCell ||
           display == EDisplay::kTableCaption;
  }

  static bool IsDisplayFlexibleBox(EDisplay display) {
    return display == EDisplay::kFlex || display == EDisplay::kInlineFlex;
  }

  static bool IsDisplayGridBox(EDisplay display) {
    return display == EDisplay::kGrid || display == EDisplay::kInlineGrid;
  }

  static bool IsDisplayReplacedType(EDisplay display) {
    return display == EDisplay::kInlineBlock ||
           display == EDisplay::kWebkitInlineBox ||
           display == EDisplay::kInlineFlex ||
           display == EDisplay::kInlineTable ||
           display == EDisplay::kInlineGrid;
  }

  static bool IsDisplayInlineType(EDisplay display) {
    return display == EDisplay::kInline || IsDisplayReplacedType(display);
  }

  static bool IsDisplayTableType(EDisplay display) {
    return display == EDisplay::kTable || display == EDisplay::kInlineTable ||
           display == EDisplay::kTableRowGroup ||
           display == EDisplay::kTableHeaderGroup ||
           display == EDisplay::kTableFooterGroup ||
           display == EDisplay::kTableRow ||
           display == EDisplay::kTableColumnGroup ||
           display == EDisplay::kTableColumn ||
           display == EDisplay::kTableCell ||
           display == EDisplay::kTableCaption;
  }

  // Color accessors are all private to make sure callers use
  // VisitedDependentColor instead to access them.
  StyleColor BorderLeftColor() const {
    return BorderLeftColorIsCurrentColor()
               ? StyleColor::CurrentColor()
               : StyleColor(BorderLeftColorInternal());
  }
  StyleColor BorderRightColor() const {
    return BorderRightColorIsCurrentColor()
               ? StyleColor::CurrentColor()
               : StyleColor(BorderRightColorInternal());
  }
  StyleColor BorderTopColor() const {
    return BorderTopColorIsCurrentColor()
               ? StyleColor::CurrentColor()
               : StyleColor(BorderTopColorInternal());
  }
  StyleColor BorderBottomColor() const {
    return BorderBottomColorIsCurrentColor()
               ? StyleColor::CurrentColor()
               : StyleColor(BorderBottomColorInternal());
  }

  StyleColor BackgroundColor() const { return BackgroundColorInternal(); }
  StyleAutoColor CaretColor() const {
    if (CaretColorIsCurrentColorInternal())
      return StyleAutoColor::CurrentColor();
    if (CaretColorIsAutoInternal())
      return StyleAutoColor::AutoColor();
    return StyleAutoColor(CaretColorInternal());
  }
  Color GetColor() const;
  StyleColor ColumnRuleColor() const {
    return rare_non_inherited_data_->multi_col_data_->column_rule_.GetColor();
  }
  StyleColor OutlineColor() const {
    return rare_non_inherited_data_->outline_.GetColor();
  }
  StyleColor TextEmphasisColor() const {
    return TextEmphasisColorIsCurrentColorInternal()
               ? StyleColor::CurrentColor()
               : StyleColor(TextEmphasisColorInternal());
  }
  StyleColor TextFillColor() const {
    return TextFillColorIsCurrentColorInternal()
               ? StyleColor::CurrentColor()
               : StyleColor(TextFillColorInternal());
  }
  StyleColor TextStrokeColor() const {
    return TextStrokeColorIsCurrentColorInternal()
               ? StyleColor::CurrentColor()
               : StyleColor(TextStrokeColorInternal());
  }
  StyleAutoColor VisitedLinkCaretColor() const {
    if (VisitedLinkCaretColorIsCurrentColorInternal())
      return StyleAutoColor::CurrentColor();
    if (VisitedLinkCaretColorIsAutoInternal())
      return StyleAutoColor::AutoColor();
    return StyleAutoColor(VisitedLinkCaretColorInternal());
  }
  StyleColor VisitedLinkBackgroundColor() const {
    return rare_non_inherited_data_->visited_link_background_color_;
  }
  StyleColor VisitedLinkBorderLeftColor() const {
    return rare_non_inherited_data_->visited_link_border_left_color_;
  }
  bool VisitedLinkBorderLeftColorHasNotChanged(
      const ComputedStyle& other) const {
    return (VisitedLinkBorderLeftColor() ==
                other.VisitedLinkBorderLeftColor() ||
            !BorderLeftWidth());
  }
  StyleColor VisitedLinkBorderRightColor() const {
    return rare_non_inherited_data_->visited_link_border_right_color_;
  }
  bool VisitedLinkBorderRightColorHasNotChanged(
      const ComputedStyle& other) const {
    return (VisitedLinkBorderRightColor() ==
                other.VisitedLinkBorderRightColor() ||
            !BorderRightWidth());
  }
  StyleColor VisitedLinkBorderBottomColor() const {
    return rare_non_inherited_data_->visited_link_border_bottom_color_;
  }
  bool VisitedLinkBorderBottomColorHasNotChanged(
      const ComputedStyle& other) const {
    return (VisitedLinkBorderBottomColor() ==
                other.VisitedLinkBorderBottomColor() ||
            !BorderBottomWidth());
  }
  StyleColor VisitedLinkBorderTopColor() const {
    return rare_non_inherited_data_->visited_link_border_top_color_;
  }
  bool VisitedLinkBorderTopColorHasNotChanged(
      const ComputedStyle& other) const {
    return (VisitedLinkBorderTopColor() == other.VisitedLinkBorderTopColor() ||
            !BorderTopWidth());
  }
  StyleColor VisitedLinkOutlineColor() const {
    return rare_non_inherited_data_->visited_link_outline_color_;
  }
  bool VisitedLinkOutlineColorHasNotChanged(const ComputedStyle& other) const {
    return (VisitedLinkOutlineColor() == other.VisitedLinkOutlineColor() ||
            !OutlineWidth());
  }
  StyleColor VisitedLinkColumnRuleColor() const {
    return rare_non_inherited_data_->multi_col_data_
        ->visited_link_column_rule_color_;
  }
  StyleColor TextDecorationColor() const {
    return rare_non_inherited_data_->text_decoration_color_;
  }
  StyleColor VisitedLinkTextDecorationColor() const {
    return rare_non_inherited_data_->visited_link_text_decoration_color_;
  }
  StyleColor VisitedLinkTextEmphasisColor() const {
    return VisitedLinkTextEmphasisColorIsCurrentColorInternal()
               ? StyleColor::CurrentColor()
               : StyleColor(VisitedLinkTextEmphasisColorInternal());
  }
  StyleColor VisitedLinkTextFillColor() const {
    return VisitedLinkTextFillColorIsCurrentColorInternal()
               ? StyleColor::CurrentColor()
               : StyleColor(VisitedLinkTextFillColorInternal());
  }
  StyleColor VisitedLinkTextStrokeColor() const {
    return VisitedLinkTextStrokeColorIsCurrentColorInternal()
               ? StyleColor::CurrentColor()
               : StyleColor(VisitedLinkTextStrokeColorInternal());
  }

  StyleColor DecorationColorIncludingFallback(bool visited_link) const;
  Color ColorIncludingFallback(int color_property, bool visited_link) const;

  Color StopColor() const { return SvgStyle().StopColor(); }
  Color FloodColor() const { return SvgStyle().FloodColor(); }
  Color LightingColor() const { return SvgStyle().LightingColor(); }

  void AddAppliedTextDecoration(const AppliedTextDecoration&);
  void OverrideTextDecorationColors(Color propagated_color);
  void ApplyMotionPathTransform(float origin_x,
                                float origin_y,
                                const FloatRect& bounding_box,
                                TransformationMatrix&) const;

  bool ScrollAnchorDisablingPropertyChanged(const ComputedStyle& other,
                                            const StyleDifference&) const;
  bool DiffNeedsFullLayoutAndPaintInvalidation(
      const ComputedStyle& other) const;
  bool DiffNeedsFullLayout(const ComputedStyle& other) const;
  bool DiffNeedsPaintInvalidationSubtree(const ComputedStyle& other) const;
  bool DiffNeedsPaintInvalidationObject(const ComputedStyle& other) const;
  bool DiffNeedsPaintInvalidationObjectForPaintImage(
      const StyleImage*,
      const ComputedStyle& other) const;
  bool DiffNeedsVisualRectUpdate(const ComputedStyle& other) const;
  void UpdatePropertySpecificDifferences(const ComputedStyle& other,
                                         StyleDifference&) const;

  static bool ShadowListHasCurrentColor(const ShadowList*);

  StyleInheritedVariables& MutableInheritedVariables();
  StyleNonInheritedVariables& MutableNonInheritedVariables();

  FRIEND_TEST_ALL_PREFIXES(
      ComputedStyleTest,
      UpdatePropertySpecificDifferencesRespectsTransformAnimation);
};

// FIXME: Reduce/remove the dependency on zoom adjusted int values.
// The float or LayoutUnit versions of layout values should be used.
int AdjustForAbsoluteZoom(int value, float zoom_factor);

inline int AdjustForAbsoluteZoom(int value, const ComputedStyle* style) {
  float zoom_factor = style->EffectiveZoom();
  if (zoom_factor == 1)
    return value;
  return AdjustForAbsoluteZoom(value, zoom_factor);
}

inline float AdjustFloatForAbsoluteZoom(float value,
                                        const ComputedStyle& style) {
  return value / style.EffectiveZoom();
}

inline double AdjustDoubleForAbsoluteZoom(double value,
                                          const ComputedStyle& style) {
  return value / style.EffectiveZoom();
}

inline LayoutUnit AdjustLayoutUnitForAbsoluteZoom(LayoutUnit value,
                                                  const ComputedStyle& style) {
  return LayoutUnit(value / style.EffectiveZoom());
}

inline float AdjustScrollForAbsoluteZoom(float scroll_offset,
                                         float zoom_factor) {
  return scroll_offset / zoom_factor;
}

inline float AdjustScrollForAbsoluteZoom(float scroll_offset,
                                         const ComputedStyle& style) {
  return AdjustScrollForAbsoluteZoom(scroll_offset, style.EffectiveZoom());
}

inline bool ComputedStyle::SetZoom(float f) {
  if (compareEqual(ZoomInternal(), f))
    return false;
  SetZoomInternal(f);
  SetEffectiveZoom(EffectiveZoom() * Zoom());
  return true;
}

inline bool ComputedStyle::SetEffectiveZoom(float f) {
  // Clamp the effective zoom value to a smaller (but hopeful still large
  // enough) range, to avoid overflow in derived computations.
  float clamped_effective_zoom = clampTo<float>(f, 1e-6, 1e6);
  if (compareEqual(EffectiveZoomInternal(), clamped_effective_zoom))
    return false;
  SetEffectiveZoomInternal(clamped_effective_zoom);
  return true;
}

inline bool ComputedStyle::IsSharable() const {
  if (Unique())
    return false;
  if (HasUniquePseudoStyle())
    return false;
  return true;
}

inline bool ComputedStyle::HasAnyPublicPseudoStyles() const {
  return PseudoBitsInternal() != kPseudoIdNone;
}

inline bool ComputedStyle::HasPseudoStyle(PseudoId pseudo) const {
  DCHECK(pseudo >= kFirstPublicPseudoId);
  DCHECK(pseudo < kFirstInternalPseudoId);
  return (1 << (pseudo - kFirstPublicPseudoId)) & PseudoBitsInternal();
}

inline void ComputedStyle::SetHasPseudoStyle(PseudoId pseudo) {
  DCHECK(pseudo >= kFirstPublicPseudoId);
  DCHECK(pseudo < kFirstInternalPseudoId);
  // TODO: Fix up this code. It is hard to understand.
  SetPseudoBitsInternal(static_cast<PseudoId>(
      PseudoBitsInternal() | 1 << (pseudo - kFirstPublicPseudoId)));
}

inline bool ComputedStyle::HasPseudoElementStyle() const {
  return PseudoBitsInternal() & kElementPseudoIdMask;
}

}  // namespace blink

#endif  // ComputedStyle_h
