/*
 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "RenderStyle.h"

#include "ContentData.h"
#include "CSSCustomPropertyValue.h"
#include "CSSParser.h"
#include "CSSPropertyNames.h"
#include "CursorList.h"
#include "FloatRoundedRect.h"
#include "FontCascade.h"
#include "FontSelector.h"
#include "InlineTextBoxStyle.h"
#include "Pagination.h"
#include "QuotesData.h"
#include "RenderObject.h"
#include "RenderTheme.h"
#include "RuntimeEnabledFeatures.h"
#include "ScaleTransformOperation.h"
#include "ShadowData.h"
#include "StyleImage.h"
#include "StyleInheritedData.h"
#include "StyleResolver.h"
#include "StyleScrollSnapPoints.h"
#include "StyleSelfAlignmentData.h"
#include "StyleTreeResolver.h"
#include "WillChangeData.h"
#include <wtf/MathExtras.h>
#include <wtf/PointerComparison.h>
#include <wtf/StdLibExtras.h>
#include <algorithm>

#if ENABLE(TEXT_AUTOSIZING)
#include <wtf/text/StringHash.h>
#endif

namespace WebCore {

struct SameSizeAsBorderValue {
    float m_width;
    Color m_color;
    int m_restBits;
};

COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);

struct SameSizeAsRenderStyle {
    void* dataRefs[7];
    void* ownPtrs[1];
    void* dataRefSvgStyle;
    struct InheritedFlags {
        unsigned m_bitfields[2];
    } m_inheritedFlags;

    struct NonInheritedFlags {
        unsigned m_bitfields[2];
    } m_nonInheritedFlags;
#if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
    bool deletionCheck;
#endif
};

static_assert(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), "RenderStyle should stay small");

RenderStyle& RenderStyle::defaultStyle()
{
    static NeverDestroyed<RenderStyle> style { CreateDefaultStyle };
    return style;
}

RenderStyle RenderStyle::create()
{
    return clone(defaultStyle());
}

std::unique_ptr<RenderStyle> RenderStyle::createPtr()
{
    return clonePtr(defaultStyle());
}

RenderStyle RenderStyle::clone(const RenderStyle& style)
{
    return RenderStyle(style, Clone);
}

std::unique_ptr<RenderStyle> RenderStyle::clonePtr(const RenderStyle& style)
{
    return std::make_unique<RenderStyle>(style, Clone);
}

RenderStyle RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle& parentStyle, EDisplay display)
{
    auto newStyle = create();
    newStyle.inheritFrom(parentStyle);
    newStyle.inheritUnicodeBidiFrom(&parentStyle);
    newStyle.setDisplay(display);
    return newStyle;
}

RenderStyle RenderStyle::createStyleInheritingFromPseudoStyle(const RenderStyle& pseudoStyle)
{
    ASSERT(pseudoStyle.styleType() == BEFORE || pseudoStyle.styleType() == AFTER);

    auto style = create();
    style.inheritFrom(pseudoStyle);
    return style;
}

RenderStyle::RenderStyle(RenderStyle&&) = default;
RenderStyle& RenderStyle::operator=(RenderStyle&&) = default;

RenderStyle::RenderStyle(CreateDefaultStyleTag)
    : m_boxData(StyleBoxData::create())
    , m_visualData(StyleVisualData::create())
    , m_backgroundData(StyleBackgroundData::create())
    , m_surroundData(StyleSurroundData::create())
    , m_rareNonInheritedData(StyleRareNonInheritedData::create())
    , m_rareInheritedData(StyleRareInheritedData::create())
    , m_inheritedData(StyleInheritedData::create())
    , m_svgStyle(SVGRenderStyle::create())
{
    m_inheritedFlags.emptyCells = initialEmptyCells();
    m_inheritedFlags.captionSide = initialCaptionSide();
    m_inheritedFlags.listStyleType = initialListStyleType();
    m_inheritedFlags.listStylePosition = initialListStylePosition();
    m_inheritedFlags.visibility = initialVisibility();
    m_inheritedFlags.textAlign = initialTextAlign();
    m_inheritedFlags.textTransform = initialTextTransform();
    m_inheritedFlags.textDecorations = initialTextDecoration();
    m_inheritedFlags.cursor = initialCursor();
#if ENABLE(CURSOR_VISIBILITY)
    m_inheritedFlags.cursorVisibility = initialCursorVisibility();
#endif
    m_inheritedFlags.direction = initialDirection();
    m_inheritedFlags.whiteSpace = initialWhiteSpace();
    m_inheritedFlags.borderCollapse = initialBorderCollapse();
    m_inheritedFlags.rtlOrdering = initialRTLOrdering();
    m_inheritedFlags.boxDirection = initialBoxDirection();
    m_inheritedFlags.printColorAdjust = initialPrintColorAdjust();
    m_inheritedFlags.pointerEvents = initialPointerEvents();
    m_inheritedFlags.insideLink = NotInsideLink;
    m_inheritedFlags.insideDefaultButton = false;
    m_inheritedFlags.writingMode = initialWritingMode();

    m_nonInheritedFlags.effectiveDisplay = initialDisplay();
    m_nonInheritedFlags.originalDisplay = initialDisplay();
    m_nonInheritedFlags.overflowX = initialOverflowX();
    m_nonInheritedFlags.overflowY = initialOverflowY();
    m_nonInheritedFlags.verticalAlign = initialVerticalAlign();
    m_nonInheritedFlags.clear = initialClear();
    m_nonInheritedFlags.position = initialPosition();
    m_nonInheritedFlags.unicodeBidi = initialUnicodeBidi();
    m_nonInheritedFlags.floating = initialFloating();
    m_nonInheritedFlags.tableLayout = initialTableLayout();
    m_nonInheritedFlags.hasExplicitlySetDirection = false;
    m_nonInheritedFlags.hasExplicitlySetWritingMode = false;
    m_nonInheritedFlags.hasExplicitlySetTextAlign = false;
    m_nonInheritedFlags.hasViewportUnits = false;
    m_nonInheritedFlags.hasExplicitlyInheritedProperties = false;
    m_nonInheritedFlags.isUnique = false;
    m_nonInheritedFlags.emptyState = false;
    m_nonInheritedFlags.firstChildState = false;
    m_nonInheritedFlags.lastChildState = false;
    m_nonInheritedFlags.affectedByHover = false;
    m_nonInheritedFlags.affectedByActive = false;
    m_nonInheritedFlags.affectedByDrag = false;
    m_nonInheritedFlags.isLink = false;
    m_nonInheritedFlags.styleType = NOPSEUDO;
    m_nonInheritedFlags.pseudoBits = NOPSEUDO;

    static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags does not grow");
    static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags does not grow");
}

inline RenderStyle::RenderStyle(const RenderStyle& other, CloneTag)
    : m_boxData(other.m_boxData)
    , m_visualData(other.m_visualData)
    , m_backgroundData(other.m_backgroundData)
    , m_surroundData(other.m_surroundData)
    , m_rareNonInheritedData(other.m_rareNonInheritedData)
    , m_nonInheritedFlags(other.m_nonInheritedFlags)
    , m_rareInheritedData(other.m_rareInheritedData)
    , m_inheritedData(other.m_inheritedData)
    , m_inheritedFlags(other.m_inheritedFlags)
    , m_svgStyle(other.m_svgStyle)
{
}

inline RenderStyle::RenderStyle(RenderStyle& a, RenderStyle&& b)
    : m_boxData(a.m_boxData.replace(WTFMove(b.m_boxData)))
    , m_visualData(a.m_visualData.replace(WTFMove(b.m_visualData)))
    , m_backgroundData(a.m_backgroundData.replace(WTFMove(b.m_backgroundData)))
    , m_surroundData(a.m_surroundData.replace(WTFMove(b.m_surroundData)))
    , m_rareNonInheritedData(a.m_rareNonInheritedData.replace(WTFMove(b.m_rareNonInheritedData)))
    , m_nonInheritedFlags(std::exchange(a.m_nonInheritedFlags, b.m_nonInheritedFlags))
    , m_rareInheritedData(a.m_rareInheritedData.replace(WTFMove(b.m_rareInheritedData)))
    , m_inheritedData(a.m_inheritedData.replace(WTFMove(b.m_inheritedData)))
    , m_inheritedFlags(std::exchange(a.m_inheritedFlags, b.m_inheritedFlags))
    , m_cachedPseudoStyles(std::exchange(a.m_cachedPseudoStyles, WTFMove(b.m_cachedPseudoStyles)))
    , m_svgStyle(a.m_svgStyle.replace(WTFMove(b.m_svgStyle)))
{
}

RenderStyle::~RenderStyle()
{
#if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
    ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
    m_deletionHasBegun = true;
#endif
}

RenderStyle RenderStyle::replace(RenderStyle&& newStyle)
{
    return RenderStyle { *this, WTFMove(newStyle) };
}

static StyleSelfAlignmentData resolvedSelfAlignment(const StyleSelfAlignmentData& value, ItemPosition normalValueBehavior)
{
    if (value.position() == ItemPositionLegacy || value.position() == ItemPositionNormal || value.position() == ItemPositionAuto)
        return { normalValueBehavior, OverflowAlignmentDefault };
    return value;
}

StyleSelfAlignmentData RenderStyle::resolvedAlignItems(ItemPosition normalValueBehaviour) const
{
    return resolvedSelfAlignment(alignItems(), normalValueBehaviour);
}

StyleSelfAlignmentData RenderStyle::resolvedAlignSelf(const RenderStyle* parentStyle, ItemPosition normalValueBehaviour) const
{
    // The auto keyword computes to the parent's align-items computed value.
    // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
    if (!parentStyle || alignSelf().position() != ItemPositionAuto)
        return resolvedSelfAlignment(alignSelf(), normalValueBehaviour);
    return parentStyle->resolvedAlignItems(normalValueBehaviour);
}

StyleSelfAlignmentData RenderStyle::resolvedJustifyItems(ItemPosition normalValueBehaviour) const
{
    return resolvedSelfAlignment(justifyItems(), normalValueBehaviour);
}

StyleSelfAlignmentData RenderStyle::resolvedJustifySelf(const RenderStyle* parentStyle, ItemPosition normalValueBehaviour) const
{
    // The auto keyword computes to the parent's justify-items computed value.
    // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
    if (!parentStyle || justifySelf().position() != ItemPositionAuto)
        return resolvedSelfAlignment(justifySelf(), normalValueBehaviour);
    return parentStyle->resolvedJustifyItems(normalValueBehaviour);
}

static inline StyleContentAlignmentData resolvedContentAlignment(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
{
    return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior : value;
}

StyleContentAlignmentData RenderStyle::resolvedAlignContent(const StyleContentAlignmentData& normalValueBehavior) const
{
    // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
    return resolvedContentAlignment(alignContent(), normalValueBehavior);
}

StyleContentAlignmentData RenderStyle::resolvedJustifyContent(const StyleContentAlignmentData& normalValueBehavior) const
{
    // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
    return resolvedContentAlignment(justifyContent(), normalValueBehavior);
}

static inline ContentPosition resolvedContentAlignmentPosition(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
{
    return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.position() : value.position();
}

static inline ContentDistributionType resolvedContentAlignmentDistribution(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
{
    return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.distribution() : value.distribution();
}

ContentPosition RenderStyle::resolvedJustifyContentPosition(const StyleContentAlignmentData& normalValueBehavior) const
{
    return resolvedContentAlignmentPosition(justifyContent(), normalValueBehavior);
}

ContentDistributionType RenderStyle::resolvedJustifyContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
{
    return resolvedContentAlignmentDistribution(justifyContent(), normalValueBehavior);
}

ContentPosition RenderStyle::resolvedAlignContentPosition(const StyleContentAlignmentData& normalValueBehavior) const
{
    return resolvedContentAlignmentPosition(alignContent(), normalValueBehavior);
}

ContentDistributionType RenderStyle::resolvedAlignContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
{
    return resolvedContentAlignmentDistribution(alignContent(), normalValueBehavior);
}

void RenderStyle::inheritFrom(const RenderStyle& inheritParent)
{
    m_rareInheritedData = inheritParent.m_rareInheritedData;
    m_inheritedData = inheritParent.m_inheritedData;
    m_inheritedFlags = inheritParent.m_inheritedFlags;

    if (m_svgStyle != inheritParent.m_svgStyle)
        m_svgStyle.access().inheritFrom(inheritParent.m_svgStyle.get());
}

void RenderStyle::copyNonInheritedFrom(const RenderStyle& other)
{
    m_boxData = other.m_boxData;
    m_visualData = other.m_visualData;
    m_backgroundData = other.m_backgroundData;
    m_surroundData = other.m_surroundData;
    m_rareNonInheritedData = other.m_rareNonInheritedData;
    m_nonInheritedFlags.copyNonInheritedFrom(other.m_nonInheritedFlags);

    if (m_svgStyle != other.m_svgStyle)
        m_svgStyle.access().copyNonInheritedFrom(other.m_svgStyle.get());

    ASSERT(zoom() == initialZoom());
}

void RenderStyle::copyContentFrom(const RenderStyle& other)
{
    if (!other.m_rareNonInheritedData->content)
        return;
    m_rareNonInheritedData.access().content = other.m_rareNonInheritedData->content->clone();
}

bool RenderStyle::operator==(const RenderStyle& other) const
{
    // compare everything except the pseudoStyle pointer
    return m_inheritedFlags == other.m_inheritedFlags
        && m_nonInheritedFlags == other.m_nonInheritedFlags
        && m_boxData == other.m_boxData
        && m_visualData == other.m_visualData
        && m_backgroundData == other.m_backgroundData
        && m_surroundData == other.m_surroundData
        && m_rareNonInheritedData == other.m_rareNonInheritedData
        && m_rareInheritedData == other.m_rareInheritedData
        && m_inheritedData == other.m_inheritedData
        && m_svgStyle == other.m_svgStyle;
}

bool RenderStyle::hasUniquePseudoStyle() const
{
    if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
        return false;

    for (auto& pseudoStyle : *m_cachedPseudoStyles) {
        if (pseudoStyle->unique())
            return true;
    }

    return false;
}

RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
{
    if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
        return nullptr;

    if (styleType() != NOPSEUDO) 
        return nullptr;

    for (auto& pseudoStyle : *m_cachedPseudoStyles) {
        if (pseudoStyle->styleType() == pid)
            return pseudoStyle.get();
    }

    return nullptr;
}

RenderStyle* RenderStyle::addCachedPseudoStyle(std::unique_ptr<RenderStyle> pseudo)
{
    if (!pseudo)
        return nullptr;

    ASSERT(pseudo->styleType() > NOPSEUDO);

    RenderStyle* result = pseudo.get();

    if (!m_cachedPseudoStyles)
        m_cachedPseudoStyles = std::make_unique<PseudoStyleCache>();

    m_cachedPseudoStyles->append(WTFMove(pseudo));

    return result;
}

void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
{
    if (!m_cachedPseudoStyles)
        return;
    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
        if (pseudoStyle->styleType() == pid) {
            m_cachedPseudoStyles->remove(i);
            return;
        }
    }
}

bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
{
    return m_inheritedFlags != other->m_inheritedFlags
        || m_inheritedData != other->m_inheritedData
        || m_svgStyle->inheritedNotEqual(other->m_svgStyle)
        || m_rareInheritedData != other->m_rareInheritedData;
}

#if ENABLE(TEXT_AUTOSIZING)

static inline unsigned computeFontHash(const FontCascade& font)
{
    IntegerHasher hasher;
    hasher.add(ASCIICaseInsensitiveHash::hash(font.fontDescription().firstFamily()));
    hasher.add(font.fontDescription().specifiedSize());
    return hasher.hash();
}

unsigned RenderStyle::hashForTextAutosizing() const
{
    // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>.
    unsigned hash = m_rareNonInheritedData->appearance;
    hash ^= m_rareNonInheritedData->marginBeforeCollapse;
    hash ^= m_rareNonInheritedData->marginAfterCollapse;
    hash ^= m_rareNonInheritedData->lineClamp.value();
    hash ^= m_rareInheritedData->overflowWrap;
    hash ^= m_rareInheritedData->nbspMode;
    hash ^= m_rareInheritedData->lineBreak;
    hash ^= WTF::FloatHash<float>::hash(m_inheritedData->specifiedLineHeight.value());
    hash ^= computeFontHash(m_inheritedData->fontCascade);
    hash ^= WTF::FloatHash<float>::hash(m_inheritedData->horizontalBorderSpacing);
    hash ^= WTF::FloatHash<float>::hash(m_inheritedData->verticalBorderSpacing);
    hash ^= m_inheritedFlags.boxDirection;
    hash ^= m_inheritedFlags.rtlOrdering;
    hash ^= m_nonInheritedFlags.position;
    hash ^= m_nonInheritedFlags.floating;
    hash ^= m_rareNonInheritedData->textOverflow;
    hash ^= m_rareInheritedData->textSecurity;
    return hash;
}

bool RenderStyle::equalForTextAutosizing(const RenderStyle& other) const
{
    return m_rareNonInheritedData->appearance == other.m_rareNonInheritedData->appearance
        && m_rareNonInheritedData->marginBeforeCollapse == other.m_rareNonInheritedData->marginBeforeCollapse
        && m_rareNonInheritedData->marginAfterCollapse == other.m_rareNonInheritedData->marginAfterCollapse
        && m_rareNonInheritedData->lineClamp == other.m_rareNonInheritedData->lineClamp
        && m_rareInheritedData->textSizeAdjust == other.m_rareInheritedData->textSizeAdjust
        && m_rareInheritedData->overflowWrap == other.m_rareInheritedData->overflowWrap
        && m_rareInheritedData->nbspMode == other.m_rareInheritedData->nbspMode
        && m_rareInheritedData->lineBreak == other.m_rareInheritedData->lineBreak
        && m_rareInheritedData->textSecurity == other.m_rareInheritedData->textSecurity
        && m_inheritedData->specifiedLineHeight == other.m_inheritedData->specifiedLineHeight
        && m_inheritedData->fontCascade.equalForTextAutoSizing(other.m_inheritedData->fontCascade)
        && m_inheritedData->horizontalBorderSpacing == other.m_inheritedData->horizontalBorderSpacing
        && m_inheritedData->verticalBorderSpacing == other.m_inheritedData->verticalBorderSpacing
        && m_inheritedFlags.boxDirection == other.m_inheritedFlags.boxDirection
        && m_inheritedFlags.rtlOrdering == other.m_inheritedFlags.rtlOrdering
        && m_nonInheritedFlags.position == other.m_nonInheritedFlags.position
        && m_nonInheritedFlags.floating == other.m_nonInheritedFlags.floating
        && m_rareNonInheritedData->textOverflow == other.m_rareNonInheritedData->textOverflow;
}

#endif // ENABLE(TEXT_AUTOSIZING)

bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
{
    // This is a fast check that only looks if the data structures are shared.
    return m_inheritedFlags == other->m_inheritedFlags
        && m_inheritedData.ptr() == other->m_inheritedData.ptr()
        && m_svgStyle.ptr() == other->m_svgStyle.ptr()
        && m_rareInheritedData.ptr() == other->m_rareInheritedData.ptr();
}

static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width)
{
    // If any unit types are different, then we can't guarantee
    // that this was just a movement.
    if (a.left().type() != b.left().type()
        || a.right().type() != b.right().type()
        || a.top().type() != b.top().type()
        || a.bottom().type() != b.bottom().type())
        return false;

    // Only one unit can be non-auto in the horizontal direction and
    // in the vertical direction.  Otherwise the adjustment of values
    // is changing the size of the box.
    if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
        return false;
    if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
        return false;
    // If our width is auto and left or right is specified then this 
    // is not just a movement - we need to resize to our container.
    if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
        return false;

    // One of the units is fixed or percent in both directions and stayed
    // that way in the new style.  Therefore all we are doing is moving.
    return true;
}

inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const
{
    if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()
        && !arePointingToEqualData(m_rareNonInheritedData->boxShadow, other.m_rareNonInheritedData->boxShadow))
        return true;

    if (m_rareInheritedData.ptr() != other.m_rareInheritedData.ptr()
        && !arePointingToEqualData(m_rareInheritedData->textShadow, other.m_rareInheritedData->textShadow))
        return true;

    if (m_inheritedFlags.textDecorations != other.m_inheritedFlags.textDecorations
        || m_visualData->textDecoration != other.m_visualData->textDecoration
        || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle) {
        // Underlines are always drawn outside of their textbox bounds when text-underline-position: under;
        // is specified. We can take an early out here.
        if (textUnderlinePosition() == TextUnderlinePositionUnder
            || other.textUnderlinePosition() == TextUnderlinePositionUnder)
            return true;
        return visualOverflowForDecorations(*this, nullptr) != visualOverflowForDecorations(other, nullptr);
    }

    if (hasOutlineInVisualOverflow() != other.hasOutlineInVisualOverflow())
        return true;
    return false;
}

bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
{
    if (m_boxData->width() != other.m_boxData->width()
        || m_boxData->minWidth() != other.m_boxData->minWidth()
        || m_boxData->maxWidth() != other.m_boxData->maxWidth()
        || m_boxData->height() != other.m_boxData->height()
        || m_boxData->minHeight() != other.m_boxData->minHeight()
        || m_boxData->maxHeight() != other.m_boxData->maxHeight())
        return true;

    if (m_boxData->verticalAlign() != other.m_boxData->verticalAlign() || m_nonInheritedFlags.verticalAlign != other.m_nonInheritedFlags.verticalAlign)
        return true;

    if (m_boxData->boxSizing() != other.m_boxData->boxSizing())
        return true;

    if (m_surroundData->margin != other.m_surroundData->margin)
        return true;

    if (m_surroundData->padding != other.m_surroundData->padding)
        return true;

    // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
    if (changeAffectsVisualOverflow(other))
        return true;

    if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()) {
        if (m_rareNonInheritedData->appearance != other.m_rareNonInheritedData->appearance
            || m_rareNonInheritedData->marginBeforeCollapse != other.m_rareNonInheritedData->marginBeforeCollapse
            || m_rareNonInheritedData->marginAfterCollapse != other.m_rareNonInheritedData->marginAfterCollapse
            || m_rareNonInheritedData->lineClamp != other.m_rareNonInheritedData->lineClamp
            || m_rareNonInheritedData->initialLetter != other.m_rareNonInheritedData->initialLetter
            || m_rareNonInheritedData->textOverflow != other.m_rareNonInheritedData->textOverflow)
            return true;

        if (m_rareNonInheritedData->shapeMargin != other.m_rareNonInheritedData->shapeMargin)
            return true;

        if (m_rareNonInheritedData->deprecatedFlexibleBox != other.m_rareNonInheritedData->deprecatedFlexibleBox)
            return true;

        if (m_rareNonInheritedData->flexibleBox != other.m_rareNonInheritedData->flexibleBox)
            return true;

        if (m_rareNonInheritedData->order != other.m_rareNonInheritedData->order
            || m_rareNonInheritedData->alignContent != other.m_rareNonInheritedData->alignContent
            || m_rareNonInheritedData->alignItems != other.m_rareNonInheritedData->alignItems
            || m_rareNonInheritedData->alignSelf != other.m_rareNonInheritedData->alignSelf
            || m_rareNonInheritedData->justifyContent != other.m_rareNonInheritedData->justifyContent
            || m_rareNonInheritedData->justifyItems != other.m_rareNonInheritedData->justifyItems
            || m_rareNonInheritedData->justifySelf != other.m_rareNonInheritedData->justifySelf)
            return true;

        if (!arePointingToEqualData(m_rareNonInheritedData->boxReflect, other.m_rareNonInheritedData->boxReflect))
            return true;

        if (m_rareNonInheritedData->multiCol != other.m_rareNonInheritedData->multiCol)
            return true;

        if (m_rareNonInheritedData->transform != other.m_rareNonInheritedData->transform) {
            if (m_rareNonInheritedData->transform->hasTransform() != other.m_rareNonInheritedData->transform->hasTransform())
                return true;
            if (*m_rareNonInheritedData->transform != *other.m_rareNonInheritedData->transform) {
                changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
                // Don't return; keep looking for another change
            }
        }

        if (m_rareNonInheritedData->grid != other.m_rareNonInheritedData->grid
            || m_rareNonInheritedData->gridItem != other.m_rareNonInheritedData->gridItem)
            return true;

#if ENABLE(DASHBOARD_SUPPORT)
        // If regions change, trigger a relayout to re-calc regions.
        if (m_rareNonInheritedData->dashboardRegions != other.m_rareNonInheritedData->dashboardRegions)
            return true;
#endif

        if (!arePointingToEqualData(m_rareNonInheritedData->willChange, other.m_rareNonInheritedData->willChange)) {
            changedContextSensitiveProperties |= ContextSensitivePropertyWillChange;
            // Don't return; keep looking for another change
        }
    }

    if (m_rareInheritedData.ptr() != other.m_rareInheritedData.ptr()) {
        if (m_rareInheritedData->indent != other.m_rareInheritedData->indent
#if ENABLE(CSS3_TEXT)
            || m_rareInheritedData->textAlignLast != other.m_rareInheritedData->textAlignLast
            || m_rareInheritedData->textJustify != other.m_rareInheritedData->textJustify
            || m_rareInheritedData->textIndentLine != other.m_rareInheritedData->textIndentLine
#endif
            || m_rareInheritedData->effectiveZoom != other.m_rareInheritedData->effectiveZoom
            || m_rareInheritedData->textZoom != other.m_rareInheritedData->textZoom
#if ENABLE(TEXT_AUTOSIZING)
            || m_rareInheritedData->textSizeAdjust != other.m_rareInheritedData->textSizeAdjust
#endif
            || m_rareInheritedData->wordBreak != other.m_rareInheritedData->wordBreak
            || m_rareInheritedData->overflowWrap != other.m_rareInheritedData->overflowWrap
            || m_rareInheritedData->nbspMode != other.m_rareInheritedData->nbspMode
            || m_rareInheritedData->lineBreak != other.m_rareInheritedData->lineBreak
            || m_rareInheritedData->textSecurity != other.m_rareInheritedData->textSecurity
            || m_rareInheritedData->hyphens != other.m_rareInheritedData->hyphens
            || m_rareInheritedData->hyphenationLimitBefore != other.m_rareInheritedData->hyphenationLimitBefore
            || m_rareInheritedData->hyphenationLimitAfter != other.m_rareInheritedData->hyphenationLimitAfter
            || m_rareInheritedData->hyphenationString != other.m_rareInheritedData->hyphenationString
            || m_rareInheritedData->rubyPosition != other.m_rareInheritedData->rubyPosition
            || m_rareInheritedData->textEmphasisMark != other.m_rareInheritedData->textEmphasisMark
            || m_rareInheritedData->textEmphasisPosition != other.m_rareInheritedData->textEmphasisPosition
            || m_rareInheritedData->textEmphasisCustomMark != other.m_rareInheritedData->textEmphasisCustomMark
            || m_rareInheritedData->textOrientation != other.m_rareInheritedData->textOrientation
            || m_rareInheritedData->tabSize != other.m_rareInheritedData->tabSize
            || m_rareInheritedData->lineBoxContain != other.m_rareInheritedData->lineBoxContain
            || m_rareInheritedData->lineGrid != other.m_rareInheritedData->lineGrid
#if ENABLE(CSS_IMAGE_ORIENTATION)
            || m_rareInheritedData->imageOrientation != other.m_rareInheritedData->imageOrientation
#endif
#if ENABLE(CSS_IMAGE_RESOLUTION)
            || m_rareInheritedData->imageResolutionSource != other.m_rareInheritedData->imageResolutionSource
            || m_rareInheritedData->imageResolutionSnap != other.m_rareInheritedData->imageResolutionSnap
            || m_rareInheritedData->imageResolution != other.m_rareInheritedData->imageResolution
#endif
            || m_rareInheritedData->lineSnap != other.m_rareInheritedData->lineSnap
            || m_rareInheritedData->lineAlign != other.m_rareInheritedData->lineAlign
            || m_rareInheritedData->hangingPunctuation != other.m_rareInheritedData->hangingPunctuation
#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
            || m_rareInheritedData->useTouchOverflowScrolling != other.m_rareInheritedData->useTouchOverflowScrolling
#endif
            || m_rareInheritedData->listStyleImage != other.m_rareInheritedData->listStyleImage) // FIXME: needs arePointingToEqualData()?
            return true;

        if (textStrokeWidth() != other.textStrokeWidth())
            return true;
        
        // These properties affect the cached stroke bounding box rects.
        if (m_rareInheritedData->capStyle != other.m_rareInheritedData->capStyle
            || m_rareInheritedData->joinStyle != other.m_rareInheritedData->joinStyle
            || m_rareInheritedData->strokeWidth != other.m_rareInheritedData->strokeWidth
            || m_rareInheritedData->miterLimit != other.m_rareInheritedData->miterLimit)
            return true;
    }

    if (m_inheritedData->lineHeight != other.m_inheritedData->lineHeight
#if ENABLE(TEXT_AUTOSIZING)
        || m_inheritedData->specifiedLineHeight != other.m_inheritedData->specifiedLineHeight
#endif
        || m_inheritedData->fontCascade != other.m_inheritedData->fontCascade
        || m_inheritedData->horizontalBorderSpacing != other.m_inheritedData->horizontalBorderSpacing
        || m_inheritedData->verticalBorderSpacing != other.m_inheritedData->verticalBorderSpacing
        || m_inheritedFlags.boxDirection != other.m_inheritedFlags.boxDirection
        || m_inheritedFlags.rtlOrdering != other.m_inheritedFlags.rtlOrdering
        || m_nonInheritedFlags.position != other.m_nonInheritedFlags.position
        || m_nonInheritedFlags.floating != other.m_nonInheritedFlags.floating
        || m_nonInheritedFlags.originalDisplay != other.m_nonInheritedFlags.originalDisplay)
        return true;


    if (m_nonInheritedFlags.effectiveDisplay >= TABLE) {
        if (m_inheritedFlags.borderCollapse != other.m_inheritedFlags.borderCollapse
            || m_inheritedFlags.emptyCells != other.m_inheritedFlags.emptyCells
            || m_inheritedFlags.captionSide != other.m_inheritedFlags.captionSide
            || m_nonInheritedFlags.tableLayout != other.m_nonInheritedFlags.tableLayout)
            return true;

        // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
        // does not, so these style differences can be width differences.
        if (m_inheritedFlags.borderCollapse
            && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE)
                || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDDEN)
                || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle() == BNONE)
                || (borderBottomStyle() == BNONE && other.borderBottomStyle() == BHIDDEN)
                || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == BNONE)
                || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHIDDEN)
                || (borderRightStyle() == BHIDDEN && other.borderRightStyle() == BNONE)
                || (borderRightStyle() == BNONE && other.borderRightStyle() == BHIDDEN)))
            return true;
    }

    if (m_nonInheritedFlags.effectiveDisplay == LIST_ITEM) {
        if (m_inheritedFlags.listStyleType != other.m_inheritedFlags.listStyleType
            || m_inheritedFlags.listStylePosition != other.m_inheritedFlags.listStylePosition)
            return true;
    }

    if (m_inheritedFlags.textAlign != other.m_inheritedFlags.textAlign
        || m_inheritedFlags.textTransform != other.m_inheritedFlags.textTransform
        || m_inheritedFlags.direction != other.m_inheritedFlags.direction
        || m_inheritedFlags.whiteSpace != other.m_inheritedFlags.whiteSpace
        || m_nonInheritedFlags.clear != other.m_nonInheritedFlags.clear
        || m_nonInheritedFlags.unicodeBidi != other.m_nonInheritedFlags.unicodeBidi)
        return true;

    // Check block flow direction.
    if (m_inheritedFlags.writingMode != other.m_inheritedFlags.writingMode)
        return true;

    // Check text combine mode.
    if (m_rareNonInheritedData->textCombine != other.m_rareNonInheritedData->textCombine)
        return true;

    // Check breaks.
    if (m_rareNonInheritedData->breakBefore != other.m_rareNonInheritedData->breakBefore
        || m_rareNonInheritedData->breakAfter != other.m_rareNonInheritedData->breakAfter
        || m_rareNonInheritedData->breakInside != other.m_rareNonInheritedData->breakInside)
        return true;

    // Overflow returns a layout hint.
    if (m_nonInheritedFlags.overflowX != other.m_nonInheritedFlags.overflowX
        || m_nonInheritedFlags.overflowY != other.m_nonInheritedFlags.overflowY)
        return true;

    // If our border widths change, then we need to layout.  Other changes to borders
    // only necessitate a repaint.
    if (borderLeftWidth() != other.borderLeftWidth()
        || borderTopWidth() != other.borderTopWidth()
        || borderBottomWidth() != other.borderBottomWidth()
        || borderRightWidth() != other.borderRightWidth())
        return true;

    // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
    if (!arePointingToEqualData(m_rareNonInheritedData->counterDirectives, other.m_rareNonInheritedData->counterDirectives))
        return true;

    if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
        return true;

    if (m_rareNonInheritedData->hasOpacity() != other.m_rareNonInheritedData->hasOpacity()) {
        // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
        // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
        // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
        // In addition we need to solve the floating object issue when layers come and go. Right now
        // a full layout is necessary to keep floating object lists sane.
        return true;
    }

    if (m_rareNonInheritedData->hasFilters() != other.m_rareNonInheritedData->hasFilters())
        return true;

#if ENABLE(FILTERS_LEVEL_2)
    if (m_rareNonInheritedData->hasBackdropFilters() != other.m_rareNonInheritedData->hasBackdropFilters())
        return true;
#endif

    if (!arePointingToEqualData(m_rareInheritedData->quotes, other.m_rareInheritedData->quotes))
        return true;

    if (position() != StaticPosition) {
        if (m_surroundData->offset != other.m_surroundData->offset) {
            // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
            // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
            // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
            if (position() != AbsolutePosition)
                return true;

            // Optimize for the case where a positioned layer is moving but not changing size.
            if (!positionChangeIsMovementOnly(m_surroundData->offset, other.m_surroundData->offset, m_boxData->width()))
                return true;
        }
    }

    bool hasFirstLineStyle = hasPseudoStyle(FIRST_LINE);
    if (hasFirstLineStyle != other.hasPseudoStyle(FIRST_LINE))
        return true;
    if (hasFirstLineStyle) {
        auto* firstLineStyle = getCachedPseudoStyle(FIRST_LINE);
        if (!firstLineStyle)
            return true;
        auto* otherFirstLineStyle = other.getCachedPseudoStyle(FIRST_LINE);
        if (!otherFirstLineStyle)
            return true;
        // FIXME: Not all first line style changes actually need layout.
        if (*firstLineStyle != *otherFirstLineStyle)
            return true;
    }

    return false;
}

bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle& other, unsigned&) const
{
    if (position() == StaticPosition)
        return false;

    if (m_surroundData->offset != other.m_surroundData->offset) {
        // Optimize for the case where a positioned layer is moving but not changing size.
        if (position() == AbsolutePosition && positionChangeIsMovementOnly(m_surroundData->offset, other.m_surroundData->offset, m_boxData->width()))
            return true;
    }
    
    return false;
}

bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
{
    // StyleResolver has ensured that zIndex is non-auto only if it's applicable.
    if (m_boxData->zIndex() != other.m_boxData->zIndex() || m_boxData->hasAutoZIndex() != other.m_boxData->hasAutoZIndex())
        return true;

    if (position() != StaticPosition) {
        if (m_visualData->clip != other.m_visualData->clip || m_visualData->hasClip != other.m_visualData->hasClip) {
            changedContextSensitiveProperties |= ContextSensitivePropertyClipRect;
            return true;
        }
    }

#if ENABLE(CSS_COMPOSITING)
    if (m_rareNonInheritedData->effectiveBlendMode != other.m_rareNonInheritedData->effectiveBlendMode)
        return true;
#endif

    if (m_rareNonInheritedData->opacity != other.m_rareNonInheritedData->opacity) {
        changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
        // Don't return; keep looking for another change.
    }

    if (m_rareNonInheritedData->filter != other.m_rareNonInheritedData->filter) {
        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
        // Don't return; keep looking for another change.
    }

#if ENABLE(FILTERS_LEVEL_2)
    if (m_rareNonInheritedData->backdropFilter != other.m_rareNonInheritedData->backdropFilter) {
        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
        // Don't return; keep looking for another change.
    }
#endif

    if (m_rareNonInheritedData->mask != other.m_rareNonInheritedData->mask
        || m_rareNonInheritedData->maskBoxImage != other.m_rareNonInheritedData->maskBoxImage)
        return true;

    return false;
}

static bool requiresPainting(const RenderStyle& style)
{
    if (style.visibility() == HIDDEN)
        return false;
    if (!style.opacity())
        return false;
    return true;
}

bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
{
    if (!requiresPainting(*this) && !requiresPainting(other))
        return false;

    if (m_inheritedFlags.visibility != other.m_inheritedFlags.visibility
        || m_inheritedFlags.printColorAdjust != other.m_inheritedFlags.printColorAdjust
        || m_inheritedFlags.insideLink != other.m_inheritedFlags.insideLink
        || m_inheritedFlags.insideDefaultButton != other.m_inheritedFlags.insideDefaultButton
        || m_surroundData->border != other.m_surroundData->border
        || !m_backgroundData->isEquivalentForPainting(*other.m_backgroundData)
        || m_rareInheritedData->userModify != other.m_rareInheritedData->userModify
        || m_rareInheritedData->userSelect != other.m_rareInheritedData->userSelect
        || m_rareInheritedData->colorFilter != other.m_rareInheritedData->colorFilter
        || m_rareNonInheritedData->userDrag != other.m_rareNonInheritedData->userDrag
        || m_rareNonInheritedData->borderFit != other.m_rareNonInheritedData->borderFit
        || m_rareNonInheritedData->objectFit != other.m_rareNonInheritedData->objectFit
        || m_rareNonInheritedData->objectPosition != other.m_rareNonInheritedData->objectPosition
        || m_rareInheritedData->imageRendering != other.m_rareInheritedData->imageRendering)
        return true;

    if (m_rareNonInheritedData->isNotFinal != other.m_rareNonInheritedData->isNotFinal)
        return true;

    if (m_rareNonInheritedData->shapeOutside != other.m_rareNonInheritedData->shapeOutside)
        return true;

    // FIXME: this should probably be moved to changeRequiresLayerRepaint().
    if (m_rareNonInheritedData->clipPath != other.m_rareNonInheritedData->clipPath) {
        changedContextSensitiveProperties |= ContextSensitivePropertyClipPath;
        // Don't return; keep looking for another change.
    }

    return false;
}

bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle& other, unsigned&) const
{
    if (m_inheritedData->color != other.m_inheritedData->color
        || m_inheritedFlags.textDecorations != other.m_inheritedFlags.textDecorations
        || m_visualData->textDecoration != other.m_visualData->textDecoration
        || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle
        || m_rareNonInheritedData->textDecorationColor != other.m_rareNonInheritedData->textDecorationColor
        || m_rareInheritedData->textDecorationSkip != other.m_rareInheritedData->textDecorationSkip
        || m_rareInheritedData->textFillColor != other.m_rareInheritedData->textFillColor
        || m_rareInheritedData->textStrokeColor != other.m_rareInheritedData->textStrokeColor
        || m_rareInheritedData->textEmphasisColor != other.m_rareInheritedData->textEmphasisColor
        || m_rareInheritedData->textEmphasisFill != other.m_rareInheritedData->textEmphasisFill
        || m_rareInheritedData->strokeColor != other.m_rareInheritedData->strokeColor
        || m_rareInheritedData->caretColor != other.m_rareInheritedData->caretColor)
        return true;

    return false;
}

bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle& other, unsigned&) const
{
    if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()) {
        if (m_rareNonInheritedData->transformStyle3D != other.m_rareNonInheritedData->transformStyle3D
            || m_rareNonInheritedData->backfaceVisibility != other.m_rareNonInheritedData->backfaceVisibility
            || m_rareNonInheritedData->perspective != other.m_rareNonInheritedData->perspective
            || m_rareNonInheritedData->perspectiveOriginX != other.m_rareNonInheritedData->perspectiveOriginX
            || m_rareNonInheritedData->perspectiveOriginY != other.m_rareNonInheritedData->perspectiveOriginY)
            return true;
    }

    return false;
}

StyleDifference RenderStyle::diff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
{
    changedContextSensitiveProperties = ContextSensitivePropertyNone;

    StyleDifference svgChange = StyleDifferenceEqual;
    if (m_svgStyle != other.m_svgStyle) {
        svgChange = m_svgStyle->diff(other.m_svgStyle.get());
        if (svgChange == StyleDifferenceLayout)
            return svgChange;
    }

    if (changeRequiresLayout(other, changedContextSensitiveProperties))
        return StyleDifferenceLayout;

    // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
    // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
    // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
    // that are relevant for SVG and might return StyleDifferenceLayout.
    if (svgChange != StyleDifferenceEqual)
        return svgChange;

    if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
        return StyleDifferenceLayoutPositionedMovementOnly;

    if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
        return StyleDifferenceRepaintLayer;

    if (changeRequiresRepaint(other, changedContextSensitiveProperties))
        return StyleDifferenceRepaint;

    if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
        return StyleDifferenceRecompositeLayer;

    if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
        return StyleDifferenceRepaintIfTextOrBorderOrOutline;

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

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

bool RenderStyle::diffRequiresLayerRepaint(const RenderStyle& style, bool isComposited) const
{
    unsigned changedContextSensitiveProperties = 0;

    if (changeRequiresRepaint(style, changedContextSensitiveProperties))
        return true;

    if (isComposited && changeRequiresLayerRepaint(style, changedContextSensitiveProperties))
        return changedContextSensitiveProperties & ContextSensitivePropertyClipRect;

    return false;
}

void RenderStyle::setClip(Length&& top, Length&& right, Length&& bottom, Length&& left)
{
    auto& data = m_visualData.access();
    data.clip.top() = WTFMove(top);
    data.clip.right() = WTFMove(right);
    data.clip.bottom() = WTFMove(bottom);
    data.clip.left() = WTFMove(left);
}

void RenderStyle::addCursor(RefPtr<StyleImage>&& image, const IntPoint& hotSpot)
{
    auto& cursorData = m_rareInheritedData.access().cursorData;
    if (!cursorData)
        cursorData = CursorList::create();
    cursorData->append(CursorData(WTFMove(image), hotSpot));
}

void RenderStyle::setCursorList(RefPtr<CursorList>&& list)
{
    m_rareInheritedData.access().cursorData = WTFMove(list);
}

void RenderStyle::setQuotes(RefPtr<QuotesData>&& q)
{
    if (m_rareInheritedData->quotes == q || (m_rareInheritedData->quotes && q && *m_rareInheritedData->quotes == *q))
        return;

    m_rareInheritedData.access().quotes = WTFMove(q);
}

void RenderStyle::setWillChange(RefPtr<WillChangeData>&& willChangeData)
{
    if (arePointingToEqualData(m_rareNonInheritedData->willChange.get(), willChangeData.get()))
        return;

    m_rareNonInheritedData.access().willChange = WTFMove(willChangeData);
}

void RenderStyle::clearCursorList()
{
    if (m_rareInheritedData->cursorData)
        m_rareInheritedData.access().cursorData = nullptr;
}

void RenderStyle::clearContent()
{
    if (m_rareNonInheritedData->content)
        m_rareNonInheritedData.access().content = nullptr;
}

static inline ContentData& lastContent(ContentData& firstContent)
{
    auto* lastContent = &firstContent;
    for (auto* content = &firstContent; content; content = content->next())
        lastContent = content;
    return *lastContent;
}

void RenderStyle::setContent(std::unique_ptr<ContentData> contentData, bool add)
{
    auto& data = m_rareNonInheritedData.access();
    if (add && data.content)
        lastContent(*data.content).setNext(WTFMove(contentData));
    else {
        data.content = WTFMove(contentData);
        auto& altText = data.altText;
        if (!altText.isNull())
            data.content->setAltText(altText);
    }
}

void RenderStyle::setContent(RefPtr<StyleImage>&& image, bool add)
{
    if (!image)
        return;
    setContent(std::make_unique<ImageContentData>(image.releaseNonNull()), add);
}

void RenderStyle::setContent(const String& string, bool add)
{
    auto& data = m_rareNonInheritedData.access();
    if (add && data.content) {
        auto& last = lastContent(*data.content);
        if (!is<TextContentData>(last))
            last.setNext(std::make_unique<TextContentData>(string));
        else {
            auto& textContent = downcast<TextContentData>(last);
            textContent.setText(textContent.text() + string);
        }
    } else {
        data.content = std::make_unique<TextContentData>(string);
        auto& altText = data.altText;
        if (!altText.isNull())
            data.content->setAltText(altText);
    }
}

void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
{
    if (!counter)
        return;
    setContent(std::make_unique<CounterContentData>(WTFMove(counter)), add);
}

void RenderStyle::setContent(QuoteType quote, bool add)
{
    setContent(std::make_unique<QuoteContentData>(quote), add);
}

void RenderStyle::setContentAltText(const String& string)
{
    auto& data = m_rareNonInheritedData.access();
    data.altText = string;
    if (data.content)
        data.content->setAltText(string);
}

const String& RenderStyle::contentAltText() const
{
    return m_rareNonInheritedData->altText;
}

void RenderStyle::setHasAttrContent()
{
    setUnique();
    SET_VAR(m_rareNonInheritedData, hasAttrContent, true);
}

static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
{
    // The transform-origin property brackets the transform with translate operations.
    // When the only transform is a translation, the transform-origin is irrelevant.

    if (applyOrigin != RenderStyle::IncludeTransformOrigin)
        return false;

    for (auto& operation : transformOperations) {
        // FIXME: Use affectedByTransformOrigin().
        auto type = operation->type();
        if (type != TransformOperation::TRANSLATE
            && type != TransformOperation::TRANSLATE_3D
            && type != TransformOperation::TRANSLATE_X
            && type != TransformOperation::TRANSLATE_Y
            && type != TransformOperation::TRANSLATE_Z)
            return true;
    }

    return false;
}

void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
{
    auto& operations = m_rareNonInheritedData->transform->operations.operations();
    bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
    
    FloatPoint3D originTranslate;
    if (applyTransformOrigin) {
        originTranslate.setX(boundingBox.x() + floatValueForLength(transformOriginX(), boundingBox.width()));
        originTranslate.setY(boundingBox.y() + floatValueForLength(transformOriginY(), boundingBox.height()));
        originTranslate.setZ(transformOriginZ());
        transform.translate3d(originTranslate.x(), originTranslate.y(), originTranslate.z());
    }

    for (auto& operation : operations)
        operation->apply(transform, boundingBox.size());

    if (applyTransformOrigin)
        transform.translate3d(-originTranslate.x(), -originTranslate.y(), -originTranslate.z());
}

void RenderStyle::setPageScaleTransform(float scale)
{
    if (scale == 1)
        return;
    TransformOperations transform;
    transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
    setTransform(transform);
    setTransformOriginX(Length(0, Fixed));
    setTransformOriginY(Length(0, Fixed));
}

void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add)
{
    ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));

    auto& rareData = m_rareInheritedData.access();
    if (!add) {
        rareData.textShadow = WTFMove(shadowData);
        return;
    }

    shadowData->setNext(WTFMove(rareData.textShadow));
    rareData.textShadow = WTFMove(shadowData);
}

void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add)
{
    auto& rareData = m_rareNonInheritedData.access();
    if (!add) {
        rareData.boxShadow = WTFMove(shadowData);
        return;
    }

    shadowData->setNext(WTFMove(rareData.boxShadow));
    rareData.boxShadow = WTFMove(shadowData);
}

static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size)
{
    return {
        sizeForLengthSize(border.topLeft(), size),
        sizeForLengthSize(border.topRight(), size),
        sizeForLengthSize(border.bottomLeft(), size),
        sizeForLengthSize(border.bottomRight(), size)
    };
}

StyleImage* RenderStyle::listStyleImage() const
{
    return m_rareInheritedData->listStyleImage.get();
}

void RenderStyle::setListStyleImage(RefPtr<StyleImage>&& v)
{
    if (m_rareInheritedData->listStyleImage != v)
        m_rareInheritedData.access().listStyleImage = WTFMove(v);
}

const Color& RenderStyle::color() const
{
    return m_inheritedData->color;
}

const Color& RenderStyle::visitedLinkColor() const
{
    return m_inheritedData->visitedLinkColor;
}

void RenderStyle::setColor(const Color& v)
{
    SET_VAR(m_inheritedData, color, v);
}

void RenderStyle::setVisitedLinkColor(const Color& v)
{
    SET_VAR(m_inheritedData, visitedLinkColor, v);
}

float RenderStyle::horizontalBorderSpacing() const
{
    return m_inheritedData->horizontalBorderSpacing;
}

float RenderStyle::verticalBorderSpacing() const
{
    return m_inheritedData->verticalBorderSpacing;
}

void RenderStyle::setHorizontalBorderSpacing(float v)
{
    SET_VAR(m_inheritedData, horizontalBorderSpacing, v);
}

void RenderStyle::setVerticalBorderSpacing(float v)
{
    SET_VAR(m_inheritedData, verticalBorderSpacing, v);
}

RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
    RoundedRect roundedRect(borderRect);
    if (hasBorderRadius()) {
        RoundedRect::Radii radii = calcRadiiFor(m_surroundData->border, borderRect.size());
        radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
        roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
    }
    return roundedRect;
}

RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
    bool horizontal = isHorizontalWritingMode();
    auto leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
    auto rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
    auto topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
    auto bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
    return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
}

RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth,
    LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
    RoundedRect roundedRect { { borderRect.x() + leftWidth, borderRect.y() + topWidth,
        borderRect.width() - leftWidth - rightWidth, borderRect.height() - topWidth - bottomWidth } };
    if (hasBorderRadius()) {
        auto radii = getRoundedBorderFor(borderRect).radii();
        radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
        roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
    }
    return roundedRect;
}

static bool allLayersAreFixed(const FillLayer& layers)
{
    for (auto* layer = &layers; layer; layer = layer->next()) {
        if (!(layer->image() && layer->attachment() == FixedBackgroundAttachment))
            return false;
    }
    return true;
}

bool RenderStyle::hasEntirelyFixedBackground() const
{
    return allLayersAreFixed(backgroundLayers());
}

const CounterDirectiveMap* RenderStyle::counterDirectives() const
{
    return m_rareNonInheritedData->counterDirectives.get();
}

CounterDirectiveMap& RenderStyle::accessCounterDirectives()
{
    auto& map = m_rareNonInheritedData.access().counterDirectives;
    if (!map)
        map = std::make_unique<CounterDirectiveMap>();
    return *map;
}

const AtomicString& RenderStyle::hyphenString() const
{
    ASSERT(hyphens() != HyphensNone);

    auto& hyphenationString = m_rareInheritedData->hyphenationString;
    if (!hyphenationString.isNull())
        return hyphenationString;

    // FIXME: This should depend on locale.
    static NeverDestroyed<AtomicString> hyphenMinusString(&hyphenMinus, 1);
    static NeverDestroyed<AtomicString> hyphenString(&hyphen, 1);
    return fontCascade().primaryFont().glyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
}

const AtomicString& RenderStyle::textEmphasisMarkString() const
{
    switch (textEmphasisMark()) {
    case TextEmphasisMarkNone:
        return nullAtom();
    case TextEmphasisMarkCustom:
        return textEmphasisCustomMark();
    case TextEmphasisMarkDot: {
        static NeverDestroyed<AtomicString> filledDotString(&bullet, 1);
        static NeverDestroyed<AtomicString> openDotString(&whiteBullet, 1);
        return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
    }
    case TextEmphasisMarkCircle: {
        static NeverDestroyed<AtomicString> filledCircleString(&blackCircle, 1);
        static NeverDestroyed<AtomicString> openCircleString(&whiteCircle, 1);
        return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
    }
    case TextEmphasisMarkDoubleCircle: {
        static NeverDestroyed<AtomicString> filledDoubleCircleString(&fisheye, 1);
        static NeverDestroyed<AtomicString> openDoubleCircleString(&bullseye, 1);
        return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
    }
    case TextEmphasisMarkTriangle: {
        static NeverDestroyed<AtomicString> filledTriangleString(&blackUpPointingTriangle, 1);
        static NeverDestroyed<AtomicString> openTriangleString(&whiteUpPointingTriangle, 1);
        return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
    }
    case TextEmphasisMarkSesame: {
        static NeverDestroyed<AtomicString> filledSesameString(&sesameDot, 1);
        static NeverDestroyed<AtomicString> openSesameString(&whiteSesameDot, 1);
        return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
    }
    case TextEmphasisMarkAuto:
        ASSERT_NOT_REACHED();
        return nullAtom();
    }

    ASSERT_NOT_REACHED();
    return nullAtom();
}

#if ENABLE(DASHBOARD_SUPPORT)

const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
{
    static NeverDestroyed<Vector<StyleDashboardRegion>> emptyList;
    return emptyList;
}

const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
{
    static NeverDestroyed<Vector<StyleDashboardRegion>> noneList;
    static bool noneListInitialized = false;
    if (!noneListInitialized) {
        noneList.get().append(StyleDashboardRegion { emptyString(), { }, StyleDashboardRegion::None });
        noneListInitialized = true;
    }
    return noneList;
}

#endif

void RenderStyle::adjustAnimations()
{
    auto* animationList = m_rareNonInheritedData->animations.get();
    if (!animationList)
        return;

    // Get rid of empty animations and anything beyond them
    for (size_t i = 0, size = animationList->size(); i < size; ++i) {
        if (animationList->animation(i).isEmpty()) {
            animationList->resize(i);
            break;
        }
    }

    if (animationList->isEmpty()) {
        clearAnimations();
        return;
    }

    // Repeat patterns into layers that don't have some properties set.
    animationList->fillUnsetProperties();
}

void RenderStyle::adjustTransitions()
{
    auto* transitionList = m_rareNonInheritedData->transitions.get();
    if (!transitionList)
        return;

    // Get rid of empty transitions and anything beyond them
    for (size_t i = 0, size = transitionList->size(); i < size; ++i) {
        if (transitionList->animation(i).isEmpty()) {
            transitionList->resize(i);
            break;
        }
    }

    if (transitionList->isEmpty()) {
        clearTransitions();
        return;
    }

    // Repeat patterns into layers that don't have some properties set.
    transitionList->fillUnsetProperties();

    // Make sure there are no duplicate properties.
    // This is an O(n^2) algorithm but the lists tend to be short, so it is probably OK.
    for (size_t i = 0; i < transitionList->size(); ++i) {
        for (size_t j = i + 1; j < transitionList->size(); ++j) {
            if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
                // toss i
                transitionList->remove(i);
                j = i;
            }
        }
    }
}

AnimationList& RenderStyle::ensureAnimations()
{
    if (!m_rareNonInheritedData.access().animations)
        m_rareNonInheritedData.access().animations = std::make_unique<AnimationList>();
    return *m_rareNonInheritedData->animations;
}

AnimationList& RenderStyle::ensureTransitions()
{
    if (!m_rareNonInheritedData.access().transitions)
        m_rareNonInheritedData.access().transitions = std::make_unique<AnimationList>();
    return *m_rareNonInheritedData->transitions;
}

const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
{
    auto* transitions = this->transitions();
    if (!transitions)
        return nullptr;
    for (size_t i = 0, size = transitions->size(); i < size; ++i) {
        auto& animation = transitions->animation(i);
        if (animation.animationMode() == Animation::AnimateAll || animation.property() == property)
            return &animation;
    }
    return nullptr;
}

const FontCascade& RenderStyle::fontCascade() const
{
    return m_inheritedData->fontCascade;
}

const FontMetrics& RenderStyle::fontMetrics() const
{
    return m_inheritedData->fontCascade.fontMetrics();
}

const FontCascadeDescription& RenderStyle::fontDescription() const
{
    return m_inheritedData->fontCascade.fontDescription();
}

float RenderStyle::specifiedFontSize() const
{
    return fontDescription().specifiedSize();
}

float RenderStyle::computedFontSize() const
{
    return fontDescription().computedSize();
}

unsigned RenderStyle::computedFontPixelSize() const
{
    return fontDescription().computedPixelSize();
}

const Length& RenderStyle::wordSpacing() const
{
    return m_rareInheritedData->wordSpacing;
}

float RenderStyle::letterSpacing() const
{
    return m_inheritedData->fontCascade.letterSpacing();
}

bool RenderStyle::setFontDescription(const FontCascadeDescription& description)
{
    if (m_inheritedData->fontCascade.fontDescription() == description)
        return false;
    auto& cascade = m_inheritedData.access().fontCascade;
    cascade = { description, cascade.letterSpacing(), cascade.wordSpacing() };
    return true;
}

const Length& RenderStyle::specifiedLineHeight() const
{
#if ENABLE(TEXT_AUTOSIZING)
    return m_inheritedData->specifiedLineHeight;
#else
    return m_inheritedData->lineHeight;
#endif
}

#if ENABLE(TEXT_AUTOSIZING)

void RenderStyle::setSpecifiedLineHeight(Length&& height)
{
    SET_VAR(m_inheritedData, specifiedLineHeight, WTFMove(height));
}

#endif

const Length& RenderStyle::lineHeight() const
{
    return m_inheritedData->lineHeight;
}

void RenderStyle::setLineHeight(Length&& height)
{
    SET_VAR(m_inheritedData, lineHeight, WTFMove(height));
}

int RenderStyle::computedLineHeight() const
{
    const Length& lh = lineHeight();

    // Negative value means the line height is not set. Use the font's built-in spacing.
    if (lh.isNegative())
        return fontMetrics().lineSpacing();

    if (lh.isPercentOrCalculated())
        return minimumValueForLength(lh, computedFontPixelSize());

    return clampTo<int>(lh.value());
}

void RenderStyle::setWordSpacing(Length&& value)
{
    float fontWordSpacing;
    switch (value.type()) {
    case Auto:
        fontWordSpacing = 0;
        break;
    case Percent:
        fontWordSpacing = value.percent() * fontCascade().spaceWidth() / 100;
        break;
    case Fixed:
        fontWordSpacing = value.value();
        break;
    case Calculated:
        fontWordSpacing = value.nonNanCalculatedValue(maxValueForCssLength);
        break;
    default:
        ASSERT_NOT_REACHED();
        fontWordSpacing = 0;
        break;
    }
    m_inheritedData.access().fontCascade.setWordSpacing(fontWordSpacing);
    m_rareInheritedData.access().wordSpacing = WTFMove(value);
}

void RenderStyle::setLetterSpacing(float v) { m_inheritedData.access().fontCascade.setLetterSpacing(v); }

void RenderStyle::setFontSize(float size)
{
    // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
    // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).

    ASSERT(std::isfinite(size));
    if (!std::isfinite(size) || size < 0)
        size = 0;
    else
        size = std::min(maximumAllowedFontSize, size);

    FontSelector* currentFontSelector = fontCascade().fontSelector();
    auto description = fontDescription();
    description.setSpecifiedSize(size);
    description.setComputedSize(size);

    setFontDescription(description);
    fontCascade().update(currentFontSelector);
}

#if ENABLE(VARIATION_FONTS)
void RenderStyle::setFontVariationSettings(FontVariationSettings settings)
{
    FontSelector* currentFontSelector = fontCascade().fontSelector();
    auto description = fontDescription();
    description.setVariationSettings(WTFMove(settings));

    setFontDescription(description);
    fontCascade().update(currentFontSelector);
}
#endif

void RenderStyle::setFontWeight(FontSelectionValue value)
{
    FontSelector* currentFontSelector = fontCascade().fontSelector();
    auto description = fontDescription();
    description.setWeight(value);

    setFontDescription(description);
    fontCascade().update(currentFontSelector);
}

void RenderStyle::setFontStretch(FontSelectionValue value)
{
    FontSelector* currentFontSelector = fontCascade().fontSelector();
    auto description = fontDescription();
    description.setStretch(value);

    setFontDescription(description);
    fontCascade().update(currentFontSelector);
}

void RenderStyle::setFontItalic(FontSelectionValue value)
{
    FontSelector* currentFontSelector = fontCascade().fontSelector();
    auto description = fontDescription();
    description.setItalic(value);

    setFontDescription(description);
    fontCascade().update(currentFontSelector);
}

void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
{
    top = 0;
    right = 0;
    bottom = 0;
    left = 0;

    for ( ; shadow; shadow = shadow->next()) {
        if (shadow->style() == Inset)
            continue;

        int extentAndSpread = shadow->paintingExtent() + shadow->spread();
        top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
        right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
        bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
        left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
    }
}

LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
{
    LayoutUnit top = 0;
    LayoutUnit right = 0;
    LayoutUnit bottom = 0;
    LayoutUnit left = 0;

    for ( ; shadow; shadow = shadow->next()) {
        if (shadow->style() == Normal)
            continue;

        int extentAndSpread = shadow->paintingExtent() + shadow->spread();
        top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread);
        right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread);
        bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
        left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
    }

    return LayoutBoxExtent(WTFMove(top), WTFMove(right), WTFMove(bottom), WTFMove(left));
}

void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
{
    left = 0;
    right = 0;

    for ( ; shadow; shadow = shadow->next()) {
        if (shadow->style() == Inset)
            continue;

        int extentAndSpread = shadow->paintingExtent() + shadow->spread();
        left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
        right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
    }
}

void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
{
    top = 0;
    bottom = 0;

    for ( ; shadow; shadow = shadow->next()) {
        if (shadow->style() == Inset)
            continue;

        int extentAndSpread = shadow->paintingExtent() + shadow->spread();
        top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
        bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
    }
}

Color RenderStyle::colorIncludingFallback(CSSPropertyID colorProperty, bool visitedLink) const
{
    Color result;
    EBorderStyle borderStyle = BNONE;
    switch (colorProperty) {
    case CSSPropertyBackgroundColor:
        return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
    case CSSPropertyBorderLeftColor:
        result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
        borderStyle = borderLeftStyle();
        break;
    case CSSPropertyBorderRightColor:
        result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
        borderStyle = borderRightStyle();
        break;
    case CSSPropertyBorderTopColor:
        result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
        borderStyle = borderTopStyle();
        break;
    case CSSPropertyBorderBottomColor:
        result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
        borderStyle = borderBottomStyle();
        break;
    case CSSPropertyCaretColor:
        result = visitedLink ? visitedLinkCaretColor() : caretColor();
        break;
    case CSSPropertyColor:
        result = visitedLink ? visitedLinkColor() : color();
        break;
    case CSSPropertyOutlineColor:
        result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
        break;
    case CSSPropertyColumnRuleColor:
        result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
        break;
    case CSSPropertyWebkitTextDecorationColor:
        // Text decoration color fallback is handled in RenderObject::decorationColor.
        return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
    case CSSPropertyWebkitTextEmphasisColor:
        result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
        break;
    case CSSPropertyWebkitTextFillColor:
        result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
        break;
    case CSSPropertyWebkitTextStrokeColor:
        result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
        break;
    case CSSPropertyStrokeColor:
        result = visitedLink ? visitedLinkStrokeColor() : strokeColor();
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }

    if (!result.isValid()) {
        if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
            result = Color(238, 238, 238);
        else
            result = visitedLink ? visitedLinkColor() : color();
    }
    return result;
}

Color RenderStyle::visitedDependentColor(CSSPropertyID colorProperty) const
{
    Color unvisitedColor = colorIncludingFallback(colorProperty, false);
    if (insideLink() != InsideVisitedLink)
        return unvisitedColor;

    Color visitedColor = colorIncludingFallback(colorProperty, true);

    // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
    if (colorProperty == CSSPropertyWebkitTextDecorationColor)
        return visitedColor;

    // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
    // assume that if the background color is transparent that it wasn't set. Note that it's weird that
    // we're returning unvisited info for a visited link, but given our restriction that the alpha values
    // have to match, it makes more sense to return the unvisited background color if specified than it
    // does to return black. This behavior matches what Firefox 4 does as well.
    if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
        return unvisitedColor;

    // Take the alpha from the unvisited color, but get the RGB values from the visited color.
    return visitedColor.colorWithAlpha(unvisitedColor.alphaAsFloat());
}

Color RenderStyle::visitedDependentColorWithColorFilter(CSSPropertyID colorProperty) const
{
    if (!hasColorFilter())
        return visitedDependentColor(colorProperty);

    return colorByApplyingColorFilter(visitedDependentColor(colorProperty));
}

Color RenderStyle::colorByApplyingColorFilter(const Color& color) const
{
    Color transformedColor = color;
    colorFilter().transformColor(transformedColor);
    return transformedColor;
}

const BorderValue& RenderStyle::borderBefore() const
{
    switch (writingMode()) {
    case TopToBottomWritingMode:
        return borderTop();
    case BottomToTopWritingMode:
        return borderBottom();
    case LeftToRightWritingMode:
        return borderLeft();
    case RightToLeftWritingMode:
        return borderRight();
    }
    ASSERT_NOT_REACHED();
    return borderTop();
}

const BorderValue& RenderStyle::borderAfter() const
{
    switch (writingMode()) {
    case TopToBottomWritingMode:
        return borderBottom();
    case BottomToTopWritingMode:
        return borderTop();
    case LeftToRightWritingMode:
        return borderRight();
    case RightToLeftWritingMode:
        return borderLeft();
    }
    ASSERT_NOT_REACHED();
    return borderBottom();
}

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

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

float RenderStyle::borderBeforeWidth() const
{
    switch (writingMode()) {
    case TopToBottomWritingMode:
        return borderTopWidth();
    case BottomToTopWritingMode:
        return borderBottomWidth();
    case LeftToRightWritingMode:
        return borderLeftWidth();
    case RightToLeftWritingMode:
        return borderRightWidth();
    }
    ASSERT_NOT_REACHED();
    return borderTopWidth();
}

float RenderStyle::borderAfterWidth() const
{
    switch (writingMode()) {
    case TopToBottomWritingMode:
        return borderBottomWidth();
    case BottomToTopWritingMode:
        return borderTopWidth();
    case LeftToRightWritingMode:
        return borderRightWidth();
    case RightToLeftWritingMode:
        return borderLeftWidth();
    }
    ASSERT_NOT_REACHED();
    return borderBottomWidth();
}

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

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

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

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

TextEmphasisMark RenderStyle::textEmphasisMark() const
{
    auto mark = static_cast<TextEmphasisMark>(m_rareInheritedData->textEmphasisMark);
    if (mark != TextEmphasisMarkAuto)
        return mark;
    if (isHorizontalWritingMode())
        return TextEmphasisMarkDot;
    return TextEmphasisMarkSesame;
}

#if ENABLE(TOUCH_EVENTS)

Color RenderStyle::initialTapHighlightColor()
{
    return RenderTheme::tapHighlightColor();
}

#endif

LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
{
    return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
                           NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
                           NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
                           NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
}

std::pair<FontOrientation, NonCJKGlyphOrientation> RenderStyle::fontAndGlyphOrientation()
{
    // FIXME: TextOrientationSideways should map to sideways-left in vertical-lr, which is not supported yet.

    if (isHorizontalWritingMode())
        return { Horizontal, NonCJKGlyphOrientation::Mixed };

    switch (textOrientation()) {
    case TextOrientation::Mixed:
        return { Vertical, NonCJKGlyphOrientation::Mixed };
    case TextOrientation::Upright:
        return { Vertical, NonCJKGlyphOrientation::Upright };
    case TextOrientation::Sideways:
        return { Horizontal, NonCJKGlyphOrientation::Mixed };
    default:
        ASSERT_NOT_REACHED();
        return { Horizontal, NonCJKGlyphOrientation::Mixed };
    }
}

void RenderStyle::setBorderImageSource(RefPtr<StyleImage>&& image)
{
    if (m_surroundData->border.m_image.image() == image.get())
        return;
    m_surroundData.access().border.m_image.setImage(WTFMove(image));
}

void RenderStyle::setBorderImageSlices(LengthBox&& slices)
{
    if (m_surroundData->border.m_image.imageSlices() == slices)
        return;
    m_surroundData.access().border.m_image.setImageSlices(WTFMove(slices));
}

void RenderStyle::setBorderImageWidth(LengthBox&& slices)
{
    if (m_surroundData->border.m_image.borderSlices() == slices)
        return;
    m_surroundData.access().border.m_image.setBorderSlices(WTFMove(slices));
}

void RenderStyle::setBorderImageOutset(LengthBox&& outset)
{
    if (m_surroundData->border.m_image.outset() == outset)
        return;
    m_surroundData.access().border.m_image.setOutset(WTFMove(outset));
}

void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
{
    if (paginationMode == Pagination::Unpaginated)
        return;
    
    setColumnFill(ColumnFillAuto);
    
    switch (paginationMode) {
    case Pagination::LeftToRightPaginated:
        setColumnAxis(HorizontalColumnAxis);
        if (isHorizontalWritingMode())
            setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
        else
            setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
        break;
    case Pagination::RightToLeftPaginated:
        setColumnAxis(HorizontalColumnAxis);
        if (isHorizontalWritingMode())
            setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
        else
            setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
        break;
    case Pagination::TopToBottomPaginated:
        setColumnAxis(VerticalColumnAxis);
        if (isHorizontalWritingMode())
            setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
        else
            setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
        break;
    case Pagination::BottomToTopPaginated:
        setColumnAxis(VerticalColumnAxis);
        if (isHorizontalWritingMode())
            setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
        else
            setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
        break;
    case Pagination::Unpaginated:
        ASSERT_NOT_REACHED();
        break;
    }
}

#if ENABLE(CSS_SCROLL_SNAP)

ScrollSnapType RenderStyle::initialScrollSnapType()
{
    return { };
}

ScrollSnapAlign RenderStyle::initialScrollSnapAlign()
{
    return { };
}

const StyleScrollSnapArea& RenderStyle::scrollSnapArea() const
{
    return *m_rareNonInheritedData->scrollSnapArea;
}

const StyleScrollSnapPort& RenderStyle::scrollSnapPort() const
{
    return *m_rareNonInheritedData->scrollSnapPort;
}

const ScrollSnapType& RenderStyle::scrollSnapType() const
{
    return m_rareNonInheritedData->scrollSnapPort->type;
}

const LengthBox& RenderStyle::scrollPadding() const
{
    return m_rareNonInheritedData->scrollSnapPort->scrollPadding;
}

const Length& RenderStyle::scrollPaddingTop() const
{
    return scrollPadding().top();
}

const Length& RenderStyle::scrollPaddingBottom() const
{
    return scrollPadding().bottom();
}

const Length& RenderStyle::scrollPaddingLeft() const
{
    return scrollPadding().left();
}

const Length& RenderStyle::scrollPaddingRight() const
{
    return scrollPadding().right();
}

const ScrollSnapAlign& RenderStyle::scrollSnapAlign() const
{
    return m_rareNonInheritedData->scrollSnapArea->alignment;
}

const LengthBox& RenderStyle::scrollSnapMargin() const
{
    return m_rareNonInheritedData->scrollSnapArea->scrollSnapMargin;
}

const Length& RenderStyle::scrollSnapMarginTop() const
{
    return scrollSnapMargin().top();
}

const Length& RenderStyle::scrollSnapMarginBottom() const
{
    return scrollSnapMargin().bottom();
}

const Length& RenderStyle::scrollSnapMarginLeft() const
{
    return scrollSnapMargin().left();
}

const Length& RenderStyle::scrollSnapMarginRight() const
{
    return scrollSnapMargin().right();
}

void RenderStyle::setScrollSnapType(const ScrollSnapType& type)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, type, type);
}

void RenderStyle::setScrollPaddingTop(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.top(), WTFMove(length));
}

void RenderStyle::setScrollPaddingBottom(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.bottom(), WTFMove(length));
}

void RenderStyle::setScrollPaddingLeft(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.left(), WTFMove(length));
}

void RenderStyle::setScrollPaddingRight(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.right(), WTFMove(length));
}

void RenderStyle::setScrollSnapAlign(const ScrollSnapAlign& alignment)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, alignment, alignment);
}

void RenderStyle::setScrollSnapMarginTop(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.top(), WTFMove(length));
}

void RenderStyle::setScrollSnapMarginBottom(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.bottom(), WTFMove(length));
}

void RenderStyle::setScrollSnapMarginLeft(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.left(), WTFMove(length));
}

void RenderStyle::setScrollSnapMarginRight(Length&& length)
{
    SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.right(), WTFMove(length));
}

#endif

bool RenderStyle::hasReferenceFilterOnly() const
{
    if (!hasFilter())
        return false;
    auto& filterOperations = m_rareNonInheritedData->filter->operations;
    return filterOperations.size() == 1 && filterOperations.at(0)->type() == FilterOperation::REFERENCE;
}

void RenderStyle::checkVariablesInCustomProperties()
{
    if (!m_rareInheritedData->customProperties->containsVariables)
        return;

    auto& customPropertyData = m_rareInheritedData.access().customProperties.access();

    // Our first pass checks the variables for validity and replaces any properties that became
    // invalid with empty values.
    auto& customProperties = customPropertyData.values;
    HashSet<AtomicString> invalidProperties;
    for (auto entry : customProperties) {
        if (!entry.value->containsVariables())
            continue;
        HashSet<AtomicString> seenProperties;
        entry.value->checkVariablesForCycles(entry.key, customProperties, seenProperties, invalidProperties);
    }
    
    // Now insert invalid values.
    if (!invalidProperties.isEmpty()) {
        auto invalidValue = CSSCustomPropertyValue::createInvalid();
        for (auto& property : invalidProperties)
            customProperties.set(property, invalidValue.copyRef());
    }

    // Now that all of the properties have been tested for validity and replaced with
    // invalid values if they failed, we can perform variable substitution on the valid values.
    Vector<Ref<CSSCustomPropertyValue>> resolvedValues;
    for (auto entry : customProperties) {
        if (!entry.value->containsVariables())
            continue;
        entry.value->resolveVariableReferences(customProperties, resolvedValues);
    }
    
    // With all results computed, we can now mutate our table to eliminate the variables and
    // hold the final values. This way when we inherit, we don't end up resubstituting variables, etc.
    for (auto& resolvedValue : resolvedValues)
        customProperties.set(resolvedValue->name(), resolvedValue.copyRef());

    customPropertyData.containsVariables = false;
}

float RenderStyle::outlineWidth() const
{
    if (m_backgroundData->outline.style() == BNONE)
        return 0;
    if (outlineStyleIsAuto())
        return std::max(m_backgroundData->outline.width(), RenderTheme::platformFocusRingWidth());
    return m_backgroundData->outline.width();
}

float RenderStyle::outlineOffset() const
{
    if (m_backgroundData->outline.style() == BNONE)
        return 0;
    if (outlineStyleIsAuto())
        return (m_backgroundData->outline.offset() + RenderTheme::platformFocusRingOffset(outlineWidth()));
    return m_backgroundData->outline.offset();
}

bool RenderStyle::shouldPlaceBlockDirectionScrollbarOnLeft() const
{
    return !isLeftToRightDirection() && isHorizontalWritingMode();
}

#if ENABLE(DASHBOARD_SUPPORT)

void RenderStyle::setDashboardRegion(int type, const String& label, Length&& top, Length&& right, Length&& bottom, Length&& left, bool append)
{
    if (!append)
        m_rareNonInheritedData.access().dashboardRegions.clear();
    m_rareNonInheritedData.access().dashboardRegions.append({ label, { WTFMove(top), WTFMove(right), WTFMove(bottom), WTFMove(left) }, type });
}

#endif

Vector<PaintType, 3> RenderStyle::paintTypesForPaintOrder(PaintOrder order)
{
    Vector<PaintType, 3> paintOrder;
    switch (order) {
    case PaintOrder::Normal:
        FALLTHROUGH;
    case PaintOrder::Fill:
        paintOrder.append(PaintType::Fill);
        paintOrder.append(PaintType::Stroke);
        paintOrder.append(PaintType::Markers);
        break;
    case PaintOrder::FillMarkers:
        paintOrder.append(PaintType::Fill);
        paintOrder.append(PaintType::Markers);
        paintOrder.append(PaintType::Stroke);
        break;
    case PaintOrder::Stroke:
        paintOrder.append(PaintType::Stroke);
        paintOrder.append(PaintType::Fill);
        paintOrder.append(PaintType::Markers);
        break;
    case PaintOrder::StrokeMarkers:
        paintOrder.append(PaintType::Stroke);
        paintOrder.append(PaintType::Markers);
        paintOrder.append(PaintType::Fill);
        break;
    case PaintOrder::Markers:
        paintOrder.append(PaintType::Markers);
        paintOrder.append(PaintType::Fill);
        paintOrder.append(PaintType::Stroke);
        break;
    case PaintOrder::MarkersStroke:
        paintOrder.append(PaintType::Markers);
        paintOrder.append(PaintType::Stroke);
        paintOrder.append(PaintType::Fill);
        break;
    };
    return paintOrder;
}

float RenderStyle::computedStrokeWidth(const IntSize& viewportSize) const
{
    // Use the stroke-width and stroke-color value combination only if stroke-color has been explicitly specified.
    // Since there will be no visible stroke when stroke-color is not specified (transparent by default), we fall
    // back to the legacy Webkit text stroke combination in that case.
    if (!hasExplicitlySetStrokeColor())
        return textStrokeWidth();
    
    const Length& length = strokeWidth();

    if (length.isPercent()) {
        // According to the spec, https://drafts.fxtf.org/paint/#stroke-width, the percentage is relative to the scaled viewport size.
        // The scaled viewport size is the geometric mean of the viewport width and height.
        ExceptionOr<float> result = length.value() * (viewportSize.width() + viewportSize.height()) / 200.0f;
        if (result.hasException())
            return 0;
        return result.releaseReturnValue();
    }
    
    if (length.isAuto() || !length.isSpecified())
        return 0;
    
    return floatValueForLength(length, viewportSize.width());
}

bool RenderStyle::hasPositiveStrokeWidth() const
{
    if (!hasExplicitlySetStrokeWidth())
        return textStrokeWidth() > 0;

    return strokeWidth().isPositive();
}

Color RenderStyle::computedStrokeColor() const
{
    CSSPropertyID propertyID = CSSPropertyStrokeColor;
    if (!hasExplicitlySetStrokeColor())
        propertyID = CSSPropertyWebkitTextStrokeColor;
    return visitedDependentColor(propertyID);
}

} // namespace WebCore
