/*
 * 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 "core/CSSPropertyNames.h"
#include "core/ComputedStyleBase.h"
#include "core/CoreExport.h"
#include "core/style/BorderValue.h"
#include "core/style/ComputedStyleConstants.h"
#include "core/style/CounterDirectives.h"
#include "core/style/DataRef.h"
#include "core/style/LineClampValue.h"
#include "core/style/NinePieceImage.h"
#include "core/style/SVGComputedStyle.h"
#include "core/style/StyleBackgroundData.h"
#include "core/style/StyleBoxData.h"
#include "core/style/StyleContentAlignmentData.h"
#include "core/style/StyleDeprecatedFlexibleBoxData.h"
#include "core/style/StyleDifference.h"
#include "core/style/StyleFilterData.h"
#include "core/style/StyleFlexibleBoxData.h"
#include "core/style/StyleGridData.h"
#include "core/style/StyleGridItemData.h"
#include "core/style/StyleInheritedData.h"
#include "core/style/StyleMultiColData.h"
#include "core/style/StyleOffsetRotation.h"
#include "core/style/StyleRareInheritedData.h"
#include "core/style/StyleRareNonInheritedData.h"
#include "core/style/StyleReflection.h"
#include "core/style/StyleSelfAlignmentData.h"
#include "core/style/StyleSurroundData.h"
#include "core/style/StyleTransformData.h"
#include "core/style/StyleVisualData.h"
#include "core/style/StyleWillChangeData.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/FontDescription.h"
#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/LayoutRectOutsets.h"
#include "platform/graphics/Color.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/text/TextDirection.h"
#include "platform/text/UnicodeBidi.h"
#include "platform/transforms/TransformOperations.h"
#include "wtf/Forward.h"
#include "wtf/LeakAnnotations.h"
#include "wtf/RefCounted.h"
#include "wtf/Vector.h"
#include <memory>

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

#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.color(), value))  \
  group.access()->variable.setColor(value)

namespace blink {

using std::max;

class FilterOperations;

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

class ContentData;

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

// ComputedStyle stores the final style for an element and provides the
// interface between the style engine and the rest of Blink.
//
// It contains all the resolved styles for an element, and is densely packed and
// optimized for memory and performance. Enums and small fields are packed in
// bit fields, while large fields are stored in pointers and shared where not
// modified from their parent value (see the DataRef class).
//
// Currently, ComputedStyle is hand-written and ComputedStyleBase is generated.
// Over time, methods will be moved to ComputedStyleBase and the generator will
// be expanded to handle more and more types of properties. Eventually, all
// methods will be on ComputedStyleBase (with custom methods defined in a class
// such as ComputedStyleBase.cpp) and ComputedStyle will be removed.
class CORE_EXPORT ComputedStyle : public ComputedStyleBase,
                                  public RefCounted<ComputedStyle> {
  friend class
      AnimatedStyleBuilder;  // Used by Web Animations CSS. Sets the color styles
  friend class
      CSSAnimatableValueFactory;  // Used by Web Animations CSS. Gets visited and unvisited colors separately.
  friend class
      CSSPropertyEquality;         // Used by CSS animations. We can't allow them to animate based off visited colors.
  friend class ApplyStyleCommand;  // Editing has to only reveal unvisited info.
  friend class EditingStyle;       // Editing has to only reveal unvisited info.
  friend class
      ComputedStyleCSSValueMapping;  // Needs to be able to see visited and unvisited colors for devtools.
  friend class StyleBuilderFunctions;  // Sets color styles
  friend class
      CachedUAStyle;  // Saves Border/Background information for later comparison.
  friend class
      ColorPropertyFunctions;  // Accesses visited and unvisited colors.

  // 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:
  // non-inherited attributes
  DataRef<StyleBoxData> m_box;
  DataRef<StyleVisualData> m_visual;
  DataRef<StyleBackgroundData> m_background;
  DataRef<StyleSurroundData> m_surround;
  DataRef<StyleRareNonInheritedData> m_rareNonInheritedData;

  // inherited attributes
  DataRef<StyleRareInheritedData> m_rareInheritedData;
  DataRef<StyleInheritedData> m_styleInheritedData;

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

  DataRef<SVGComputedStyle> m_svgStyle;

  // !START SYNC!: Keep this in sync with the copy constructor in ComputedStyle.cpp and implicitlyInherited() in StyleResolver.cpp

  // inherit
  struct InheritedData {
    bool operator==(const InheritedData& other) const {
      return compareEqualIndependent(other) &&
             compareEqualNonIndependent(other);
    }

    bool operator!=(const InheritedData& other) const {
      return !(*this == other);
    }

    inline bool compareEqualIndependent(const InheritedData& other) const {
      // These must match the properties tagged 'independent' in
      // CSSProperties.in.
      // TODO(sashab): Generate this function.
      return (m_pointerEvents == other.m_pointerEvents);
    }

    inline bool compareEqualNonIndependent(const InheritedData& other) const {
      return (m_emptyCells == other.m_emptyCells) &&
             (m_captionSide == other.m_captionSide) &&
             (m_listStyleType == other.m_listStyleType) &&
             (m_listStylePosition == other.m_listStylePosition) &&
             (m_textAlign == other.m_textAlign) &&
             (m_textTransform == other.m_textTransform) &&
             (m_textUnderline == other.m_textUnderline) &&
             (m_cursorStyle == other.m_cursorStyle) &&
             (m_direction == other.m_direction) &&
             (m_whiteSpace == other.m_whiteSpace) &&
             (m_borderCollapse == other.m_borderCollapse) &&
             (m_boxDirection == other.m_boxDirection) &&
             (m_rtlOrdering == other.m_rtlOrdering) &&
             (m_printColorAdjust == other.m_printColorAdjust) &&
             (m_insideLink == other.m_insideLink) &&
             (m_writingMode == other.m_writingMode);
    }

    unsigned m_emptyCells : 1;         // EEmptyCells
    unsigned m_captionSide : 2;        // ECaptionSide
    unsigned m_listStyleType : 7;      // EListStyleType
    unsigned m_listStylePosition : 1;  // EListStylePosition
    unsigned m_textAlign : 4;          // ETextAlign
    unsigned m_textTransform : 2;      // ETextTransform
    unsigned m_textUnderline : 1;
    unsigned m_cursorStyle : 6;     // ECursor
    unsigned m_direction : 1;       // TextDirection
    unsigned m_whiteSpace : 3;      // EWhiteSpace
    unsigned m_borderCollapse : 1;  // EBorderCollapse
    unsigned
        m_boxDirection : 1;  // EBoxDirection (CSS3 box_direction property, flexible box layout module)
    // 32 bits

    // non CSS2 inherited
    unsigned m_rtlOrdering : 1;  // Order
    unsigned m_printColorAdjust : PrintColorAdjustBits;
    unsigned m_pointerEvents : 4;  // EPointerEvents
    unsigned m_insideLink : 2;     // EInsideLink

    // CSS Text Layout Module Level 3: Vertical writing support
    unsigned m_writingMode : 2;  // WritingMode
                                 // 42 bits
  } m_inheritedData;

  // don't inherit
  struct NonInheritedData {
    // Compare computed styles, differences in inherited bits or other flags
    // should not cause an inequality.
    bool operator==(const NonInheritedData& other) const {
      return m_effectiveDisplay == other.m_effectiveDisplay &&
             m_originalDisplay == other.m_originalDisplay &&
             m_overflowAnchor == other.m_overflowAnchor &&
             m_overflowX == other.m_overflowX &&
             m_overflowY == other.m_overflowY &&
             m_verticalAlign == other.m_verticalAlign &&
             m_clear == other.m_clear && m_position == other.m_position &&
             m_tableLayout == other.m_tableLayout &&
             m_unicodeBidi == other.m_unicodeBidi
             // hasViewportUnits
             && m_breakBefore == other.m_breakBefore &&
             m_breakAfter == other.m_breakAfter &&
             m_breakInside == other.m_breakInside;
      // styleType
      // pseudoBits
      // explicitInheritance
      // unique
      // emptyState
      // affectedByFocus
      // affectedByHover
      // affectedByActive
      // affectedByDrag
      // isLink
      // isInherited flags
    }

    bool operator!=(const NonInheritedData& other) const {
      return !(*this == other);
    }

    unsigned m_effectiveDisplay : 5;  // EDisplay
    unsigned m_originalDisplay : 5;   // EDisplay
    unsigned m_overflowAnchor : 2;    // EOverflowAnchor
    unsigned m_overflowX : 3;         // EOverflow
    unsigned m_overflowY : 3;         // EOverflow
    unsigned m_verticalAlign : 4;     // EVerticalAlign
    unsigned m_clear : 2;             // EClear
    unsigned m_position : 3;          // EPosition
    unsigned m_tableLayout : 1;       // ETableLayout
    unsigned m_unicodeBidi : 3;       // EUnicodeBidi

    // This is set if we used viewport units when resolving a length.
    // It is mutable so we can pass around const ComputedStyles to resolve lengths.
    mutable unsigned m_hasViewportUnits : 1;

    // 32 bits

    unsigned m_breakBefore : 4;  // EBreak
    unsigned m_breakAfter : 4;   // EBreak
    unsigned m_breakInside : 2;  // EBreak

    unsigned m_styleType : 6;  // PseudoId
    unsigned m_pseudoBits : 8;
    unsigned
        m_explicitInheritance : 1;  // Explicitly inherits a non-inherited property
    unsigned
        m_variableReference : 1;  // A non-inherited property references a variable or @apply is used.
    unsigned m_unique : 1;  // Style can not be shared.

    unsigned m_emptyState : 1;

    unsigned m_affectedByFocus : 1;
    unsigned m_affectedByHover : 1;
    unsigned m_affectedByActive : 1;
    unsigned m_affectedByDrag : 1;

    // 64 bits

    unsigned m_isLink : 1;

    mutable unsigned m_hasRemUnits : 1;

    // For each independent inherited property, store a 1 if the stored
    // value was inherited from its parent, or 0 if it is explicitly set on
    // this element.
    // Eventually, all properties will have a bit in here to store whether
    // they were inherited from their parent or not.
    // Although two ComputedStyles are equal if their nonInheritedData is
    // equal regardless of the isInherited flags, this struct is stored next
    // to the existing flags to take advantage of packing as much as possible.
    // TODO(sashab): Move these flags closer to inheritedData so that it's
    // clear which inherited properties have a flag stored and which don't.
    // Keep this list of fields in sync with:
    // - setBitDefaults()
    // - The ComputedStyle setter, which must take an extra boolean parameter and set this
    // - propagateIndependentInheritedProperties() in ComputedStyle.cpp
    // - The compareEqual() methods in the corresponding class
    // InheritedFlags
    unsigned m_isPointerEventsInherited : 1;
    unsigned m_isVisibilityInherited : 1;

    // If you add more style bits here, you will also need to update ComputedStyle::copyNonInheritedFromCached()
    // 68 bits
  } m_nonInheritedData;

  // !END SYNC!

  void setBitDefaults() {
    ComputedStyleBase::setBitDefaults();
    m_inheritedData.m_emptyCells = static_cast<unsigned>(initialEmptyCells());
    m_inheritedData.m_captionSide = static_cast<unsigned>(initialCaptionSide());
    m_inheritedData.m_listStyleType = initialListStyleType();
    m_inheritedData.m_listStylePosition =
        static_cast<unsigned>(initialListStylePosition());
    m_inheritedData.m_textAlign = initialTextAlign();
    m_inheritedData.m_textTransform = initialTextTransform();
    m_inheritedData.m_textUnderline = false;
    m_inheritedData.m_cursorStyle = initialCursor();
    m_inheritedData.m_direction = initialDirection();
    m_inheritedData.m_whiteSpace = initialWhiteSpace();
    m_inheritedData.m_borderCollapse = initialBorderCollapse();
    m_inheritedData.m_rtlOrdering = initialRTLOrdering();
    m_inheritedData.m_boxDirection = initialBoxDirection();
    m_inheritedData.m_printColorAdjust = initialPrintColorAdjust();
    m_inheritedData.m_pointerEvents = initialPointerEvents();
    m_inheritedData.m_insideLink = NotInsideLink;
    m_inheritedData.m_writingMode = initialWritingMode();

    m_nonInheritedData.m_effectiveDisplay =
        m_nonInheritedData.m_originalDisplay =
            static_cast<unsigned>(initialDisplay());
    m_nonInheritedData.m_overflowAnchor = initialOverflowAnchor();
    m_nonInheritedData.m_overflowX = initialOverflowX();
    m_nonInheritedData.m_overflowY = initialOverflowY();
    m_nonInheritedData.m_verticalAlign = initialVerticalAlign();
    m_nonInheritedData.m_clear = initialClear();
    m_nonInheritedData.m_position = initialPosition();
    m_nonInheritedData.m_tableLayout = initialTableLayout();
    m_nonInheritedData.m_unicodeBidi = initialUnicodeBidi();
    m_nonInheritedData.m_breakBefore = initialBreakBefore();
    m_nonInheritedData.m_breakAfter = initialBreakAfter();
    m_nonInheritedData.m_breakInside = initialBreakInside();
    m_nonInheritedData.m_styleType = PseudoIdNone;
    m_nonInheritedData.m_pseudoBits = 0;
    m_nonInheritedData.m_explicitInheritance = false;
    m_nonInheritedData.m_variableReference = false;
    m_nonInheritedData.m_unique = false;
    m_nonInheritedData.m_emptyState = false;
    m_nonInheritedData.m_hasViewportUnits = false;
    m_nonInheritedData.m_affectedByFocus = false;
    m_nonInheritedData.m_affectedByHover = false;
    m_nonInheritedData.m_affectedByActive = false;
    m_nonInheritedData.m_affectedByDrag = false;
    m_nonInheritedData.m_isLink = false;
    m_nonInheritedData.m_hasRemUnits = false;

    // All independently inherited properties default to being inherited.
    m_nonInheritedData.m_isPointerEventsInherited = true;
    m_nonInheritedData.m_isVisibilityInherited = true;
  }

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

  enum InitialStyleTag { InitialStyle };
  ALWAYS_INLINE explicit ComputedStyle(InitialStyleTag);
  ALWAYS_INLINE ComputedStyle(const ComputedStyle&);

  static PassRefPtr<ComputedStyle> createInitialStyle();
  static inline ComputedStyle& mutableInitialStyle() {
    LEAK_SANITIZER_DISABLED_SCOPE;
    DEFINE_STATIC_REF(ComputedStyle, s_initialStyle,
                      (ComputedStyle::createInitialStyle()));
    return *s_initialStyle;
  }

 public:
  static PassRefPtr<ComputedStyle> create();
  static PassRefPtr<ComputedStyle> createAnonymousStyleWithDisplay(
      const ComputedStyle& parentStyle,
      EDisplay);
  static PassRefPtr<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* oldStyle,
                                                const ComputedStyle* newStyle);

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

  ContentPosition resolvedJustifyContentPosition(
      const StyleContentAlignmentData& normalValueBehavior) const;
  ContentDistributionType resolvedJustifyContentDistribution(
      const StyleContentAlignmentData& normalValueBehavior) const;
  ContentPosition resolvedAlignContentPosition(
      const StyleContentAlignmentData& normalValueBehavior) const;
  ContentDistributionType resolvedAlignContentDistribution(
      const StyleContentAlignmentData& normalValueBehavior) const;
  StyleSelfAlignmentData resolvedAlignItems(
      ItemPosition normalValueBehaviour) const;
  StyleSelfAlignmentData resolvedAlignSelf(
      ItemPosition normalValueBehaviour,
      const ComputedStyle* parentStyle = nullptr) const;
  StyleSelfAlignmentData resolvedJustifyItems(
      ItemPosition normalValueBehaviour) const;
  StyleSelfAlignmentData resolvedJustifySelf(
      ItemPosition normalValueBehaviour,
      const ComputedStyle* parentStyle = nullptr) const;

  StyleDifference visualInvalidationDiff(const ComputedStyle&) const;

  void inheritFrom(const ComputedStyle& inheritParent,
                   IsAtShadowBoundary = NotAtShadowBoundary);
  void copyNonInheritedFromCached(const ComputedStyle&);

  PseudoId styleType() const {
    return static_cast<PseudoId>(m_nonInheritedData.m_styleType);
  }
  void setStyleType(PseudoId styleType) {
    m_nonInheritedData.m_styleType = styleType;
  }

  ComputedStyle* getCachedPseudoStyle(PseudoId) const;
  ComputedStyle* addCachedPseudoStyle(PassRefPtr<ComputedStyle>);
  void removeCachedPseudoStyle(PseudoId);

  const PseudoStyleCache* cachedPseudoStyles() const {
    return m_cachedPseudoStyles.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(ContentPositionNormal,
                                     ContentDistributionDefault,
                                     OverflowAlignmentDefault);
  }

  // align-content (aka -webkit-align-content)
  const StyleContentAlignmentData& alignContent() const {
    return m_rareNonInheritedData->m_alignContent;
  }
  void setAlignContent(const StyleContentAlignmentData& data) {
    SET_VAR(m_rareNonInheritedData, m_alignContent, data);
  }

  // justify-content (aka -webkit-justify-content)
  const StyleContentAlignmentData& justifyContent() const {
    return m_rareNonInheritedData->m_justifyContent;
  }
  void setJustifyContent(const StyleContentAlignmentData& data) {
    SET_VAR(m_rareNonInheritedData, m_justifyContent, data);
  }

  // Default-Alignment properties.
  static StyleSelfAlignmentData initialDefaultAlignment() {
    return StyleSelfAlignmentData(RuntimeEnabledFeatures::cssGridLayoutEnabled()
                                      ? ItemPositionNormal
                                      : ItemPositionStretch,
                                  OverflowAlignmentDefault);
  }

  // align-items (aka -webkit-align-items)
  const StyleSelfAlignmentData& alignItems() const {
    return m_rareNonInheritedData->m_alignItems;
  }
  void setAlignItems(const StyleSelfAlignmentData& data) {
    SET_VAR(m_rareNonInheritedData, m_alignItems, data);
  }

  // justify-items
  const StyleSelfAlignmentData& justifyItems() const {
    return m_rareNonInheritedData->m_justifyItems;
  }
  void setJustifyItems(const StyleSelfAlignmentData& data) {
    SET_VAR(m_rareNonInheritedData, m_justifyItems, data);
  }

  // Self-Alignment properties.
  static StyleSelfAlignmentData initialSelfAlignment() {
    return StyleSelfAlignmentData(ItemPositionAuto, OverflowAlignmentDefault);
  }

  // align-self (aka -webkit-align-self)
  const StyleSelfAlignmentData& alignSelf() const {
    return m_rareNonInheritedData->m_alignSelf;
  }
  void setAlignSelf(const StyleSelfAlignmentData& data) {
    SET_VAR(m_rareNonInheritedData, m_alignSelf, data);
  }

  // justify-self
  const StyleSelfAlignmentData& justifySelf() const {
    return m_rareNonInheritedData->m_justifySelf;
  }
  void setJustifySelf(const StyleSelfAlignmentData& data) {
    SET_VAR(m_rareNonInheritedData, m_justifySelf, data);
  }

  // Filter properties.

  // backdrop-filter
  static const FilterOperations& initialBackdropFilter();
  const FilterOperations& backdropFilter() const {
    return m_rareNonInheritedData->m_backdropFilter->m_operations;
  }
  FilterOperations& mutableBackdropFilter() {
    return m_rareNonInheritedData.access()
        ->m_backdropFilter.access()
        ->m_operations;
  }
  bool hasBackdropFilter() const {
    return !m_rareNonInheritedData->m_backdropFilter->m_operations.operations()
                .isEmpty();
  }
  void setBackdropFilter(const FilterOperations& ops) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_backdropFilter, m_operations, ops);
  }

  // filter (aka -webkit-filter)
  static const FilterOperations& initialFilter();
  FilterOperations& mutableFilter() {
    return m_rareNonInheritedData.access()->m_filter.access()->m_operations;
  }
  const FilterOperations& filter() const {
    return m_rareNonInheritedData->m_filter->m_operations;
  }
  bool hasFilter() const {
    return !m_rareNonInheritedData->m_filter->m_operations.operations()
                .isEmpty();
  }
  void setFilter(const FilterOperations& ops) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_filter, m_operations, ops);
  }

  // backface-visibility (aka -webkit-backface-visibility)
  static EBackfaceVisibility initialBackfaceVisibility() {
    return BackfaceVisibilityVisible;
  }
  EBackfaceVisibility backfaceVisibility() const {
    return static_cast<EBackfaceVisibility>(
        m_rareNonInheritedData->m_backfaceVisibility);
  }
  void setBackfaceVisibility(EBackfaceVisibility b) {
    SET_VAR(m_rareNonInheritedData, m_backfaceVisibility, b);
  }

  // Background properties.
  // background-color
  static Color initialBackgroundColor() { return Color::transparent; }
  void setBackgroundColor(const StyleColor& v) {
    SET_VAR(m_background, m_color, v);
  }

  // background-image
  bool hasBackgroundImage() const {
    return m_background->background().hasImage();
  }
  bool hasFixedBackgroundImage() const {
    return m_background->background().hasFixedImage();
  }
  bool hasEntirelyFixedBackground() const;

  // background-clip
  EFillBox backgroundClip() const {
    return static_cast<EFillBox>(m_background->background().clip());
  }

  // Border properties.
  // -webkit-border-image
  static NinePieceImage initialNinePieceImage() { return NinePieceImage(); }
  const NinePieceImage& borderImage() const {
    return m_surround->border.image();
  }
  void setBorderImage(const NinePieceImage& b) {
    SET_VAR(m_surround, border.m_image, b);
  }

  // border-image-slice
  const LengthBox& borderImageSlices() const {
    return m_surround->border.image().imageSlices();
  }
  void setBorderImageSlices(const LengthBox&);

  // border-image-source
  static StyleImage* initialBorderImageSource() { return 0; }
  StyleImage* borderImageSource() const {
    return m_surround->border.image().image();
  }
  void setBorderImageSource(StyleImage*);

  // border-image-width
  const BorderImageLengthBox& borderImageWidth() const {
    return m_surround->border.image().borderSlices();
  }
  void setBorderImageWidth(const BorderImageLengthBox&);

  // border-image-outset
  const BorderImageLengthBox& borderImageOutset() const {
    return m_surround->border.image().outset();
  }
  void setBorderImageOutset(const BorderImageLengthBox&);

  // Border width properties.
  static unsigned initialBorderWidth() { return 3; }

  // border-top-width
  int borderTopWidth() const { return m_surround->border.borderTopWidth(); }
  void setBorderTopWidth(unsigned v) {
    SET_VAR(m_surround, border.m_top.m_width, v);
  }

  // border-bottom-width
  int borderBottomWidth() const {
    return m_surround->border.borderBottomWidth();
  }
  void setBorderBottomWidth(unsigned v) {
    SET_VAR(m_surround, border.m_bottom.m_width, v);
  }

  // border-left-width
  int borderLeftWidth() const { return m_surround->border.borderLeftWidth(); }
  void setBorderLeftWidth(unsigned v) {
    SET_VAR(m_surround, border.m_left.m_width, v);
  }

  // border-right-width
  int borderRightWidth() const { return m_surround->border.borderRightWidth(); }
  void setBorderRightWidth(unsigned v) {
    SET_VAR(m_surround, border.m_right.m_width, v);
  }

  // Border style properties.
  static EBorderStyle initialBorderStyle() { return BorderStyleNone; }

  // border-top-style
  EBorderStyle borderTopStyle() const {
    return m_surround->border.top().style();
  }
  void setBorderTopStyle(EBorderStyle v) {
    SET_VAR(m_surround, border.m_top.m_style, v);
  }

  // border-right-style
  EBorderStyle borderRightStyle() const {
    return m_surround->border.right().style();
  }
  void setBorderRightStyle(EBorderStyle v) {
    SET_VAR(m_surround, border.m_right.m_style, v);
  }

  // border-left-style
  EBorderStyle borderLeftStyle() const {
    return m_surround->border.left().style();
  }
  void setBorderLeftStyle(EBorderStyle v) {
    SET_VAR(m_surround, border.m_left.m_style, v);
  }

  // border-bottom-style
  EBorderStyle borderBottomStyle() const {
    return m_surround->border.bottom().style();
  }
  void setBorderBottomStyle(EBorderStyle v) {
    SET_VAR(m_surround, border.m_bottom.m_style, v);
  }

  // Border color properties.
  // border-left-color
  void setBorderLeftColor(const StyleColor& v) {
    SET_BORDERVALUE_COLOR(m_surround, border.m_left, v);
  }

  // border-right-color
  void setBorderRightColor(const StyleColor& v) {
    SET_BORDERVALUE_COLOR(m_surround, border.m_right, v);
  }

  // border-top-color
  void setBorderTopColor(const StyleColor& v) {
    SET_BORDERVALUE_COLOR(m_surround, border.m_top, v);
  }

  // border-bottom-color
  void setBorderBottomColor(const StyleColor& v) {
    SET_BORDERVALUE_COLOR(m_surround, border.m_bottom, v);
  }

  // Border radius properties.
  static LengthSize initialBorderRadius() {
    return LengthSize(Length(0, Fixed), Length(0, Fixed));
  }

  // border-top-left-radius (aka -webkit-border-top-left-radius)
  const LengthSize& borderTopLeftRadius() const {
    return m_surround->border.topLeft();
  }
  void setBorderTopLeftRadius(const LengthSize& s) {
    SET_VAR(m_surround, border.m_topLeft, s);
  }

  // border-top-right-radius (aka -webkit-border-top-right-radius)
  const LengthSize& borderTopRightRadius() const {
    return m_surround->border.topRight();
  }
  void setBorderTopRightRadius(const LengthSize& s) {
    SET_VAR(m_surround, border.m_topRight, s);
  }

  // border-bottom-left-radius (aka -webkit-border-bottom-left-radius)
  const LengthSize& borderBottomLeftRadius() const {
    return m_surround->border.bottomLeft();
  }
  void setBorderBottomLeftRadius(const LengthSize& s) {
    SET_VAR(m_surround, border.m_bottomLeft, s);
  }

  // border-bottom-right-radius (aka -webkit-border-bottom-right-radius)
  const LengthSize& borderBottomRightRadius() const {
    return m_surround->border.bottomRight();
  }
  void setBorderBottomRightRadius(const LengthSize& s) {
    SET_VAR(m_surround, border.m_bottomRight, s);
  }

  // Offset properties.
  static Length initialOffset() { return Length(); }

  // left
  const Length& left() const { return m_surround->offset.left(); }
  void setLeft(const Length& v) { SET_VAR(m_surround, offset.m_left, v); }

  // right
  const Length& right() const { return m_surround->offset.right(); }
  void setRight(const Length& v) { SET_VAR(m_surround, offset.m_right, v); }

  // top
  const Length& top() const { return m_surround->offset.top(); }
  void setTop(const Length& v) { SET_VAR(m_surround, offset.m_top, v); }

  // bottom
  const Length& bottom() const { return m_surround->offset.bottom(); }
  void setBottom(const Length& v) { SET_VAR(m_surround, offset.m_bottom, v); }

  // box-shadow (aka -webkit-box-shadow)
  static ShadowList* initialBoxShadow() { return 0; }
  ShadowList* boxShadow() const {
    return m_rareNonInheritedData->m_boxShadow.get();
  }
  void setBoxShadow(PassRefPtr<ShadowList>);

  // box-sizing (aka -webkit-box-sizing)
  static EBoxSizing initialBoxSizing() { return BoxSizingContentBox; }
  EBoxSizing boxSizing() const { return m_box->boxSizing(); }
  void setBoxSizing(EBoxSizing s) { SET_VAR(m_box, m_boxSizing, s); }

  // clear
  static EClear initialClear() { return ClearNone; }
  EClear clear() const {
    return static_cast<EClear>(m_nonInheritedData.m_clear);
  }
  void setClear(EClear v) { m_nonInheritedData.m_clear = v; }

  // Page break properties.
  // break-after (shorthand for page-break-after and -webkit-column-break-after)
  static EBreak initialBreakAfter() { return BreakAuto; }
  EBreak breakAfter() const {
    return static_cast<EBreak>(m_nonInheritedData.m_breakAfter);
  }
  void setBreakAfter(EBreak b) {
    DCHECK_LE(b, BreakValueLastAllowedForBreakAfterAndBefore);
    m_nonInheritedData.m_breakAfter = b;
  }

  // break-before (shorthand for page-break-before and -webkit-column-break-before)
  static EBreak initialBreakBefore() { return BreakAuto; }
  EBreak breakBefore() const {
    return static_cast<EBreak>(m_nonInheritedData.m_breakBefore);
  }
  void setBreakBefore(EBreak b) {
    DCHECK_LE(b, BreakValueLastAllowedForBreakAfterAndBefore);
    m_nonInheritedData.m_breakBefore = b;
  }

  // break-inside (shorthand for page-break-inside and -webkit-column-break-inside)
  static EBreak initialBreakInside() { return BreakAuto; }
  EBreak breakInside() const {
    return static_cast<EBreak>(m_nonInheritedData.m_breakInside);
  }
  void setBreakInside(EBreak b) {
    DCHECK_LE(b, BreakValueLastAllowedForBreakInside);
    m_nonInheritedData.m_breakInside = b;
  }

  // clip
  static LengthBox initialClip() { return LengthBox(); }
  const LengthBox& clip() const { return m_visual->clip; }
  void setClip(const LengthBox& box) {
    SET_VAR(m_visual, hasAutoClip, false);
    SET_VAR(m_visual, clip, box);
  }
  bool hasAutoClip() const { return m_visual->hasAutoClip; }
  void setHasAutoClip() {
    SET_VAR(m_visual, hasAutoClip, true);
    SET_VAR(m_visual, clip, ComputedStyle::initialClip());
  }

  // Column properties.
  // column-count (aka -webkit-column-count)
  static unsigned short initialColumnCount() { return 1; }
  unsigned short columnCount() const {
    return m_rareNonInheritedData->m_multiCol->m_count;
  }
  void setColumnCount(unsigned short c) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_autoCount, false);
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_count, c);
  }
  bool hasAutoColumnCount() const {
    return m_rareNonInheritedData->m_multiCol->m_autoCount;
  }
  void setHasAutoColumnCount() {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_autoCount, true);
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_count,
                   initialColumnCount());
  }

  // column-fill
  static ColumnFill initialColumnFill() { return ColumnFillBalance; }
  ColumnFill getColumnFill() const {
    return static_cast<ColumnFill>(m_rareNonInheritedData->m_multiCol->m_fill);
  }
  void setColumnFill(ColumnFill columnFill) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_fill, columnFill);
  }

  // column-gap (aka -webkit-column-gap)
  float columnGap() const { return m_rareNonInheritedData->m_multiCol->m_gap; }
  void setColumnGap(float f) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_normalGap, false);
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_gap, f);
  }
  bool hasNormalColumnGap() const {
    return m_rareNonInheritedData->m_multiCol->m_normalGap;
  }
  void setHasNormalColumnGap() {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_normalGap, true);
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_gap, 0);
  }

  // column-rule-color (aka -webkit-column-rule-color)
  void setColumnRuleColor(const StyleColor& c) {
    SET_BORDERVALUE_COLOR(m_rareNonInheritedData.access()->m_multiCol, m_rule,
                          c);
  }

  // column-rule-style (aka -webkit-column-rule-style)
  EBorderStyle columnRuleStyle() const {
    return m_rareNonInheritedData->m_multiCol->m_rule.style();
  }
  void setColumnRuleStyle(EBorderStyle b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_rule.m_style, b);
  }

  // column-rule-width (aka -webkit-column-rule-width)
  static unsigned short initialColumnRuleWidth() { return 3; }
  unsigned short columnRuleWidth() const {
    return m_rareNonInheritedData->m_multiCol->ruleWidth();
  }
  void setColumnRuleWidth(unsigned short w) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_rule.m_width, w);
  }

  // column-span (aka -webkit-column-span)
  static ColumnSpan initialColumnSpan() { return ColumnSpanNone; }
  ColumnSpan getColumnSpan() const {
    return static_cast<ColumnSpan>(
        m_rareNonInheritedData->m_multiCol->m_columnSpan);
  }
  void setColumnSpan(ColumnSpan columnSpan) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_columnSpan,
                   columnSpan);
  }

  // column-width (aka -webkit-column-width)
  float columnWidth() const {
    return m_rareNonInheritedData->m_multiCol->m_width;
  }
  void setColumnWidth(float f) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_autoWidth, false);
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_width, f);
  }
  bool hasAutoColumnWidth() const {
    return m_rareNonInheritedData->m_multiCol->m_autoWidth;
  }
  void setHasAutoColumnWidth() {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_autoWidth, true);
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol, m_width, 0);
  }

  // contain
  static Containment initialContain() { return ContainsNone; }
  Containment contain() const {
    return static_cast<Containment>(m_rareNonInheritedData->m_contain);
  }
  void setContain(Containment contain) {
    SET_VAR(m_rareNonInheritedData, m_contain, contain);
  }

  // content
  ContentData* contentData() const {
    return m_rareNonInheritedData->m_content.get();
  }
  void setContent(ContentData*);

  // display
  static EDisplay initialDisplay() { return EDisplay::Inline; }
  EDisplay display() const {
    return static_cast<EDisplay>(m_nonInheritedData.m_effectiveDisplay);
  }
  EDisplay originalDisplay() const {
    return static_cast<EDisplay>(m_nonInheritedData.m_originalDisplay);
  }
  void setDisplay(EDisplay v) {
    m_nonInheritedData.m_effectiveDisplay = static_cast<unsigned>(v);
  }
  void setOriginalDisplay(EDisplay v) {
    m_nonInheritedData.m_originalDisplay = static_cast<unsigned>(v);
  }

  // Flex properties.
  // flex-basis (aka -webkit-flex-basis)
  static Length initialFlexBasis() { return Length(Auto); }
  const Length& flexBasis() const {
    return m_rareNonInheritedData->m_flexibleBox->m_flexBasis;
  }
  void setFlexBasis(const Length& length) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_flexibleBox, m_flexBasis, length);
  }

  // flex-direction (aka -webkit-flex-direction)
  static EFlexDirection initialFlexDirection() { return FlowRow; }
  EFlexDirection flexDirection() const {
    return static_cast<EFlexDirection>(
        m_rareNonInheritedData->m_flexibleBox->m_flexDirection);
  }
  void setFlexDirection(EFlexDirection direction) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_flexibleBox, m_flexDirection,
                   direction);
  }

  // flex-grow (aka -webkit-flex-grow)
  static float initialFlexGrow() { return 0; }
  float flexGrow() const {
    return m_rareNonInheritedData->m_flexibleBox->m_flexGrow;
  }
  void setFlexGrow(float f) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_flexibleBox, m_flexGrow, f);
  }

  // flex-shrink (aka -webkit-flex-shrink)
  static float initialFlexShrink() { return 1; }
  float flexShrink() const {
    return m_rareNonInheritedData->m_flexibleBox->m_flexShrink;
  }
  void setFlexShrink(float f) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_flexibleBox, m_flexShrink, f);
  }

  // flex-wrap (aka -webkit-flex-wrap)
  static EFlexWrap initialFlexWrap() { return FlexNoWrap; }
  EFlexWrap flexWrap() const {
    return static_cast<EFlexWrap>(
        m_rareNonInheritedData->m_flexibleBox->m_flexWrap);
  }
  void setFlexWrap(EFlexWrap w) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_flexibleBox, m_flexWrap, w);
  }

  // -webkit-box-flex
  static float initialBoxFlex() { return 0.0f; }
  float boxFlex() const {
    return m_rareNonInheritedData->m_deprecatedFlexibleBox->flex;
  }
  void setBoxFlex(float f) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox, flex, f);
  }

  // -webkit-box-flex-group
  static unsigned initialBoxFlexGroup() { return 1; }
  unsigned boxFlexGroup() const {
    return m_rareNonInheritedData->m_deprecatedFlexibleBox->flexGroup;
  }
  void setBoxFlexGroup(unsigned fg) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox, flexGroup,
                   fg);
  }

  // -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>(
        m_rareNonInheritedData->m_deprecatedFlexibleBox->align);
  }
  void setBoxAlign(EBoxAlignment a) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox, align, a);
  }

  // -webkit-box-decoration-break
  static EBoxDecorationBreak initialBoxDecorationBreak() {
    return BoxDecorationBreakSlice;
  }
  EBoxDecorationBreak boxDecorationBreak() const {
    return m_box->boxDecorationBreak();
  }
  void setBoxDecorationBreak(EBoxDecorationBreak b) {
    SET_VAR(m_box, m_boxDecorationBreak, b);
  }

  // -webkit-box-lines
  static EBoxLines initialBoxLines() { return SINGLE; }
  EBoxLines boxLines() const {
    return static_cast<EBoxLines>(
        m_rareNonInheritedData->m_deprecatedFlexibleBox->lines);
  }
  void setBoxLines(EBoxLines lines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox, lines,
                   lines);
  }

  // -webkit-box-ordinal-group
  static unsigned initialBoxOrdinalGroup() { return 1; }
  unsigned boxOrdinalGroup() const {
    return m_rareNonInheritedData->m_deprecatedFlexibleBox->ordinalGroup;
  }
  void setBoxOrdinalGroup(unsigned og) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox,
                   ordinalGroup, og);
  }

  // -webkit-box-orient
  static EBoxOrient initialBoxOrient() { return HORIZONTAL; }
  EBoxOrient boxOrient() const {
    return static_cast<EBoxOrient>(
        m_rareNonInheritedData->m_deprecatedFlexibleBox->orient);
  }
  void setBoxOrient(EBoxOrient o) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox, orient, o);
  }

  // -webkit-box-pack
  static EBoxPack initialBoxPack() { return BoxPackStart; }
  EBoxPack boxPack() const {
    return static_cast<EBoxPack>(
        m_rareNonInheritedData->m_deprecatedFlexibleBox->pack);
  }
  void setBoxPack(EBoxPack p) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_deprecatedFlexibleBox, pack, p);
  }

  // -webkit-box-reflect
  static StyleReflection* initialBoxReflect() { return 0; }
  StyleReflection* boxReflect() const {
    return m_rareNonInheritedData->m_boxReflect.get();
  }
  void setBoxReflect(PassRefPtr<StyleReflection> reflect) {
    if (m_rareNonInheritedData->m_boxReflect != reflect)
      m_rareNonInheritedData.access()->m_boxReflect = reflect;
  }

  // Grid properties.
  static Vector<GridTrackSize> initialGridAutoRepeatTracks() {
    return Vector<GridTrackSize>(); /* none */
  }
  static size_t initialGridAutoRepeatInsertionPoint() { return 0; }
  static AutoRepeatType initialGridAutoRepeatType() { return NoAutoRepeat; }
  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 m_rareNonInheritedData->m_grid->m_gridAutoColumns;
  }
  void setGridAutoColumns(const Vector<GridTrackSize>& trackSizeList) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoColumns,
                   trackSizeList);
  }

  // grid-auto-flow
  static GridAutoFlow initialGridAutoFlow() { return AutoFlowRow; }
  void setGridAutoFlow(GridAutoFlow flow) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoFlow, flow);
  }

  // grid-auto-rows
  static Vector<GridTrackSize> initialGridAutoRows();
  const Vector<GridTrackSize>& gridAutoRows() const {
    return m_rareNonInheritedData->m_grid->m_gridAutoRows;
  }
  void setGridAutoRows(const Vector<GridTrackSize>& trackSizeList) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoRows,
                   trackSizeList);
  }

  // grid-column-gap
  static Length initialGridColumnGap() { return Length(Fixed); }
  const Length& gridColumnGap() const {
    return m_rareNonInheritedData->m_grid->m_gridColumnGap;
  }
  void setGridColumnGap(const Length& v) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridColumnGap, v);
  }

  // grid-column-start
  static GridPosition initialGridColumnStart() {
    return GridPosition(); /* auto */
  }
  const GridPosition& gridColumnStart() const {
    return m_rareNonInheritedData->m_gridItem->m_gridColumnStart;
  }
  void setGridColumnStart(const GridPosition& columnStartPosition) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_gridItem, m_gridColumnStart,
                   columnStartPosition);
  }

  // grid-column-end
  static GridPosition initialGridColumnEnd() {
    return GridPosition(); /* auto */
  }
  const GridPosition& gridColumnEnd() const {
    return m_rareNonInheritedData->m_gridItem->m_gridColumnEnd;
  }
  void setGridColumnEnd(const GridPosition& columnEndPosition) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_gridItem, m_gridColumnEnd,
                   columnEndPosition);
  }

  // grid-row-gap
  static Length initialGridRowGap() { return Length(Fixed); }
  const Length& gridRowGap() const {
    return m_rareNonInheritedData->m_grid->m_gridRowGap;
  }
  void setGridRowGap(const Length& v) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridRowGap, v);
  }

  // grid-row-start
  static GridPosition initialGridRowStart() {
    return GridPosition(); /* auto */
  }
  const GridPosition& gridRowStart() const {
    return m_rareNonInheritedData->m_gridItem->m_gridRowStart;
  }
  void setGridRowStart(const GridPosition& rowStartPosition) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_gridItem, m_gridRowStart,
                   rowStartPosition);
  }

  // grid-row-end
  static GridPosition initialGridRowEnd() { return GridPosition(); /* auto */ }
  const GridPosition& gridRowEnd() const {
    return m_rareNonInheritedData->m_gridItem->m_gridRowEnd;
  }
  void setGridRowEnd(const GridPosition& rowEndPosition) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_gridItem, m_gridRowEnd,
                   rowEndPosition);
  }

  // grid-template-columns
  static Vector<GridTrackSize> initialGridTemplateColumns() {
    return Vector<GridTrackSize>(); /* none */
  }
  const Vector<GridTrackSize>& gridTemplateColumns() const {
    return m_rareNonInheritedData->m_grid->m_gridTemplateColumns;
  }
  void setGridTemplateColumns(const Vector<GridTrackSize>& lengths) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridTemplateColumns,
                   lengths);
  }

  // grid-template-rows
  static Vector<GridTrackSize> initialGridTemplateRows() {
    return Vector<GridTrackSize>(); /* none */
  }
  const Vector<GridTrackSize>& gridTemplateRows() const {
    return m_rareNonInheritedData->m_grid->m_gridTemplateRows;
  }
  void setGridTemplateRows(const Vector<GridTrackSize>& lengths) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridTemplateRows, lengths);
  }

  // Width/height properties.
  static Length initialSize() { return Length(); }
  static Length initialMaxSize() { return Length(MaxSizeNone); }
  static Length initialMinSize() { return Length(); }

  // width
  const Length& width() const { return m_box->width(); }
  void setWidth(const Length& v) { SET_VAR(m_box, m_width, v); }

  // height
  const Length& height() const { return m_box->height(); }
  void setHeight(const Length& v) { SET_VAR(m_box, m_height, v); }

  // max-width
  const Length& maxWidth() const { return m_box->maxWidth(); }
  void setMaxWidth(const Length& v) { SET_VAR(m_box, m_maxWidth, v); }

  // max-height
  const Length& maxHeight() const { return m_box->maxHeight(); }
  void setMaxHeight(const Length& v) { SET_VAR(m_box, m_maxHeight, v); }

  // min-width
  const Length& minWidth() const { return m_box->minWidth(); }
  void setMinWidth(const Length& v) { SET_VAR(m_box, m_minWidth, v); }

  // min-height
  const Length& minHeight() const { return m_box->minHeight(); }
  void setMinHeight(const Length& v) { SET_VAR(m_box, m_minHeight, v); }

  // image-orientation
  static RespectImageOrientationEnum initialRespectImageOrientation() {
    return DoNotRespectImageOrientation;
  }
  RespectImageOrientationEnum respectImageOrientation() const {
    return static_cast<RespectImageOrientationEnum>(
        m_rareInheritedData->m_respectImageOrientation);
  }
  void setRespectImageOrientation(RespectImageOrientationEnum v) {
    SET_VAR(m_rareInheritedData, m_respectImageOrientation, v);
  }

  // image-rendering
  static EImageRendering initialImageRendering() { return ImageRenderingAuto; }
  EImageRendering imageRendering() const {
    return static_cast<EImageRendering>(m_rareInheritedData->m_imageRendering);
  }
  void setImageRendering(EImageRendering v) {
    SET_VAR(m_rareInheritedData, m_imageRendering, v);
  }

  // isolation
  static EIsolation initialIsolation() { return IsolationAuto; }
  EIsolation isolation() const {
    return static_cast<EIsolation>(m_rareNonInheritedData->m_isolation);
  }
  void setIsolation(EIsolation v) {
    m_rareNonInheritedData.access()->m_isolation = v;
  }

  // Margin properties.
  static Length initialMargin() { return Length(Fixed); }

  // margin-top
  const Length& marginTop() const { return m_surround->margin.top(); }
  void setMarginTop(const Length& v) { SET_VAR(m_surround, margin.m_top, v); }

  // margin-bottom
  const Length& marginBottom() const { return m_surround->margin.bottom(); }
  void setMarginBottom(const Length& v) {
    SET_VAR(m_surround, margin.m_bottom, v);
  }

  // margin-left
  const Length& marginLeft() const { return m_surround->margin.left(); }
  void setMarginLeft(const Length& v) { SET_VAR(m_surround, margin.m_left, v); }

  // margin-right
  const Length& marginRight() const { return m_surround->margin.right(); }
  void setMarginRight(const Length& v) {
    SET_VAR(m_surround, margin.m_right, v);
  }

  // -webkit-margin-before-collapse (aka -webkit-margin-top-collapse)
  static EMarginCollapse initialMarginBeforeCollapse() {
    return MarginCollapseCollapse;
  }
  EMarginCollapse marginAfterCollapse() const {
    return static_cast<EMarginCollapse>(
        m_rareNonInheritedData->marginAfterCollapse);
  }
  void setMarginBeforeCollapse(EMarginCollapse c) {
    SET_VAR(m_rareNonInheritedData, marginBeforeCollapse, c);
  }

  // -webkit-margin-after-collapse (aka -webkit-margin-bottom-collapse)
  static EMarginCollapse initialMarginAfterCollapse() {
    return MarginCollapseCollapse;
  }
  EMarginCollapse marginBeforeCollapse() const {
    return static_cast<EMarginCollapse>(
        m_rareNonInheritedData->marginBeforeCollapse);
  }
  void setMarginAfterCollapse(EMarginCollapse c) {
    SET_VAR(m_rareNonInheritedData, marginAfterCollapse, c);
  }

  // mix-blend-mode
  static WebBlendMode initialBlendMode() { return WebBlendModeNormal; }
  WebBlendMode blendMode() const {
    return static_cast<WebBlendMode>(
        m_rareNonInheritedData->m_effectiveBlendMode);
  }
  void setBlendMode(WebBlendMode v) {
    m_rareNonInheritedData.access()->m_effectiveBlendMode = v;
  }

  // object-fit
  static ObjectFit initialObjectFit() { return ObjectFitFill; }
  ObjectFit getObjectFit() const {
    return static_cast<ObjectFit>(m_rareNonInheritedData->m_objectFit);
  }
  void setObjectFit(ObjectFit f) {
    SET_VAR(m_rareNonInheritedData, m_objectFit, f);
  }

  // object-position
  static LengthPoint initialObjectPosition() {
    return LengthPoint(Length(50.0, Percent), Length(50.0, Percent));
  }
  LengthPoint objectPosition() const {
    return m_rareNonInheritedData->m_objectPosition;
  }
  void setObjectPosition(LengthPoint position) {
    SET_VAR(m_rareNonInheritedData, m_objectPosition, position);
  }

  // offset-anchor
  static LengthPoint initialOffsetAnchor() {
    return LengthPoint(Length(50.0, Percent), Length(50.0, Percent));
  }
  const LengthPoint& offsetAnchor() const {
    return m_rareNonInheritedData->m_transform->m_motion.m_anchor;
  }
  void setOffsetAnchor(const LengthPoint& offsetAnchor) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_motion.m_anchor,
                   offsetAnchor);
  }

  // offset-distance
  static Length initialOffsetDistance() { return Length(0, Fixed); }
  const Length& offsetDistance() const {
    return m_rareNonInheritedData->m_transform->m_motion.m_distance;
  }
  void setOffsetDistance(const Length& offsetDistance) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_motion.m_distance,
                   offsetDistance);
  }

  // offset-path
  static StylePath* initialOffsetPath() { return nullptr; }
  StylePath* offsetPath() const {
    return m_rareNonInheritedData->m_transform->m_motion.m_path.get();
  }
  void setOffsetPath(PassRefPtr<StylePath>);

  // offset-position
  static LengthPoint initialOffsetPosition() {
    return LengthPoint(Length(Auto), Length(Auto));
  }
  const LengthPoint& offsetPosition() const {
    return m_rareNonInheritedData->m_transform->m_motion.m_position;
  }
  void setOffsetPosition(const LengthPoint& offsetPosition) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_motion.m_position,
                   offsetPosition);
  }

  // offset-rotation
  static StyleOffsetRotation initialOffsetRotation() {
    return StyleOffsetRotation(0, OffsetRotationAuto);
  }
  const StyleOffsetRotation& offsetRotation() const {
    return m_rareNonInheritedData->m_transform->m_motion.m_rotation;
  }
  void setOffsetRotation(const StyleOffsetRotation& offsetRotation) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_motion.m_rotation,
                   offsetRotation);
  }

  // opacity (aka -webkit-opacity)
  static float initialOpacity() { return 1.0f; }
  float opacity() const { return m_rareNonInheritedData->opacity; }
  void setOpacity(float f) {
    float v = clampTo<float>(f, 0, 1);
    SET_VAR(m_rareNonInheritedData, opacity, v);
  }

  // order (aka -webkit-order)
  static int initialOrder() { return 0; }
  int order() const { return m_rareNonInheritedData->m_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(m_rareNonInheritedData, m_order,
            max(std::numeric_limits<int>::min() + 2, o));
  }

  // Outline properties.
  // outline-color
  void setOutlineColor(const StyleColor& v) {
    SET_BORDERVALUE_COLOR(m_background, m_outline, v);
  }

  // outline-style
  EBorderStyle outlineStyle() const { return m_background->outline().style(); }
  void setOutlineStyle(EBorderStyle v) {
    SET_VAR(m_background, m_outline.m_style, v);
  }
  static OutlineIsAuto initialOutlineStyleIsAuto() { return OutlineIsAutoOff; }
  OutlineIsAuto outlineStyleIsAuto() const {
    return static_cast<OutlineIsAuto>(m_background->outline().isAuto());
  }
  void setOutlineStyleIsAuto(OutlineIsAuto isAuto) {
    SET_VAR(m_background, m_outline.m_isAuto, isAuto);
  }

  // outline-width
  static unsigned short initialOutlineWidth() { return 3; }
  int outlineWidth() const {
    if (m_background->outline().style() == BorderStyleNone)
      return 0;
    return m_background->outline().width();
  }
  void setOutlineWidth(unsigned short v) {
    SET_VAR(m_background, m_outline.m_width, v);
  }

  // outline-offset
  static int initialOutlineOffset() { return 0; }
  int outlineOffset() const {
    if (m_background->outline().style() == BorderStyleNone)
      return 0;
    return m_background->outline().offset();
  }
  void setOutlineOffset(int v) { SET_VAR(m_background, m_outline.m_offset, v); }

  // Overflow properties.
  // overflow-anchor
  static EOverflowAnchor initialOverflowAnchor() { return AnchorAuto; }
  EOverflowAnchor overflowAnchor() const {
    return static_cast<EOverflowAnchor>(m_nonInheritedData.m_overflowAnchor);
  }
  void setOverflowAnchor(EOverflowAnchor v) {
    m_nonInheritedData.m_overflowAnchor = v;
  }

  // overflow-x
  static EOverflow initialOverflowX() { return OverflowVisible; }
  EOverflow overflowX() const {
    return static_cast<EOverflow>(m_nonInheritedData.m_overflowX);
  }
  void setOverflowX(EOverflow v) { m_nonInheritedData.m_overflowX = v; }

  // overflow-y
  static EOverflow initialOverflowY() { return OverflowVisible; }
  EOverflow overflowY() const {
    return static_cast<EOverflow>(m_nonInheritedData.m_overflowY);
  }
  void setOverflowY(EOverflow v) { m_nonInheritedData.m_overflowY = v; }

  // Padding properties.
  static Length initialPadding() { return Length(Fixed); }

  // padding-bottom
  const Length& paddingBottom() const { return m_surround->padding.bottom(); }
  void setPaddingBottom(const Length& v) {
    SET_VAR(m_surround, padding.m_bottom, v);
  }

  // padding-left
  const Length& paddingLeft() const { return m_surround->padding.left(); }
  void setPaddingLeft(const Length& v) {
    SET_VAR(m_surround, padding.m_left, v);
  }

  // padding-right
  const Length& paddingRight() const { return m_surround->padding.right(); }
  void setPaddingRight(const Length& v) {
    SET_VAR(m_surround, padding.m_right, v);
  }

  // padding-top
  const Length& paddingTop() const { return m_surround->padding.top(); }
  void setPaddingTop(const Length& v) { SET_VAR(m_surround, padding.m_top, v); }

  // perspective (aka -webkit-perspective)
  static float initialPerspective() { return 0; }
  float perspective() const { return m_rareNonInheritedData->m_perspective; }
  void setPerspective(float p) {
    SET_VAR(m_rareNonInheritedData, m_perspective, p);
  }

  // perspective-origin (aka -webkit-perspective-origin)
  static LengthPoint initialPerspectiveOrigin() {
    return LengthPoint(Length(50.0, Percent), Length(50.0, Percent));
  }
  const LengthPoint& perspectiveOrigin() const {
    return m_rareNonInheritedData->m_perspectiveOrigin;
  }
  void setPerspectiveOrigin(const LengthPoint& p) {
    SET_VAR(m_rareNonInheritedData, m_perspectiveOrigin, p);
  }

  // -webkit-perspective-origin-x
  static Length initialPerspectiveOriginX() { return Length(50.0, Percent); }
  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, Percent); }
  const Length& perspectiveOriginY() const { return perspectiveOrigin().y(); }
  void setPerspectiveOriginY(const Length& v) {
    setPerspectiveOrigin(LengthPoint(perspectiveOriginX(), v));
  }

  // position
  static EPosition initialPosition() { return StaticPosition; }
  EPosition position() const {
    return static_cast<EPosition>(m_nonInheritedData.m_position);
  }
  void setPosition(EPosition v) { m_nonInheritedData.m_position = v; }

  // resize
  static EResize initialResize() { return RESIZE_NONE; }
  EResize resize() const {
    return static_cast<EResize>(m_rareNonInheritedData->m_resize);
  }
  void setResize(EResize r) { SET_VAR(m_rareNonInheritedData, m_resize, r); }

  // Transform properties.
  // transform (aka -webkit-transform)
  static EmptyTransformOperations initialTransform() {
    return EmptyTransformOperations();
  }
  const TransformOperations& transform() const {
    return m_rareNonInheritedData->m_transform->m_operations;
  }
  void setTransform(const TransformOperations& ops) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_operations, ops);
  }

  // transform-origin (aka -webkit-transform-origin)
  static TransformOrigin initialTransformOrigin() {
    return TransformOrigin(Length(50.0, Percent), Length(50.0, Percent), 0);
  }
  const TransformOrigin& transformOrigin() const {
    return m_rareNonInheritedData->m_transform->m_origin;
  }
  void setTransformOrigin(const TransformOrigin& o) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_origin, o);
  }

  // transform-style (aka -webkit-transform-style)
  static ETransformStyle3D initialTransformStyle3D() {
    return TransformStyle3DFlat;
  }
  ETransformStyle3D transformStyle3D() const {
    return static_cast<ETransformStyle3D>(
        m_rareNonInheritedData->m_transformStyle3D);
  }
  void setTransformStyle3D(ETransformStyle3D b) {
    SET_VAR(m_rareNonInheritedData, m_transformStyle3D, b);
  }

  // -webkit-transform-origin-x
  static Length initialTransformOriginX() { return Length(50.0, Percent); }
  const Length& transformOriginX() const { return transformOrigin().x(); }
  void setTransformOriginX(const Length& v) {
    setTransformOrigin(
        TransformOrigin(v, transformOriginY(), transformOriginZ()));
  }

  // -webkit-transform-origin-y
  static Length initialTransformOriginY() { return Length(50.0, Percent); }
  const Length& transformOriginY() const { return transformOrigin().y(); }
  void setTransformOriginY(const Length& v) {
    setTransformOrigin(
        TransformOrigin(transformOriginX(), v, transformOriginZ()));
  }

  // -webkit-transform-origin-z
  static float initialTransformOriginZ() { return 0; }
  float transformOriginZ() const { return transformOrigin().z(); }
  void setTransformOriginZ(float f) {
    setTransformOrigin(
        TransformOrigin(transformOriginX(), transformOriginY(), f));
  }

  // Independent transform properties.
  // translate
  static PassRefPtr<TranslateTransformOperation> initialTranslate() {
    return TranslateTransformOperation::create(
        Length(0, Fixed), Length(0, Fixed), 0, TransformOperation::Translate3D);
  }
  TranslateTransformOperation* translate() const {
    return m_rareNonInheritedData->m_transform->m_translate.get();
  }
  void setTranslate(PassRefPtr<TranslateTransformOperation> v) {
    m_rareNonInheritedData.access()->m_transform.access()->m_translate = v;
  }

  // rotate
  static PassRefPtr<RotateTransformOperation> initialRotate() {
    return RotateTransformOperation::create(0, 0, 1, 0,
                                            TransformOperation::Rotate3D);
  }
  RotateTransformOperation* rotate() const {
    return m_rareNonInheritedData->m_transform->m_rotate.get();
  }
  void setRotate(PassRefPtr<RotateTransformOperation> v) {
    m_rareNonInheritedData.access()->m_transform.access()->m_rotate = v;
  }

  // scale
  static PassRefPtr<ScaleTransformOperation> initialScale() {
    return ScaleTransformOperation::create(1, 1, 1,
                                           TransformOperation::Scale3D);
  }
  ScaleTransformOperation* scale() const {
    return m_rareNonInheritedData->m_transform->m_scale.get();
  }
  void setScale(PassRefPtr<ScaleTransformOperation> v) {
    m_rareNonInheritedData.access()->m_transform.access()->m_scale = v;
  }

  // Scroll properties.
  // scroll-behavior
  static ScrollBehavior initialScrollBehavior() { return ScrollBehaviorAuto; }
  ScrollBehavior getScrollBehavior() const {
    return static_cast<ScrollBehavior>(
        m_rareNonInheritedData->m_scrollBehavior);
  }
  void setScrollBehavior(ScrollBehavior b) {
    SET_VAR(m_rareNonInheritedData, m_scrollBehavior, b);
  }

  // scroll-snap-coordinate
  static Vector<LengthPoint> initialScrollSnapCoordinate() {
    return Vector<LengthPoint>();
  }
  const Vector<LengthPoint>& scrollSnapCoordinate() const {
    return m_rareNonInheritedData->m_scrollSnap->m_coordinates;
  }
  void setScrollSnapCoordinate(const Vector<LengthPoint>& b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_scrollSnap, m_coordinates, b);
  }

  // scroll-snap-destination
  static LengthPoint initialScrollSnapDestination() {
    return LengthPoint(Length(0, Fixed), Length(0, Fixed));
  }
  const LengthPoint& scrollSnapDestination() const {
    return m_rareNonInheritedData->m_scrollSnap->m_destination;
  }
  void setScrollSnapDestination(const LengthPoint& b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_scrollSnap, m_destination, b);
  }

  // scroll-snap-points-x
  static ScrollSnapPoints initialScrollSnapPointsX() {
    return ScrollSnapPoints();
  }
  const ScrollSnapPoints& scrollSnapPointsX() const {
    return m_rareNonInheritedData->m_scrollSnap->m_xPoints;
  }
  void setScrollSnapPointsX(const ScrollSnapPoints& b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_scrollSnap, m_xPoints, b);
  }

  // scroll-snap-points-y
  static ScrollSnapPoints initialScrollSnapPointsY() {
    return ScrollSnapPoints();
  }
  const ScrollSnapPoints& scrollSnapPointsY() const {
    return m_rareNonInheritedData->m_scrollSnap->m_yPoints;
  }
  void setScrollSnapPointsY(const ScrollSnapPoints& b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_scrollSnap, m_yPoints, b);
  }

  // scroll-snap-type
  static ScrollSnapType initialScrollSnapType() { return ScrollSnapTypeNone; }
  ScrollSnapType getScrollSnapType() const {
    return static_cast<ScrollSnapType>(
        m_rareNonInheritedData->m_scrollSnapType);
  }
  void setScrollSnapType(ScrollSnapType b) {
    SET_VAR(m_rareNonInheritedData, m_scrollSnapType, b);
  }

  // shape-image-threshold (aka -webkit-shape-image-threshold)
  static float initialShapeImageThreshold() { return 0; }
  float shapeImageThreshold() const {
    return m_rareNonInheritedData->m_shapeImageThreshold;
  }
  void setShapeImageThreshold(float shapeImageThreshold) {
    float clampedShapeImageThreshold =
        clampTo<float>(shapeImageThreshold, 0, 1);
    SET_VAR(m_rareNonInheritedData, m_shapeImageThreshold,
            clampedShapeImageThreshold);
  }

  // shape-margin (aka -webkit-shape-margin)
  static Length initialShapeMargin() { return Length(0, Fixed); }
  const Length& shapeMargin() const {
    return m_rareNonInheritedData->m_shapeMargin;
  }
  void setShapeMargin(const Length& shapeMargin) {
    SET_VAR(m_rareNonInheritedData, m_shapeMargin, shapeMargin);
  }

  // shape-outside (aka -webkit-shape-outside)
  static ShapeValue* initialShapeOutside() { return 0; }
  ShapeValue* shapeOutside() const {
    return m_rareNonInheritedData->m_shapeOutside.get();
  }
  void setShapeOutside(ShapeValue* value) {
    if (m_rareNonInheritedData->m_shapeOutside == value)
      return;
    m_rareNonInheritedData.access()->m_shapeOutside = value;
  }

  // size
  const FloatSize& pageSize() const {
    return m_rareNonInheritedData->m_pageSize;
  }
  PageSizeType getPageSizeType() const {
    return static_cast<PageSizeType>(m_rareNonInheritedData->m_pageSizeType);
  }
  void setPageSize(const FloatSize& s) {
    SET_VAR(m_rareNonInheritedData, m_pageSize, s);
  }
  void setPageSizeType(PageSizeType t) {
    SET_VAR(m_rareNonInheritedData, m_pageSizeType, t);
  }
  // table-layout
  static ETableLayout initialTableLayout() { return TableLayoutAuto; }
  ETableLayout tableLayout() const {
    return static_cast<ETableLayout>(m_nonInheritedData.m_tableLayout);
  }
  void setTableLayout(ETableLayout v) { m_nonInheritedData.m_tableLayout = v; }

  // Text decoration properties.
  // text-decoration-line
  static TextDecoration initialTextDecoration() { return TextDecorationNone; }
  TextDecoration getTextDecoration() const {
    return static_cast<TextDecoration>(m_visual->textDecoration);
  }
  void setTextDecoration(TextDecoration v) {
    SET_VAR(m_visual, textDecoration, v);
  }

  // text-decoration-color
  void setTextDecorationColor(const StyleColor& c) {
    SET_VAR(m_rareNonInheritedData, m_textDecorationColor, c);
  }

  // text-decoration-style
  static TextDecorationStyle initialTextDecorationStyle() {
    return TextDecorationStyleSolid;
  }
  TextDecorationStyle getTextDecorationStyle() const {
    return static_cast<TextDecorationStyle>(
        m_rareNonInheritedData->m_textDecorationStyle);
  }
  void setTextDecorationStyle(TextDecorationStyle v) {
    SET_VAR(m_rareNonInheritedData, m_textDecorationStyle, v);
  }

  // text-underline-position
  static TextUnderlinePosition initialTextUnderlinePosition() {
    return TextUnderlinePositionAuto;
  }
  TextUnderlinePosition getTextUnderlinePosition() const {
    return static_cast<TextUnderlinePosition>(
        m_rareInheritedData->m_textUnderlinePosition);
  }
  void setTextUnderlinePosition(TextUnderlinePosition v) {
    SET_VAR(m_rareInheritedData, m_textUnderlinePosition, v);
  }

  // text-overflow
  static TextOverflow initialTextOverflow() { return TextOverflowClip; }
  TextOverflow getTextOverflow() const {
    return static_cast<TextOverflow>(m_rareNonInheritedData->textOverflow);
  }
  void setTextOverflow(TextOverflow overflow) {
    SET_VAR(m_rareNonInheritedData, textOverflow, overflow);
  }

  // touch-action
  static TouchAction initialTouchAction() { return TouchActionAuto; }
  TouchAction getTouchAction() const {
    return static_cast<TouchAction>(m_rareNonInheritedData->m_touchAction);
  }
  void setTouchAction(TouchAction t) {
    SET_VAR(m_rareNonInheritedData, m_touchAction, t);
  }

  // unicode-bidi
  static EUnicodeBidi initialUnicodeBidi() { return UBNormal; }
  EUnicodeBidi unicodeBidi() const {
    return static_cast<EUnicodeBidi>(m_nonInheritedData.m_unicodeBidi);
  }
  void setUnicodeBidi(EUnicodeBidi b) { m_nonInheritedData.m_unicodeBidi = b; }

  // vertical-align
  static EVerticalAlign initialVerticalAlign() { return VerticalAlignBaseline; }
  EVerticalAlign verticalAlign() const {
    return static_cast<EVerticalAlign>(m_nonInheritedData.m_verticalAlign);
  }
  const Length& getVerticalAlignLength() const {
    return m_box->verticalAlign();
  }
  void setVerticalAlign(EVerticalAlign v) {
    m_nonInheritedData.m_verticalAlign = v;
  }
  void setVerticalAlignLength(const Length& length) {
    setVerticalAlign(VerticalAlignLength);
    SET_VAR(m_box, m_verticalAlign, length);
  }

  // visibility
  // TODO(sashab): Move this to ComputedStyleBase.
  void setVisibilityIsInherited(bool isInherited) {
    m_nonInheritedData.m_isVisibilityInherited = isInherited;
  }

  // will-change
  const Vector<CSSPropertyID>& willChangeProperties() const {
    return m_rareNonInheritedData->m_willChange->m_properties;
  }
  bool willChangeContents() const {
    return m_rareNonInheritedData->m_willChange->m_contents;
  }
  bool willChangeScrollPosition() const {
    return m_rareNonInheritedData->m_willChange->m_scrollPosition;
  }
  bool subtreeWillChangeContents() const {
    return m_rareInheritedData->m_subtreeWillChangeContents;
  }
  void setWillChangeProperties(const Vector<CSSPropertyID>& properties) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_willChange, m_properties,
                   properties);
  }
  void setWillChangeContents(bool b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_willChange, m_contents, b);
  }
  void setWillChangeScrollPosition(bool b) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_willChange, m_scrollPosition, b);
  }
  void setSubtreeWillChangeContents(bool b) {
    SET_VAR(m_rareInheritedData, m_subtreeWillChangeContents, b);
  }

  // z-index
  int zIndex() const { return m_box->zIndex(); }
  bool hasAutoZIndex() const { return m_box->hasAutoZIndex(); }
  void setZIndex(int v) {
    SET_VAR(m_box, m_hasAutoZIndex, false);
    SET_VAR(m_box, m_zIndex, v);
  }
  void setHasAutoZIndex() {
    SET_VAR(m_box, m_hasAutoZIndex, true);
    SET_VAR(m_box, m_zIndex, 0);
  }

  // zoom
  static float initialZoom() { return 1.0f; }
  float zoom() const { return m_visual->m_zoom; }
  float effectiveZoom() const { return m_rareInheritedData->m_effectiveZoom; }
  bool setZoom(float);
  bool setEffectiveZoom(float);

  // -webkit-app-region
  DraggableRegionMode getDraggableRegionMode() const {
    return m_rareNonInheritedData->m_draggableRegionMode;
  }
  void setDraggableRegionMode(DraggableRegionMode v) {
    SET_VAR(m_rareNonInheritedData, m_draggableRegionMode, v);
  }

  // -webkit-appearance
  static ControlPart initialAppearance() { return NoControlPart; }
  ControlPart appearance() const {
    return static_cast<ControlPart>(m_rareNonInheritedData->m_appearance);
  }
  void setAppearance(ControlPart a) {
    SET_VAR(m_rareNonInheritedData, m_appearance, a);
  }

  // -webkit-clip-path
  static ClipPathOperation* initialClipPath() { return 0; }
  ClipPathOperation* clipPath() const {
    return m_rareNonInheritedData->m_clipPath.get();
  }
  void setClipPath(PassRefPtr<ClipPathOperation> operation) {
    if (m_rareNonInheritedData->m_clipPath != operation)
      m_rareNonInheritedData.access()->m_clipPath = operation;
  }

  // Mask properties.
  // -webkit-mask-box-image-outset
  const BorderImageLengthBox& maskBoxImageOutset() const {
    return m_rareNonInheritedData->m_maskBoxImage.outset();
  }
  void setMaskBoxImageOutset(const BorderImageLengthBox& outset) {
    m_rareNonInheritedData.access()->m_maskBoxImage.setOutset(outset);
  }

  // -webkit-mask-box-image-slice
  const LengthBox& maskBoxImageSlices() const {
    return m_rareNonInheritedData->m_maskBoxImage.imageSlices();
  }
  void setMaskBoxImageSlices(const LengthBox& slices) {
    m_rareNonInheritedData.access()->m_maskBoxImage.setImageSlices(slices);
  }

  // -webkit-mask-box-image-source
  static StyleImage* initialMaskBoxImageSource() { return 0; }
  StyleImage* maskBoxImageSource() const {
    return m_rareNonInheritedData->m_maskBoxImage.image();
  }
  void setMaskBoxImageSource(StyleImage* v) {
    m_rareNonInheritedData.access()->m_maskBoxImage.setImage(v);
  }

  // -webkit-mask-box-image-width
  const BorderImageLengthBox& maskBoxImageWidth() const {
    return m_rareNonInheritedData->m_maskBoxImage.borderSlices();
  }
  void setMaskBoxImageWidth(const BorderImageLengthBox& slices) {
    m_rareNonInheritedData.access()->m_maskBoxImage.setBorderSlices(slices);
  }

  // Inherited properties.

  // border-collapse
  static EBorderCollapse initialBorderCollapse() {
    return BorderCollapseSeparate;
  }
  EBorderCollapse borderCollapse() const {
    return static_cast<EBorderCollapse>(m_inheritedData.m_borderCollapse);
  }
  void setBorderCollapse(EBorderCollapse collapse) {
    m_inheritedData.m_borderCollapse = collapse;
  }

  // Border-spacing properties.
  // -webkit-border-horizontal-spacing
  static short initialHorizontalBorderSpacing() { return 0; }
  short horizontalBorderSpacing() const;
  void setHorizontalBorderSpacing(short);

  // -webkit-border-vertical-spacing
  static short initialVerticalBorderSpacing() { return 0; }
  short verticalBorderSpacing() const;
  void setVerticalBorderSpacing(short);

  // caption-side (aka -epub-caption-side)
  static ECaptionSide initialCaptionSide() { return ECaptionSide::Top; }
  ECaptionSide captionSide() const {
    return static_cast<ECaptionSide>(m_inheritedData.m_captionSide);
  }
  void setCaptionSide(ECaptionSide v) {
    m_inheritedData.m_captionSide = static_cast<unsigned>(v);
  }

  // cursor
  static ECursor initialCursor() { return CURSOR_AUTO; }
  ECursor cursor() const {
    return static_cast<ECursor>(m_inheritedData.m_cursorStyle);
  }
  void setCursor(ECursor c) { m_inheritedData.m_cursorStyle = c; }

  // direction
  static TextDirection initialDirection() { return LTR; }
  TextDirection direction() const {
    return static_cast<TextDirection>(m_inheritedData.m_direction);
  }
  void setDirection(TextDirection v) { m_inheritedData.m_direction = v; }

  // empty-cells
  static EEmptyCells initialEmptyCells() { return EEmptyCells::Show; }
  EEmptyCells emptyCells() const {
    return static_cast<EEmptyCells>(m_inheritedData.m_emptyCells);
  }
  void setEmptyCells(EEmptyCells v) {
    m_inheritedData.m_emptyCells = static_cast<unsigned>(v);
  }

  // color
  static Color initialColor() { return Color::black; }
  void setColor(const Color&);

  // hyphens
  static Hyphens initialHyphens() { return HyphensManual; }
  Hyphens getHyphens() const {
    return static_cast<Hyphens>(m_rareInheritedData->hyphens);
  }
  void setHyphens(Hyphens h) { SET_VAR(m_rareInheritedData, hyphens, h); }

  // -webkit-hyphenate-character
  static const AtomicString& initialHyphenationString() { return nullAtom; }
  const AtomicString& hyphenationString() const {
    return m_rareInheritedData->hyphenationString;
  }
  void setHyphenationString(const AtomicString& h) {
    SET_VAR(m_rareInheritedData, hyphenationString, h);
  }

  // line-height
  static Length initialLineHeight() { return Length(-100.0, Percent); }
  Length lineHeight() const;
  void setLineHeight(const Length& specifiedLineHeight);

  // List style properties.
  // list-style-type
  static EListStyleType initialListStyleType() { return Disc; }
  EListStyleType listStyleType() const {
    return static_cast<EListStyleType>(m_inheritedData.m_listStyleType);
  }
  void setListStyleType(EListStyleType v) {
    m_inheritedData.m_listStyleType = v;
  }

  // list-style-position
  static EListStylePosition initialListStylePosition() {
    return EListStylePosition::Outside;
  }
  EListStylePosition listStylePosition() const {
    return static_cast<EListStylePosition>(m_inheritedData.m_listStylePosition);
  }
  void setListStylePosition(EListStylePosition v) {
    m_inheritedData.m_listStylePosition = static_cast<unsigned>(v);
  }

  // list-style-image
  static StyleImage* initialListStyleImage() { return 0; }
  StyleImage* listStyleImage() const;
  void setListStyleImage(StyleImage*);

  // orphans
  static short initialOrphans() { return 2; }
  short orphans() const { return m_rareInheritedData->orphans; }
  void setOrphans(short o) { SET_VAR(m_rareInheritedData, orphans, o); }

  // widows
  static short initialWidows() { return 2; }
  short widows() const { return m_rareInheritedData->widows; }
  void setWidows(short w) { SET_VAR(m_rareInheritedData, widows, w); }

  // overflow-wrap (aka word-wrap)
  static EOverflowWrap initialOverflowWrap() { return NormalOverflowWrap; }
  EOverflowWrap overflowWrap() const {
    return static_cast<EOverflowWrap>(m_rareInheritedData->overflowWrap);
  }
  void setOverflowWrap(EOverflowWrap b) {
    SET_VAR(m_rareInheritedData, overflowWrap, b);
  }

  // pointer-events
  static EPointerEvents initialPointerEvents() { return PE_AUTO; }
  EPointerEvents pointerEvents() const {
    return static_cast<EPointerEvents>(m_inheritedData.m_pointerEvents);
  }
  void setPointerEvents(EPointerEvents p) {
    m_inheritedData.m_pointerEvents = p;
  }
  void setPointerEventsIsInherited(bool isInherited) {
    m_nonInheritedData.m_isPointerEventsInherited = isInherited;
  }

  // quotes
  static QuotesData* initialQuotes() { return 0; }
  QuotesData* quotes() const { return m_rareInheritedData->quotes.get(); }
  void setQuotes(PassRefPtr<QuotesData>);

  // snap-height
  uint8_t snapHeightPosition() const {
    return m_rareInheritedData->m_snapHeightPosition;
  }
  uint8_t snapHeightUnit() const {
    return m_rareInheritedData->m_snapHeightUnit;
  }
  void setSnapHeightPosition(uint8_t position) {
    SET_VAR(m_rareInheritedData, m_snapHeightPosition, position);
  }
  void setSnapHeightUnit(uint8_t unit) {
    SET_VAR(m_rareInheritedData, m_snapHeightUnit, unit);
  }

  // speak
  static ESpeak initialSpeak() { return SpeakNormal; }
  ESpeak speak() const {
    return static_cast<ESpeak>(m_rareInheritedData->speak);
  }
  void setSpeak(ESpeak s) { SET_VAR(m_rareInheritedData, speak, s); }

  // tab-size
  static TabSize initialTabSize() { return TabSize(8); }
  TabSize getTabSize() const { return m_rareInheritedData->m_tabSize; }
  void setTabSize(TabSize size) {
    SET_VAR(m_rareInheritedData, m_tabSize, size);
  }

  // text-align
  static ETextAlign initialTextAlign() { return TASTART; }
  ETextAlign textAlign() const {
    return static_cast<ETextAlign>(m_inheritedData.m_textAlign);
  }
  void setTextAlign(ETextAlign v) { m_inheritedData.m_textAlign = v; }

  // text-align-last
  static TextAlignLast initialTextAlignLast() { return TextAlignLastAuto; }
  TextAlignLast getTextAlignLast() const {
    return static_cast<TextAlignLast>(m_rareInheritedData->m_textAlignLast);
  }
  void setTextAlignLast(TextAlignLast v) {
    SET_VAR(m_rareInheritedData, m_textAlignLast, v);
  }

  // text-combine-upright (aka -webkit-text-combine, -epub-text-combine)
  static TextCombine initialTextCombine() { return TextCombineNone; }
  TextCombine getTextCombine() const {
    return static_cast<TextCombine>(m_rareInheritedData->m_textCombine);
  }
  void setTextCombine(TextCombine v) {
    SET_VAR(m_rareInheritedData, m_textCombine, v);
  }

  // text-indent
  static Length initialTextIndent() { return Length(Fixed); }
  static TextIndentLine initialTextIndentLine() { return TextIndentFirstLine; }
  static TextIndentType initialTextIndentType() { return TextIndentNormal; }
  const Length& textIndent() const { return m_rareInheritedData->indent; }
  TextIndentLine getTextIndentLine() const {
    return static_cast<TextIndentLine>(m_rareInheritedData->m_textIndentLine);
  }
  TextIndentType getTextIndentType() const {
    return static_cast<TextIndentType>(m_rareInheritedData->m_textIndentType);
  }
  void setTextIndent(const Length& v) {
    SET_VAR(m_rareInheritedData, indent, v);
  }
  void setTextIndentLine(TextIndentLine v) {
    SET_VAR(m_rareInheritedData, m_textIndentLine, v);
  }
  void setTextIndentType(TextIndentType v) {
    SET_VAR(m_rareInheritedData, m_textIndentType, v);
  }

  // text-justify
  static TextJustify initialTextJustify() { return TextJustifyAuto; }
  TextJustify getTextJustify() const {
    return static_cast<TextJustify>(m_rareInheritedData->m_textJustify);
  }
  void setTextJustify(TextJustify v) {
    SET_VAR(m_rareInheritedData, m_textJustify, v);
  }

  // text-orientation (aka -webkit-text-orientation, -epub-text-orientation)
  static TextOrientation initialTextOrientation() {
    return TextOrientationMixed;
  }
  TextOrientation getTextOrientation() const {
    return static_cast<TextOrientation>(m_rareInheritedData->m_textOrientation);
  }
  bool setTextOrientation(TextOrientation);

  // text-shadow
  static ShadowList* initialTextShadow() { return 0; }
  ShadowList* textShadow() const {
    return m_rareInheritedData->textShadow.get();
  }
  void setTextShadow(PassRefPtr<ShadowList>);

  // text-size-adjust (aka -webkit-text-size-adjust)
  static TextSizeAdjust initialTextSizeAdjust() {
    return TextSizeAdjust::adjustAuto();
  }
  TextSizeAdjust getTextSizeAdjust() const {
    return m_rareInheritedData->m_textSizeAdjust;
  }
  void setTextSizeAdjust(TextSizeAdjust sizeAdjust) {
    SET_VAR(m_rareInheritedData, m_textSizeAdjust, sizeAdjust);
  }

  // text-transform (aka -epub-text-transform)
  static ETextTransform initialTextTransform() { return TTNONE; }
  ETextTransform textTransform() const {
    return static_cast<ETextTransform>(m_inheritedData.m_textTransform);
  }
  void setTextTransform(ETextTransform v) {
    m_inheritedData.m_textTransform = v;
  }

  // white-space inherited
  static EWhiteSpace initialWhiteSpace() { return NORMAL; }
  EWhiteSpace whiteSpace() const {
    return static_cast<EWhiteSpace>(m_inheritedData.m_whiteSpace);
  }
  void setWhiteSpace(EWhiteSpace v) { m_inheritedData.m_whiteSpace = v; }

  // word-break inherited (aka -epub-word-break)
  static EWordBreak initialWordBreak() { return NormalWordBreak; }
  EWordBreak wordBreak() const {
    return static_cast<EWordBreak>(m_rareInheritedData->wordBreak);
  }
  void setWordBreak(EWordBreak b) {
    SET_VAR(m_rareInheritedData, wordBreak, b);
  }

  // -webkit-line-break
  static LineBreak initialLineBreak() { return LineBreakAuto; }
  LineBreak getLineBreak() const {
    return static_cast<LineBreak>(m_rareInheritedData->lineBreak);
  }
  void setLineBreak(LineBreak b) { SET_VAR(m_rareInheritedData, lineBreak, b); }

  // writing-mode (aka -webkit-writing-mode, -epub-writing-mode)
  static WritingMode initialWritingMode() { return TopToBottomWritingMode; }
  WritingMode getWritingMode() const {
    return static_cast<WritingMode>(m_inheritedData.m_writingMode);
  }
  bool setWritingMode(WritingMode v) {
    if (v == getWritingMode())
      return false;

    m_inheritedData.m_writingMode = v;
    return true;
  }

  // Text emphasis properties.
  static TextEmphasisFill initialTextEmphasisFill() {
    return TextEmphasisFillFilled;
  }
  static TextEmphasisMark initialTextEmphasisMark() {
    return TextEmphasisMarkNone;
  }
  static const AtomicString& initialTextEmphasisCustomMark() {
    return nullAtom;
  }
  TextEmphasisFill getTextEmphasisFill() const {
    return static_cast<TextEmphasisFill>(m_rareInheritedData->textEmphasisFill);
  }
  TextEmphasisMark getTextEmphasisMark() const;
  const AtomicString& textEmphasisCustomMark() const {
    return m_rareInheritedData->textEmphasisCustomMark;
  }
  const AtomicString& textEmphasisMarkString() const;
  void setTextEmphasisFill(TextEmphasisFill fill) {
    SET_VAR(m_rareInheritedData, textEmphasisFill, fill);
  }
  void setTextEmphasisMark(TextEmphasisMark mark) {
    SET_VAR(m_rareInheritedData, textEmphasisMark, mark);
  }
  void setTextEmphasisCustomMark(const AtomicString& mark) {
    SET_VAR(m_rareInheritedData, textEmphasisCustomMark, mark);
  }

  // -webkit-text-emphasis-color (aka -epub-text-emphasis-color)
  void setTextEmphasisColor(const StyleColor& c) {
    SET_VAR_WITH_SETTER(m_rareInheritedData, textEmphasisColor,
                        setTextEmphasisColor, c);
  }

  // -webkit-text-emphasis-position
  static TextEmphasisPosition initialTextEmphasisPosition() {
    return TextEmphasisPositionOver;
  }
  TextEmphasisPosition getTextEmphasisPosition() const {
    return static_cast<TextEmphasisPosition>(
        m_rareInheritedData->textEmphasisPosition);
  }
  void setTextEmphasisPosition(TextEmphasisPosition position) {
    SET_VAR(m_rareInheritedData, textEmphasisPosition, position);
  }

  // -webkit-box-direction
  static EBoxDirection initialBoxDirection() { return BNORMAL; }
  EBoxDirection boxDirection() const {
    return static_cast<EBoxDirection>(m_inheritedData.m_boxDirection);
  }
  void setBoxDirection(EBoxDirection d) { m_inheritedData.m_boxDirection = d; }

  // -webkit-highlight
  static const AtomicString& initialHighlight() { return nullAtom; }
  const AtomicString& highlight() const {
    return m_rareInheritedData->highlight;
  }
  void setHighlight(const AtomicString& h) {
    SET_VAR(m_rareInheritedData, highlight, h);
  }

  // -webkit-line-clamp
  static LineClampValue initialLineClamp() { return LineClampValue(); }
  const LineClampValue& lineClamp() const {
    return m_rareNonInheritedData->lineClamp;
  }
  void setLineClamp(LineClampValue c) {
    SET_VAR(m_rareNonInheritedData, lineClamp, c);
  }

  // -webkit-print-color-adjust
  static PrintColorAdjust initialPrintColorAdjust() {
    return PrintColorAdjustEconomy;
  }
  PrintColorAdjust getPrintColorAdjust() const {
    return static_cast<PrintColorAdjust>(m_inheritedData.m_printColorAdjust);
  }
  void setPrintColorAdjust(PrintColorAdjust value) {
    m_inheritedData.m_printColorAdjust = value;
  }

  // -webkit-rtl-ordering
  static Order initialRTLOrdering() { return LogicalOrder; }
  Order rtlOrdering() const {
    return static_cast<Order>(m_inheritedData.m_rtlOrdering);
  }
  void setRTLOrdering(Order o) { m_inheritedData.m_rtlOrdering = o; }

  // -webkit-ruby-position
  static RubyPosition initialRubyPosition() { return RubyPositionBefore; }
  RubyPosition getRubyPosition() const {
    return static_cast<RubyPosition>(m_rareInheritedData->m_rubyPosition);
  }
  void setRubyPosition(RubyPosition position) {
    SET_VAR(m_rareInheritedData, m_rubyPosition, position);
  }

  // -webkit-tap-highlight-color
  static Color initialTapHighlightColor();
  Color tapHighlightColor() const {
    return m_rareInheritedData->tapHighlightColor;
  }
  void setTapHighlightColor(const Color& c) {
    SET_VAR(m_rareInheritedData, tapHighlightColor, c);
  }

  // -webkit-text-fill-color
  void setTextFillColor(const StyleColor& c) {
    SET_VAR_WITH_SETTER(m_rareInheritedData, textFillColor, setTextFillColor,
                        c);
  }

  // -webkit-text-security
  static ETextSecurity initialTextSecurity() { return TSNONE; }
  ETextSecurity textSecurity() const {
    return static_cast<ETextSecurity>(m_rareInheritedData->textSecurity);
  }
  void setTextSecurity(ETextSecurity aTextSecurity) {
    SET_VAR(m_rareInheritedData, textSecurity, aTextSecurity);
  }

  // -webkit-text-stroke-color
  void setTextStrokeColor(const StyleColor& c) {
    SET_VAR_WITH_SETTER(m_rareInheritedData, textStrokeColor,
                        setTextStrokeColor, c);
  }

  // -webkit-text-stroke-width
  static float initialTextStrokeWidth() { return 0; }
  float textStrokeWidth() const { return m_rareInheritedData->textStrokeWidth; }
  void setTextStrokeWidth(float w) {
    SET_VAR(m_rareInheritedData, textStrokeWidth, w);
  }

  // -webkit-user-drag
  static EUserDrag initialUserDrag() { return DRAG_AUTO; }
  EUserDrag userDrag() const {
    return static_cast<EUserDrag>(m_rareNonInheritedData->userDrag);
  }
  void setUserDrag(EUserDrag d) {
    SET_VAR(m_rareNonInheritedData, userDrag, d);
  }

  // -webkit-user-modify
  static EUserModify initialUserModify() { return READ_ONLY; }
  EUserModify userModify() const {
    return static_cast<EUserModify>(m_rareInheritedData->userModify);
  }
  void setUserModify(EUserModify u) {
    SET_VAR(m_rareInheritedData, userModify, u);
  }

  // -webkit-user-select
  static EUserSelect initialUserSelect() { return SELECT_TEXT; }
  EUserSelect userSelect() const {
    return static_cast<EUserSelect>(m_rareInheritedData->userSelect);
  }
  void setUserSelect(EUserSelect s) {
    SET_VAR(m_rareInheritedData, userSelect, s);
  }

  // Font properties.
  const Font& font() const;
  void setFont(const Font&);
  const FontMetrics& getFontMetrics() const;
  const FontDescription& getFontDescription() const;
  bool setFontDescription(const FontDescription&);

  // font-size
  int fontSize() const;
  float specifiedFontSize() const;
  float computedFontSize() const;

  // font-size-adjust
  float fontSizeAdjust() const;
  bool hasFontSizeAdjust() const;

  // font-weight
  FontWeight fontWeight() const;

  // font-stretch
  FontStretch fontStretch() const;

  // -webkit-locale
  const AtomicString& locale() const {
    return LayoutLocale::localeString(getFontDescription().locale());
  }

  // 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 *m_svgStyle.get(); }
  SVGComputedStyle& accessSVGStyle() { return *m_svgStyle.access(); }

  // baseline-shift
  EBaselineShift baselineShift() const { return svgStyle().baselineShift(); }
  const Length& baselineShiftValue() const {
    return svgStyle().baselineShiftValue();
  }
  void setBaselineShiftValue(const Length& value) {
    SVGComputedStyle& svgStyle = accessSVGStyle();
    svgStyle.setBaselineShift(BS_LENGTH);
    svgStyle.setBaselineShiftValue(value);
  }

  // cx
  void setCx(const Length& cx) { accessSVGStyle().setCx(cx); }

  // cy
  void setCy(const Length& cy) { accessSVGStyle().setCy(cy); }

  // d
  void setD(PassRefPtr<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(PassRefPtr<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
  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 emptyState() || hasExplicitlyInheritedProperties();
  }
  void copyChildDependentFlagsFrom(const ComputedStyle&);

  // Counters.
  const CounterDirectiveMap* counterDirectives() 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&,
                                      PassRefPtr<CSSVariableData>);
  void setUnresolvedNonInheritedVariable(const AtomicString&,
                                         PassRefPtr<CSSVariableData>);

  void setResolvedUnregisteredVariable(const AtomicString&,
                                       PassRefPtr<CSSVariableData>);
  void setResolvedInheritedVariable(const AtomicString&,
                                    PassRefPtr<CSSVariableData>,
                                    const CSSValue*);
  void setResolvedNonInheritedVariable(const AtomicString&,
                                       PassRefPtr<CSSVariableData>,
                                       const CSSValue*);

  void removeInheritedVariable(const AtomicString&);
  void removeNonInheritedVariable(const AtomicString&);

  void setHasVariableReferenceFromNonInheritedProperty() {
    m_nonInheritedData.m_variableReference = true;
  }
  bool hasVariableReferenceFromNonInheritedProperty() const {
    return m_nonInheritedData.m_variableReference;
  }

  // Animations.
  CSSAnimationData& accessAnimations();
  const CSSAnimationData* animations() const {
    return m_rareNonInheritedData->m_animations.get();
  }

  // Transitions.
  const CSSTransitionData* transitions() const {
    return m_rareNonInheritedData->m_transitions.get();
  }
  CSSTransitionData& accessTransitions();

  // Callback selectors.
  const Vector<String>& callbackSelectors() const {
    return m_rareNonInheritedData->m_callbackSelectors;
  }
  void addCallbackSelector(const String& selector);

  // Non-property flags.
  bool hasViewportUnits() const {
    return m_nonInheritedData.m_hasViewportUnits;
  }
  void setHasViewportUnits(bool hasViewportUnits = true) const {
    m_nonInheritedData.m_hasViewportUnits = hasViewportUnits;
  }

  bool hasRemUnits() const { return m_nonInheritedData.m_hasRemUnits; }
  void setHasRemUnits() const { m_nonInheritedData.m_hasRemUnits = true; }

  bool affectedByFocus() const { return m_nonInheritedData.m_affectedByFocus; }
  void setAffectedByFocus() { m_nonInheritedData.m_affectedByFocus = true; }

  bool affectedByHover() const { return m_nonInheritedData.m_affectedByHover; }
  void setAffectedByHover() { m_nonInheritedData.m_affectedByHover = true; }

  bool affectedByActive() const {
    return m_nonInheritedData.m_affectedByActive;
  }
  void setAffectedByActive() { m_nonInheritedData.m_affectedByActive = true; }

  bool affectedByDrag() const { return m_nonInheritedData.m_affectedByDrag; }
  void setAffectedByDrag() { m_nonInheritedData.m_affectedByDrag = true; }

  bool emptyState() const { return m_nonInheritedData.m_emptyState; }
  void setEmptyState(bool b) {
    setUnique();
    m_nonInheritedData.m_emptyState = b;
  }

  bool hasInlineTransform() const {
    return m_rareNonInheritedData->m_hasInlineTransform;
  }
  void setHasInlineTransform(bool b) {
    SET_VAR(m_rareNonInheritedData, m_hasInlineTransform, b);
  }

  bool hasCompositorProxy() const {
    return m_rareNonInheritedData->m_hasCompositorProxy;
  }
  void setHasCompositorProxy(bool b) {
    SET_VAR(m_rareNonInheritedData, m_hasCompositorProxy, b);
  }

  bool isLink() const { return m_nonInheritedData.m_isLink; }
  void setIsLink(bool b) { m_nonInheritedData.m_isLink = b; }

  EInsideLink insideLink() const {
    return static_cast<EInsideLink>(m_inheritedData.m_insideLink);
  }
  void setInsideLink(EInsideLink insideLink) {
    m_inheritedData.m_insideLink = insideLink;
  }

  bool hasExplicitlyInheritedProperties() const {
    return m_nonInheritedData.m_explicitInheritance;
  }
  void setHasExplicitlyInheritedProperties() {
    m_nonInheritedData.m_explicitInheritance = true;
  }

  bool requiresAcceleratedCompositingForExternalReasons(bool b) {
    return m_rareNonInheritedData
        ->m_requiresAcceleratedCompositingForExternalReasons;
  }
  void setRequiresAcceleratedCompositingForExternalReasons(bool b) {
    SET_VAR(m_rareNonInheritedData,
            m_requiresAcceleratedCompositingForExternalReasons, b);
  }

  bool hasAuthorBackground() const {
    return m_rareNonInheritedData->m_hasAuthorBackground;
  };
  void setHasAuthorBackground(bool authorBackground) {
    SET_VAR(m_rareNonInheritedData, m_hasAuthorBackground, authorBackground);
  }

  bool hasAuthorBorder() const {
    return m_rareNonInheritedData->m_hasAuthorBorder;
  };
  void setHasAuthorBorder(bool authorBorder) {
    SET_VAR(m_rareNonInheritedData, m_hasAuthorBorder, authorBorder);
  }

  // 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 m_rareNonInheritedData->m_isStackingContext;
  }
  void setIsStackingContext(bool b) {
    SET_VAR(m_rareNonInheritedData, m_isStackingContext, b);
  }

  // A unique style is one that has matches something that makes it impossible to share.
  bool unique() const { return m_nonInheritedData.m_unique; }
  void setUnique() { m_nonInheritedData.m_unique = true; }

  float textAutosizingMultiplier() const {
    return m_styleInheritedData->textAutosizingMultiplier;
  }
  void setTextAutosizingMultiplier(float);

  bool selfOrAncestorHasDirAutoAttribute() const {
    return m_rareInheritedData->m_selfOrAncestorHasDirAutoAttribute;
  }
  void setSelfOrAncestorHasDirAutoAttribute(bool v) {
    SET_VAR(m_rareInheritedData, m_selfOrAncestorHasDirAutoAttribute, v);
  }

  // Animation flags.
  bool hasCurrentOpacityAnimation() const {
    return m_rareNonInheritedData->m_hasCurrentOpacityAnimation;
  }
  void setHasCurrentOpacityAnimation(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_hasCurrentOpacityAnimation, b);
  }

  bool hasCurrentTransformAnimation() const {
    return m_rareNonInheritedData->m_hasCurrentTransformAnimation;
  }
  void setHasCurrentTransformAnimation(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_hasCurrentTransformAnimation, b);
  }

  bool hasCurrentFilterAnimation() const {
    return m_rareNonInheritedData->m_hasCurrentFilterAnimation;
  }
  void setHasCurrentFilterAnimation(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_hasCurrentFilterAnimation, b);
  }

  bool hasCurrentBackdropFilterAnimation() const {
    return m_rareNonInheritedData->m_hasCurrentBackdropFilterAnimation;
  }
  void setHasCurrentBackdropFilterAnimation(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_hasCurrentBackdropFilterAnimation, b);
  }

  bool isRunningOpacityAnimationOnCompositor() const {
    return m_rareNonInheritedData->m_runningOpacityAnimationOnCompositor;
  }
  void setIsRunningOpacityAnimationOnCompositor(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_runningOpacityAnimationOnCompositor, b);
  }

  bool isRunningTransformAnimationOnCompositor() const {
    return m_rareNonInheritedData->m_runningTransformAnimationOnCompositor;
  }
  void setIsRunningTransformAnimationOnCompositor(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_runningTransformAnimationOnCompositor, b);
  }

  bool isRunningFilterAnimationOnCompositor() const {
    return m_rareNonInheritedData->m_runningFilterAnimationOnCompositor;
  }
  void setIsRunningFilterAnimationOnCompositor(bool b = true) {
    SET_VAR(m_rareNonInheritedData, m_runningFilterAnimationOnCompositor, b);
  }

  bool isRunningBackdropFilterAnimationOnCompositor() const {
    return m_rareNonInheritedData->m_runningBackdropFilterAnimationOnCompositor;
  }
  void setIsRunningBackdropFilterAnimationOnCompositor(bool b = true) {
    SET_VAR(m_rareNonInheritedData,
            m_runningBackdropFilterAnimationOnCompositor, b);
  }

  // Column utility functions.
  void clearMultiCol();
  bool specifiesColumns() const {
    return !hasAutoColumnCount() || !hasAutoColumnWidth();
  }
  bool columnRuleIsTransparent() const {
    return m_rareNonInheritedData->m_multiCol->m_rule.isTransparent();
  }
  bool columnRuleEquivalent(const ComputedStyle* otherStyle) const;
  void inheritColumnPropertiesFrom(const ComputedStyle& parent) {
    m_rareNonInheritedData.access()->m_multiCol =
        parent.m_rareNonInheritedData->m_multiCol;
  }

  // Flex utility functions.
  bool isColumnFlexDirection() const {
    return flexDirection() == FlowColumn ||
           flexDirection() == FlowColumnReverse;
  }
  bool isReverseFlexDirection() const {
    return flexDirection() == FlowRowReverse ||
           flexDirection() == FlowColumnReverse;
  }
  bool hasBoxReflect() const { return boxReflect(); }
  bool reflectionDataEquivalent(const ComputedStyle* otherStyle) const {
    return m_rareNonInheritedData->reflectionDataEquivalent(
        *otherStyle->m_rareNonInheritedData);
  }

  // Mask utility functions.
  bool hasMask() const {
    return m_rareNonInheritedData->m_mask.hasImage() ||
           m_rareNonInheritedData->m_maskBoxImage.hasImage();
  }
  StyleImage* maskImage() const {
    return m_rareNonInheritedData->m_mask.image();
  }
  FillLayer& accessMaskLayers() {
    return m_rareNonInheritedData.access()->m_mask;
  }
  const FillLayer& maskLayers() const { return m_rareNonInheritedData->m_mask; }
  const NinePieceImage& maskBoxImage() const {
    return m_rareNonInheritedData->m_maskBoxImage;
  }
  bool maskBoxImageSlicesFill() const {
    return m_rareNonInheritedData->m_maskBoxImage.fill();
  }
  void adjustMaskLayers() {
    if (maskLayers().next()) {
      accessMaskLayers().cullEmptyLayers();
      accessMaskLayers().fillUnsetProperties();
    }
  }
  void setMaskBoxImage(const NinePieceImage& b) {
    SET_VAR(m_rareNonInheritedData, m_maskBoxImage, b);
  }
  void setMaskBoxImageSlicesFill(bool fill) {
    m_rareNonInheritedData.access()->m_maskBoxImage.setFill(fill);
  }

  // Text-combine utility functions.
  bool hasTextCombine() const { return getTextCombine() != TextCombineNone; }

  // Grid utility functions.
  const Vector<GridTrackSize>& gridAutoRepeatColumns() const {
    return m_rareNonInheritedData->m_grid->m_gridAutoRepeatColumns;
  }
  const Vector<GridTrackSize>& gridAutoRepeatRows() const {
    return m_rareNonInheritedData->m_grid->m_gridAutoRepeatRows;
  }
  size_t gridAutoRepeatColumnsInsertionPoint() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatColumnsInsertionPoint;
  }
  size_t gridAutoRepeatRowsInsertionPoint() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatRowsInsertionPoint;
  }
  AutoRepeatType gridAutoRepeatColumnsType() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatColumnsType;
  }
  AutoRepeatType gridAutoRepeatRowsType() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatRowsType;
  }
  const NamedGridLinesMap& namedGridColumnLines() const {
    return m_rareNonInheritedData->m_grid->m_namedGridColumnLines;
  }
  const NamedGridLinesMap& namedGridRowLines() const {
    return m_rareNonInheritedData->m_grid->m_namedGridRowLines;
  }
  const OrderedNamedGridLines& orderedNamedGridColumnLines() const {
    return m_rareNonInheritedData->m_grid->m_orderedNamedGridColumnLines;
  }
  const OrderedNamedGridLines& orderedNamedGridRowLines() const {
    return m_rareNonInheritedData->m_grid->m_orderedNamedGridRowLines;
  }
  const NamedGridLinesMap& autoRepeatNamedGridColumnLines() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatNamedGridColumnLines;
  }
  const NamedGridLinesMap& autoRepeatNamedGridRowLines() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatNamedGridRowLines;
  }
  const OrderedNamedGridLines& autoRepeatOrderedNamedGridColumnLines() const {
    return m_rareNonInheritedData->m_grid
        ->m_autoRepeatOrderedNamedGridColumnLines;
  }
  const OrderedNamedGridLines& autoRepeatOrderedNamedGridRowLines() const {
    return m_rareNonInheritedData->m_grid->m_autoRepeatOrderedNamedGridRowLines;
  }
  const NamedGridAreaMap& namedGridArea() const {
    return m_rareNonInheritedData->m_grid->m_namedGridArea;
  }
  size_t namedGridAreaRowCount() const {
    return m_rareNonInheritedData->m_grid->m_namedGridAreaRowCount;
  }
  size_t namedGridAreaColumnCount() const {
    return m_rareNonInheritedData->m_grid->m_namedGridAreaColumnCount;
  }
  GridAutoFlow getGridAutoFlow() const {
    return static_cast<GridAutoFlow>(
        m_rareNonInheritedData->m_grid->m_gridAutoFlow);
  }
  bool isGridAutoFlowDirectionRow() const {
    return (m_rareNonInheritedData->m_grid->m_gridAutoFlow &
            InternalAutoFlowDirectionRow) == InternalAutoFlowDirectionRow;
  }
  bool isGridAutoFlowDirectionColumn() const {
    return (m_rareNonInheritedData->m_grid->m_gridAutoFlow &
            InternalAutoFlowDirectionColumn) == InternalAutoFlowDirectionColumn;
  }
  bool isGridAutoFlowAlgorithmSparse() const {
    return (m_rareNonInheritedData->m_grid->m_gridAutoFlow &
            InternalAutoFlowAlgorithmSparse) == InternalAutoFlowAlgorithmSparse;
  }
  bool isGridAutoFlowAlgorithmDense() const {
    return (m_rareNonInheritedData->m_grid->m_gridAutoFlow &
            InternalAutoFlowAlgorithmDense) == InternalAutoFlowAlgorithmDense;
  }
  void setGridAutoRepeatColumns(const Vector<GridTrackSize>& trackSizes) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoRepeatColumns,
                   trackSizes);
  }
  void setGridAutoRepeatRows(const Vector<GridTrackSize>& trackSizes) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoRepeatRows,
                   trackSizes);
  }
  void setGridAutoRepeatColumnsInsertionPoint(const size_t insertionPoint) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_autoRepeatColumnsInsertionPoint, insertionPoint);
  }
  void setGridAutoRepeatRowsInsertionPoint(const size_t insertionPoint) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_autoRepeatRowsInsertionPoint, insertionPoint);
  }
  void setGridAutoRepeatColumnsType(const AutoRepeatType autoRepeatType) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_autoRepeatColumnsType,
                   autoRepeatType);
  }
  void setGridAutoRepeatRowsType(const AutoRepeatType autoRepeatType) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_autoRepeatRowsType,
                   autoRepeatType);
  }
  void setNamedGridColumnLines(const NamedGridLinesMap& namedGridColumnLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_namedGridColumnLines,
                   namedGridColumnLines);
  }
  void setNamedGridRowLines(const NamedGridLinesMap& namedGridRowLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_namedGridRowLines,
                   namedGridRowLines);
  }
  void setOrderedNamedGridColumnLines(
      const OrderedNamedGridLines& orderedNamedGridColumnLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_orderedNamedGridColumnLines, orderedNamedGridColumnLines);
  }
  void setOrderedNamedGridRowLines(
      const OrderedNamedGridLines& orderedNamedGridRowLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_orderedNamedGridRowLines,
                   orderedNamedGridRowLines);
  }
  void setAutoRepeatNamedGridColumnLines(
      const NamedGridLinesMap& namedGridColumnLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_autoRepeatNamedGridColumnLines, namedGridColumnLines);
  }
  void setAutoRepeatNamedGridRowLines(
      const NamedGridLinesMap& namedGridRowLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_autoRepeatNamedGridRowLines, namedGridRowLines);
  }
  void setAutoRepeatOrderedNamedGridColumnLines(
      const OrderedNamedGridLines& orderedNamedGridColumnLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_autoRepeatOrderedNamedGridColumnLines,
                   orderedNamedGridColumnLines);
  }
  void setAutoRepeatOrderedNamedGridRowLines(
      const OrderedNamedGridLines& orderedNamedGridRowLines) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid,
                   m_autoRepeatOrderedNamedGridRowLines,
                   orderedNamedGridRowLines);
  }
  void setNamedGridArea(const NamedGridAreaMap& namedGridArea) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_namedGridArea,
                   namedGridArea);
  }
  void setNamedGridAreaRowCount(size_t rowCount) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_namedGridAreaRowCount,
                   rowCount);
  }
  void setNamedGridAreaColumnCount(size_t columnCount) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_namedGridAreaColumnCount,
                   columnCount);
  }

  // align-content utility functions.
  ContentPosition alignContentPosition() const {
    return m_rareNonInheritedData->m_alignContent.position();
  }
  ContentDistributionType alignContentDistribution() const {
    return m_rareNonInheritedData->m_alignContent.distribution();
  }
  OverflowAlignment alignContentOverflowAlignment() const {
    return m_rareNonInheritedData->m_alignContent.overflow();
  }
  void setAlignContentPosition(ContentPosition position) {
    m_rareNonInheritedData.access()->m_alignContent.setPosition(position);
  }
  void setAlignContentDistribution(ContentDistributionType distribution) {
    m_rareNonInheritedData.access()->m_alignContent.setDistribution(
        distribution);
  }
  void setAlignContentOverflow(OverflowAlignment overflow) {
    m_rareNonInheritedData.access()->m_alignContent.setOverflow(overflow);
  }

  // justify-content utility functions.
  ContentPosition justifyContentPosition() const {
    return m_rareNonInheritedData->m_justifyContent.position();
  }
  ContentDistributionType justifyContentDistribution() const {
    return m_rareNonInheritedData->m_justifyContent.distribution();
  }
  OverflowAlignment justifyContentOverflowAlignment() const {
    return m_rareNonInheritedData->m_justifyContent.overflow();
  }
  void setJustifyContentPosition(ContentPosition position) {
    m_rareNonInheritedData.access()->m_justifyContent.setPosition(position);
  }
  void setJustifyContentDistribution(ContentDistributionType distribution) {
    m_rareNonInheritedData.access()->m_justifyContent.setDistribution(
        distribution);
  }
  void setJustifyContentOverflow(OverflowAlignment overflow) {
    m_rareNonInheritedData.access()->m_justifyContent.setOverflow(overflow);
  }

  // align-items utility functions.
  ItemPosition alignItemsPosition() const {
    return m_rareNonInheritedData->m_alignItems.position();
  }
  OverflowAlignment alignItemsOverflowAlignment() const {
    return m_rareNonInheritedData->m_alignItems.overflow();
  }
  void setAlignItemsPosition(ItemPosition position) {
    m_rareNonInheritedData.access()->m_alignItems.setPosition(position);
  }
  void setAlignItemsOverflow(OverflowAlignment overflow) {
    m_rareNonInheritedData.access()->m_alignItems.setOverflow(overflow);
  }

  // justify-items utility functions.
  ItemPosition justifyItemsPosition() const {
    return m_rareNonInheritedData->m_justifyItems.position();
  }
  OverflowAlignment justifyItemsOverflowAlignment() const {
    return m_rareNonInheritedData->m_justifyItems.overflow();
  }
  ItemPositionType justifyItemsPositionType() const {
    return m_rareNonInheritedData->m_justifyItems.positionType();
  }
  void setJustifyItemsPosition(ItemPosition position) {
    m_rareNonInheritedData.access()->m_justifyItems.setPosition(position);
  }
  void setJustifyItemsOverflow(OverflowAlignment overflow) {
    m_rareNonInheritedData.access()->m_justifyItems.setOverflow(overflow);
  }
  void setJustifyItemsPositionType(ItemPositionType positionType) {
    m_rareNonInheritedData.access()->m_justifyItems.setPositionType(
        positionType);
  }

  // align-self utility functions.
  ItemPosition alignSelfPosition() const {
    return m_rareNonInheritedData->m_alignSelf.position();
  }
  OverflowAlignment alignSelfOverflowAlignment() const {
    return m_rareNonInheritedData->m_alignSelf.overflow();
  }
  void setAlignSelfPosition(ItemPosition position) {
    m_rareNonInheritedData.access()->m_alignSelf.setPosition(position);
  }
  void setAlignSelfOverflow(OverflowAlignment overflow) {
    m_rareNonInheritedData.access()->m_alignSelf.setOverflow(overflow);
  }

  // justify-self utility functions.
  ItemPosition justifySelfPosition() const {
    return m_rareNonInheritedData->m_justifySelf.position();
  }
  OverflowAlignment justifySelfOverflowAlignment() const {
    return m_rareNonInheritedData->m_justifySelf.overflow();
  }
  void setJustifySelfPosition(ItemPosition position) {
    m_rareNonInheritedData.access()->m_justifySelf.setPosition(position);
  }
  void setJustifySelfOverflow(OverflowAlignment overflow) {
    m_rareNonInheritedData.access()->m_justifySelf.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;

  // Line-height utility functions.
  const Length& specifiedLineHeight() const;
  int computedLineHeight() 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()) {
      SET_VAR(m_box, m_width, v);
    } else {
      SET_VAR(m_box, m_height, v);
    }
  }

  void setLogicalHeight(const Length& v) {
    if (isHorizontalWritingMode()) {
      SET_VAR(m_box, m_height, v);
    } else {
      SET_VAR(m_box, m_width, 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 m_surround->margin.nonZero(); }
  bool hasMarginBeforeQuirk() const { return marginBefore().quirk(); }
  bool hasMarginAfterQuirk() const { return marginAfter().quirk(); }
  const Length& marginBefore() const {
    return m_surround->margin.before(getWritingMode());
  }
  const Length& marginAfter() const {
    return m_surround->margin.after(getWritingMode());
  }
  const Length& marginStart() const {
    return m_surround->margin.start(getWritingMode(), direction());
  }
  const Length& marginEnd() const {
    return m_surround->margin.end(getWritingMode(), direction());
  }
  const Length& marginOver() const {
    return m_surround->margin.over(getWritingMode());
  }
  const Length& marginUnder() const {
    return m_surround->margin.under(getWritingMode());
  }
  const Length& marginStartUsing(const ComputedStyle* otherStyle) const {
    return m_surround->margin.start(otherStyle->getWritingMode(),
                                    otherStyle->direction());
  }
  const Length& marginEndUsing(const ComputedStyle* otherStyle) const {
    return m_surround->margin.end(otherStyle->getWritingMode(),
                                  otherStyle->direction());
  }
  const Length& marginBeforeUsing(const ComputedStyle* otherStyle) const {
    return m_surround->margin.before(otherStyle->getWritingMode());
  }
  const Length& marginAfterUsing(const ComputedStyle* otherStyle) const {
    return m_surround->margin.after(otherStyle->getWritingMode());
  }
  void setMarginStart(const Length&);
  void setMarginEnd(const Length&);

  // Padding utility functions.
  const LengthBox& paddingBox() const { return m_surround->padding; }
  const Length& paddingBefore() const {
    return m_surround->padding.before(getWritingMode());
  }
  const Length& paddingAfter() const {
    return m_surround->padding.after(getWritingMode());
  }
  const Length& paddingStart() const {
    return m_surround->padding.start(getWritingMode(), direction());
  }
  const Length& paddingEnd() const {
    return m_surround->padding.end(getWritingMode(), direction());
  }
  const Length& paddingOver() const {
    return m_surround->padding.over(getWritingMode());
  }
  const Length& paddingUnder() const {
    return m_surround->padding.under(getWritingMode());
  }
  bool hasPadding() const { return m_surround->padding.nonZero(); }
  void resetPadding() { SET_VAR(m_surround, padding, LengthBox(Fixed)); }
  void setPaddingBox(const LengthBox& b) { SET_VAR(m_surround, padding, b); }

  // 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 m_surround->border.image().fill();
  }

  void setBorderImageSlicesFill(bool);
  const BorderData& border() const { return m_surround->border; }
  const BorderValue& borderLeft() const { return m_surround->border.left(); }
  const BorderValue& borderRight() const { return m_surround->border.right(); }
  const BorderValue& borderTop() const { return m_surround->border.top(); }
  const BorderValue& borderBottom() const {
    return m_surround->border.bottom();
  }
  const BorderValue& borderBefore() const;
  const BorderValue& borderAfter() const;
  const BorderValue& borderStart() const;
  const BorderValue& borderEnd() const;
  int borderAfterWidth() const;
  int borderBeforeWidth() const;
  int borderEndWidth() const;
  int borderStartWidth() const;
  int borderOverWidth() const;
  int borderUnderWidth() const;

  bool hasBorderFill() const { return m_surround->border.hasBorderFill(); }
  bool hasBorder() const { return m_surround->border.hasBorder(); }
  bool hasBorderDecoration() const { return hasBorder() || hasBorderFill(); }
  bool hasBorderRadius() const { return m_surround->border.hasBorderRadius(); }

  void resetBorder() {
    resetBorderImage();
    resetBorderTop();
    resetBorderRight();
    resetBorderBottom();
    resetBorderLeft();
    resetBorderTopLeftRadius();
    resetBorderTopRightRadius();
    resetBorderBottomLeftRadius();
    resetBorderBottomRightRadius();
  }
  void resetBorderTop() { SET_VAR(m_surround, border.m_top, BorderValue()); }
  void resetBorderRight() {
    SET_VAR(m_surround, border.m_right, BorderValue());
  }
  void resetBorderBottom() {
    SET_VAR(m_surround, border.m_bottom, BorderValue());
  }
  void resetBorderLeft() { SET_VAR(m_surround, border.m_left, BorderValue()); }
  void resetBorderImage() {
    SET_VAR(m_surround, border.m_image, NinePieceImage());
  }
  void resetBorderTopLeftRadius() {
    SET_VAR(m_surround, border.m_topLeft, initialBorderRadius());
  }
  void resetBorderTopRightRadius() {
    SET_VAR(m_surround, border.m_topRight, initialBorderRadius());
  }
  void resetBorderBottomLeftRadius() {
    SET_VAR(m_surround, border.m_bottomLeft, initialBorderRadius());
  }
  void resetBorderBottomRightRadius() {
    SET_VAR(m_surround, border.m_bottomRight, initialBorderRadius());
  }

  void setBorderRadius(const LengthSize& s) {
    setBorderTopLeftRadius(s);
    setBorderTopRightRadius(s);
    setBorderBottomLeftRadius(s);
    setBorderBottomRightRadius(s);
  }
  void setBorderRadius(const IntSize& s) {
    setBorderRadius(
        LengthSize(Length(s.width(), Fixed), Length(s.height(), Fixed)));
  }

  FloatRoundedRect getRoundedBorderFor(
      const LayoutRect& borderRect,
      bool includeLogicalLeftEdge = true,
      bool includeLogicalRightEdge = true) const;
  FloatRoundedRect getRoundedInnerBorderFor(
      const LayoutRect& borderRect,
      bool includeLogicalLeftEdge = true,
      bool includeLogicalRightEdge = true) const;
  FloatRoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect,
                                            const LayoutRectOutsets insets,
                                            bool includeLogicalLeftEdge,
                                            bool includeLogicalRightEdge) const;

  // Float utility functions.
  bool isFloating() const { return floating() != EFloat::None; }

  // Mix-blend-mode utility functions.
  bool hasBlendMode() const { return blendMode() != WebBlendModeNormal; }

  // Motion utility functions.
  bool hasOffset() const {
    return (offsetPosition().x() != Length(Auto)) || offsetPath();
  }

  // Direction utility functions.
  bool isLeftToRightDirection() const { return direction() == LTR; }

  // Perspective utility functions.
  bool hasPerspective() const {
    return m_rareNonInheritedData->m_perspective > 0;
  }

  // Page size utility functions.
  void resetPageSizeType() {
    SET_VAR(m_rareNonInheritedData, m_pageSizeType, PAGE_SIZE_AUTO);
  }

  // Outline utility functions.
  bool hasOutline() const {
    return outlineWidth() > 0 && outlineStyle() > BorderStyleHidden;
  }
  int outlineOutsetExtent() const;
  bool isOutlineEquivalent(const ComputedStyle* otherStyle) const {
    // No other style, so we don't have an outline then we consider them to be the same.
    if (!otherStyle)
      return !hasOutline();
    return m_background->outline().visuallyEqual(
        otherStyle->m_background->outline());
  }
  void setOutlineFromStyle(const ComputedStyle& o) {
    DCHECK(!isOutlineEquivalent(&o));
    m_background.access()->m_outline = o.m_background->m_outline;
  }

  // Position utility functions.
  bool hasOutOfFlowPosition() const {
    return position() == AbsolutePosition || position() == FixedPosition;
  }
  bool hasInFlowPosition() const {
    return position() == RelativePosition || position() == StickyPosition;
  }
  bool hasViewportConstrainedPosition() const {
    return position() == FixedPosition || position() == StickyPosition;
  }

  // Clip utility functions.
  const Length& clipLeft() const { return m_visual->clip.left(); }
  const Length& clipRight() const { return m_visual->clip.right(); }
  const Length& clipTop() const { return m_visual->clip.top(); }
  const Length& clipBottom() const { return m_visual->clip.bottom(); }

  // Offset utility functions.
  // Accessors for positioned object edges that take into account writing mode.
  const Length& logicalLeft() const {
    return m_surround->offset.logicalLeft(getWritingMode());
  }
  const Length& logicalRight() const {
    return m_surround->offset.logicalRight(getWritingMode());
  }
  const Length& logicalTop() const {
    return m_surround->offset.before(getWritingMode());
  }
  const Length& logicalBottom() const {
    return m_surround->offset.after(getWritingMode());
  }

  // 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* otherStyle) const {
    return const_cast<ComputedStyle*>(this)
        ->m_rareNonInheritedData->contentDataEquivalent(
            *const_cast<ComputedStyle*>(otherStyle)->m_rareNonInheritedData);
  }

  // Contain utility functions.
  bool containsPaint() const {
    return m_rareNonInheritedData->m_contain & ContainsPaint;
  }
  bool containsStyle() const {
    return m_rareNonInheritedData->m_contain & ContainsStyle;
  }
  bool containsLayout() const {
    return m_rareNonInheritedData->m_contain & ContainsLayout;
  }
  bool containsSize() const {
    return m_rareNonInheritedData->m_contain & ContainsSize;
  }

  // Display utility functions.
  bool isDisplayReplacedType() const {
    return isDisplayReplacedType(display());
  }
  bool isDisplayInlineType() const { return isDisplayInlineType(display()); }
  bool isOriginalDisplayInlineType() const {
    return isDisplayInlineType(originalDisplay());
  }
  bool isDisplayFlexibleOrGridBox() const {
    return isDisplayFlexibleBox(display()) || isDisplayGridBox(display());
  }
  bool isDisplayFlexibleBox() const { return isDisplayFlexibleBox(display()); }

  // Isolation utility functions.
  bool hasIsolation() const { return isolation() != IsolationAuto; }

  // Content utility functions.
  bool hasContent() const { return contentData(); }

  // Cursor utility functions.
  CursorList* cursors() const { return m_rareInheritedData->cursorData.get(); }
  void addCursor(StyleImage*,
                 bool hotSpotSpecified,
                 const IntPoint& hotSpot = IntPoint());
  void setCursorList(CursorList*);
  void clearCursorList();

  // Text decoration utility functions.
  void applyTextDecorations();
  void clearAppliedTextDecorations();
  void restoreParentTextDecorations(const ComputedStyle& parentStyle);
  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() != OverflowVisible || overflowX() == overflowY());
    return overflowX() == OverflowVisible;
  }
  bool isOverflowPaged() const {
    return overflowY() == OverflowPagedX || overflowY() == OverflowPagedY;
  }

  // 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() == TableLayoutFixed && !logicalWidth().isAuto();
  }

  // Filter/transform utility functions.
  bool has3DTransform() const {
    return m_rareNonInheritedData->m_transform->has3DTransform();
  }
  bool hasTransform() const {
    return hasTransformOperations() || hasOffset() ||
           hasCurrentTransformAnimation() || translate() || rotate() || scale();
  }
  bool hasTransformOperations() const {
    return !m_rareNonInheritedData->m_transform->m_operations.operations()
                .isEmpty();
  }
  ETransformStyle3D usedTransformStyle3D() const {
    return hasGroupingProperty() ? TransformStyle3DFlat : transformStyle3D();
  }
  bool transformDataEquivalent(const ComputedStyle& otherStyle) const {
    return m_rareNonInheritedData->m_transform ==
           otherStyle.m_rareNonInheritedData->m_transform;
  }
  bool preserves3D() const {
    return usedTransformStyle3D() != TransformStyle3DFlat;
  }
  enum ApplyTransformOrigin { IncludeTransformOrigin, ExcludeTransformOrigin };
  enum ApplyMotionPath { IncludeMotionPath, ExcludeMotionPath };
  enum ApplyIndependentTransformProperties {
    IncludeIndependentTransformProperties,
    ExcludeIndependentTransformProperties
  };
  void applyTransform(TransformationMatrix&,
                      const LayoutSize& borderBoxSize,
                      ApplyTransformOrigin,
                      ApplyMotionPath,
                      ApplyIndependentTransformProperties) const;
  void applyTransform(TransformationMatrix&,
                      const FloatRect& boundingBox,
                      ApplyTransformOrigin,
                      ApplyMotionPath,
                      ApplyIndependentTransformProperties) 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 isDocumentElement, bool isInTopLayer);
  bool isStacked() const {
    return isStackingContext() || position() != StaticPosition;
  }

  // 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 position() != StaticPosition;
  }
  bool canContainFixedPositionObjects() const {
    return hasTransformRelatedProperty() || containsPaint();
  }

  // Whitespace utility functions.
  static bool autoWrap(EWhiteSpace ws) {
    // Nowrap and pre don't automatically wrap.
    return ws != NOWRAP && ws != PRE;
  }

  bool autoWrap() const { return autoWrap(whiteSpace()); }

  static bool preserveNewline(EWhiteSpace ws) {
    // Normal and nowrap do not preserve newlines.
    return ws != NORMAL && ws != NOWRAP;
  }

  bool preserveNewline() const { return preserveNewline(whiteSpace()); }

  static bool collapseWhiteSpace(EWhiteSpace ws) {
    // Pre and prewrap do not collapse whitespace.
    return ws != PRE && ws != PRE_WRAP;
  }

  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() == PRE_WRAP ||
           getLineBreak() == LineBreakAfterWhiteSpace;
  }

  bool breakWords() const {
    return (wordBreak() == BreakWordBreak ||
            overflowWrap() == BreakOverflowWrap) &&
           whiteSpace() != PRE && whiteSpace() != NOWRAP;
  }

  // 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() == OverflowPagedX) == isHorizontalWritingMode();
    return false;
  }

  // Border utility functions.
  bool borderObscuresBackground() const;
  void getBorderEdgeInfo(BorderEdge edges[],
                         bool includeLogicalLeftEdge = true,
                         bool includeLogicalRightEdge = 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 m_background.access()->m_background;
  }
  const FillLayer& backgroundLayers() const {
    return m_background->background();
  }
  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 colorProperty) const;

  // -webkit-appearance utility functions.
  bool hasAppearance() const { return appearance() != NoControlPart; }

  // Other utility functions.
  bool isStyleAvailable() const;
  bool isSharable() const;

 private:
  void setVisitedLinkColor(const Color&);
  void setVisitedLinkBackgroundColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkBackgroundColor, v);
  }
  void setVisitedLinkBorderLeftColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkBorderLeftColor, v);
  }
  void setVisitedLinkBorderRightColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkBorderRightColor, v);
  }
  void setVisitedLinkBorderBottomColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkBorderBottomColor, v);
  }
  void setVisitedLinkBorderTopColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkBorderTopColor, v);
  }
  void setVisitedLinkOutlineColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkOutlineColor, v);
  }
  void setVisitedLinkColumnRuleColor(const StyleColor& v) {
    SET_NESTED_VAR(m_rareNonInheritedData, m_multiCol,
                   m_visitedLinkColumnRuleColor, v);
  }
  void setVisitedLinkTextDecorationColor(const StyleColor& v) {
    SET_VAR(m_rareNonInheritedData, m_visitedLinkTextDecorationColor, v);
  }
  void setVisitedLinkTextEmphasisColor(const StyleColor& v) {
    SET_VAR_WITH_SETTER(m_rareInheritedData, visitedLinkTextEmphasisColor,
                        setVisitedLinkTextEmphasisColor, v);
  }
  void setVisitedLinkTextFillColor(const StyleColor& v) {
    SET_VAR_WITH_SETTER(m_rareInheritedData, visitedLinkTextFillColor,
                        setVisitedLinkTextFillColor, v);
  }
  void setVisitedLinkTextStrokeColor(const StyleColor& v) {
    SET_VAR_WITH_SETTER(m_rareInheritedData, visitedLinkTextStrokeColor,
                        setVisitedLinkTextStrokeColor, v);
  }

  void inheritUnicodeBidiFrom(const ComputedStyle& parent) {
    m_nonInheritedData.m_unicodeBidi = parent.m_nonInheritedData.m_unicodeBidi;
  }

  static bool isDisplayFlexibleBox(EDisplay display) {
    return display == EDisplay::Flex || display == EDisplay::InlineFlex;
  }

  static bool isDisplayGridBox(EDisplay display) {
    return display == EDisplay::Grid || display == EDisplay::InlineGrid;
  }

  static bool isDisplayReplacedType(EDisplay display) {
    return display == EDisplay::InlineBlock || display == EDisplay::InlineBox ||
           display == EDisplay::InlineFlex ||
           display == EDisplay::InlineTable || display == EDisplay::InlineGrid;
  }

  static bool isDisplayInlineType(EDisplay display) {
    return display == EDisplay::Inline || isDisplayReplacedType(display);
  }

  static bool isDisplayTableType(EDisplay display) {
    return display == EDisplay::Table || display == EDisplay::InlineTable ||
           display == EDisplay::TableRowGroup ||
           display == EDisplay::TableHeaderGroup ||
           display == EDisplay::TableFooterGroup ||
           display == EDisplay::TableRow ||
           display == EDisplay::TableColumnGroup ||
           display == EDisplay::TableColumn || display == EDisplay::TableCell ||
           display == EDisplay::TableCaption;
  }

  // Color accessors are all private to make sure callers use visitedDependentColor instead to access them.
  StyleColor borderLeftColor() const {
    return m_surround->border.left().color();
  }
  StyleColor borderRightColor() const {
    return m_surround->border.right().color();
  }
  StyleColor borderTopColor() const { return m_surround->border.top().color(); }
  StyleColor borderBottomColor() const {
    return m_surround->border.bottom().color();
  }
  StyleColor backgroundColor() const { return m_background->color(); }
  Color color() const;
  StyleColor columnRuleColor() const {
    return m_rareNonInheritedData->m_multiCol->m_rule.color();
  }
  StyleColor outlineColor() const { return m_background->outline().color(); }
  StyleColor textEmphasisColor() const {
    return m_rareInheritedData->textEmphasisColor();
  }
  StyleColor textFillColor() const {
    return m_rareInheritedData->textFillColor();
  }
  StyleColor textStrokeColor() const {
    return m_rareInheritedData->textStrokeColor();
  }
  Color visitedLinkColor() const;
  StyleColor visitedLinkBackgroundColor() const {
    return m_rareNonInheritedData->m_visitedLinkBackgroundColor;
  }
  StyleColor visitedLinkBorderLeftColor() const {
    return m_rareNonInheritedData->m_visitedLinkBorderLeftColor;
  }
  StyleColor visitedLinkBorderRightColor() const {
    return m_rareNonInheritedData->m_visitedLinkBorderRightColor;
  }
  StyleColor visitedLinkBorderBottomColor() const {
    return m_rareNonInheritedData->m_visitedLinkBorderBottomColor;
  }
  StyleColor visitedLinkBorderTopColor() const {
    return m_rareNonInheritedData->m_visitedLinkBorderTopColor;
  }
  StyleColor visitedLinkOutlineColor() const {
    return m_rareNonInheritedData->m_visitedLinkOutlineColor;
  }
  StyleColor visitedLinkColumnRuleColor() const {
    return m_rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor;
  }
  StyleColor textDecorationColor() const {
    return m_rareNonInheritedData->m_textDecorationColor;
  }
  StyleColor visitedLinkTextDecorationColor() const {
    return m_rareNonInheritedData->m_visitedLinkTextDecorationColor;
  }
  StyleColor visitedLinkTextEmphasisColor() const {
    return m_rareInheritedData->visitedLinkTextEmphasisColor();
  }
  StyleColor visitedLinkTextFillColor() const {
    return m_rareInheritedData->visitedLinkTextFillColor();
  }
  StyleColor visitedLinkTextStrokeColor() const {
    return m_rareInheritedData->visitedLinkTextStrokeColor();
  }

  StyleColor decorationColorIncludingFallback(bool visitedLink) const;
  Color colorIncludingFallback(int colorProperty, bool visitedLink) const;

  Color stopColor() const { return svgStyle().stopColor(); }
  Color floodColor() const { return svgStyle().floodColor(); }
  Color lightingColor() const { return svgStyle().lightingColor(); }

  void addAppliedTextDecoration(const AppliedTextDecoration&);
  void applyMotionPathTransform(float originX,
                                float originY,
                                TransformationMatrix&) 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;
  void updatePropertySpecificDifferences(const ComputedStyle& other,
                                         StyleDifference&) const;

  bool requireTransformOrigin(ApplyTransformOrigin applyOrigin,
                              ApplyMotionPath) const;
  static bool shadowListHasCurrentColor(const ShadowList*);

  StyleInheritedVariables& mutableInheritedVariables();
  StyleNonInheritedVariables& mutableNonInheritedVariables();
};

