/*
 * 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/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/StyleMotionRotation.h"
#include "core/style/StyleMultiColData.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;

class CORE_EXPORT ComputedStyle: 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_visibility == other.m_visibility)
                && (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_visibility : 2; // EVisibility
        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_floating == other.m_floating
                && 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_floating : 2; // EFloat
        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()
    {
        m_inheritedData.m_emptyCells = initialEmptyCells();
        m_inheritedData.m_captionSide = initialCaptionSide();
        m_inheritedData.m_listStyleType = initialListStyleType();
        m_inheritedData.m_listStylePosition = initialListStylePosition();
        m_inheritedData.m_visibility = static_cast<unsigned>(initialVisibility());
        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 = 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_floating = initialFloating();
        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;

    enum IsAtShadowBoundary {
        AtShadowBoundary,
        NotAtShadowBoundary,
    };

    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(RuntimeEnabledFeatures::cssGridLayoutEnabled() ? ContentPositionNormal : ContentPositionFlexStart, 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 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 = v; }
    void setOriginalDisplay(EDisplay v) { m_nonInheritedData.m_originalDisplay = 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;
    }

    // float
    static EFloat initialFloating() { return NoFloat; }
    EFloat floating() const { return static_cast<EFloat>(m_nonInheritedData.m_floating); }
    void setFloating(EFloat v) { m_nonInheritedData.m_floating = v; }

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

    // motion-path
    static StylePath* initialMotionPath() { return nullptr; }
    StylePath* motionPath() const { return m_rareNonInheritedData->m_transform->m_motion.m_path.get(); }
    void setMotionPath(PassRefPtr<StylePath>);

    // motion-offset
    static Length initialMotionOffset() { return Length(0, Fixed); }
    const Length& motionOffset() const { return m_rareNonInheritedData->m_transform->m_motion.m_offset; }
    void setMotionOffset(const Length& motionOffset) { SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_motion.m_offset, motionOffset); }

    // motion-rotation
    static StyleMotionRotation initialMotionRotation() { return StyleMotionRotation(0, MotionRotationAuto); }
    const StyleMotionRotation& motionRotation() const { return m_rareNonInheritedData->m_transform->m_motion.m_rotation; }
    void setMotionRotation(const StyleMotionRotation& motionRotation) { SET_NESTED_VAR(m_rareNonInheritedData, m_transform, m_motion.m_rotation, motionRotation); }

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

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

    // 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 CaptionSideTop; }
    ECaptionSide captionSide() const { return static_cast<ECaptionSide>(m_inheritedData.m_captionSide); }
    void setCaptionSide(ECaptionSide v) { m_inheritedData.m_captionSide = 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 EmptyCellsShow; }
    EEmptyCells emptyCells() const { return static_cast<EEmptyCells>(m_inheritedData.m_emptyCells); }
    void setEmptyCells(EEmptyCells v) { m_inheritedData.m_emptyCells = 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 ListStylePositionOutside; }
    EListStylePosition listStylePosition() const { return static_cast<EListStylePosition>(m_inheritedData.m_listStylePosition); }
    void setListStylePosition(EListStylePosition v) { m_inheritedData.m_listStylePosition = 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; }

    // visibility
    static EVisibility initialVisibility() { return EVisibility::Visible; }
    EVisibility visibility() const { return static_cast<EVisibility>(m_inheritedData.m_visibility); }
    void setVisibility(EVisibility v) { m_inheritedData.m_visibility = static_cast<unsigned>(v); }
    void setVisibilityIsInherited(bool isInherited) { m_nonInheritedData.m_isVisibilityInherited = isInherited; }

    // 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 StyleVariableData* initialVariables() { return nullptr; }
    StyleVariableData* variables() const;
    void setVariable(const AtomicString&, PassRefPtr<CSSVariableData>);
    void removeVariable(const AtomicString&);
    void setHasVariableReferenceFromNonInheritedProperty() { m_nonInheritedData.m_variableReference = true; }
    bool hasVariableReferenceFromNonInheritedProperty() const { return m_nonInheritedData.m_variableReference; }

    // Call these after setting the CSSVariableData
    void setRegisteredInheritedProperty(const AtomicString&, const CSSValue*);

    // 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 m_nonInheritedData.m_floating != NoFloat; }

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

    // Motion utility functions.
    bool hasMotionPath() const { return motionPath(); }

    // 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() || hasMotionPath() || 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').
    bool hasFilterInducingProperty() const { return hasFilter() || (RuntimeEnabledFeatures::cssBoxReflectFilterEnabled() && 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; }

    bool isDisplayFlexibleBox(EDisplay display) const
    {
        return display == FLEX || display == INLINE_FLEX;
    }

    bool isDisplayGridBox(EDisplay display) const
    {
        return display == GRID || display == INLINE_GRID;
    }

    bool isDisplayReplacedType(EDisplay display) const
    {
        return display == INLINE_BLOCK || display == INLINE_BOX || display == INLINE_FLEX
            || display == INLINE_TABLE || display == INLINE_GRID;
    }

    bool isDisplayInlineType(EDisplay display) const
    {
        return display == INLINE || isDisplayReplacedType(display);
    }

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

// 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