// 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 zoomFactor);

inline int adjustForAbsoluteZoom(int value, const ComputedStyle* style) {
  float zoomFactor = style->effectiveZoom();
  if (zoomFactor == 1)
    return value;
  return adjustForAbsoluteZoom(value, zoomFactor);
}

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 double adjustScrollForAbsoluteZoom(double scrollOffset,
                                          float zoomFactor) {
  return scrollOffset / zoomFactor;
}

inline double adjustScrollForAbsoluteZoom(double scrollOffset,
                                          const ComputedStyle& style) {
  return adjustScrollForAbsoluteZoom(scrollOffset, style.effectiveZoom());
}

inline bool ComputedStyle::setZoom(float f) {
  if (compareEqual(m_visual->m_zoom, f))
    return false;
  m_visual.access()->m_zoom = 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 clampedEffectiveZoom = clampTo<float>(f, 1e-6, 1e6);
  if (compareEqual(m_rareInheritedData->m_effectiveZoom, clampedEffectiveZoom))
    return false;
  m_rareInheritedData.access()->m_effectiveZoom = clampedEffectiveZoom;
  return true;
}

inline bool ComputedStyle::isSharable() const {
  if (unique())
    return false;
  if (hasUniquePseudoStyle())
    return false;
  return true;
}

inline bool ComputedStyle::setTextOrientation(TextOrientation textOrientation) {
  if (compareEqual(m_rareInheritedData->m_textOrientation, textOrientation))
    return false;

  m_rareInheritedData.access()->m_textOrientation = textOrientation;
  return true;
}

inline bool ComputedStyle::hasAnyPublicPseudoStyles() const {
  return PublicPseudoIdMask & m_nonInheritedData.m_pseudoBits;
}

inline bool ComputedStyle::hasPseudoStyle(PseudoId pseudo) const {
  ASSERT(pseudo > PseudoIdNone);
  ASSERT(pseudo < FirstInternalPseudoId);
  return (1 << (pseudo - 1)) & m_nonInheritedData.m_pseudoBits;
}

inline void ComputedStyle::setHasPseudoStyle(PseudoId pseudo) {
  ASSERT(pseudo > PseudoIdNone);
  ASSERT(pseudo < FirstInternalPseudoId);
  m_nonInheritedData.m_pseudoBits |= 1 << (pseudo - 1);
}

inline bool ComputedStyle::hasPseudoElementStyle() const {
  return m_nonInheritedData.m_pseudoBits & ElementPseudoIdMask;
}

}  // namespace blink

#endif  // ComputedStyle_h
