Use a light scrollbar for transparent web views in dark mode.
[WebKit-https.git] / Source / WebCore / rendering / style / RenderStyle.cpp
index 8fe82e1..7ba1091 100644 (file)
@@ -39,6 +39,7 @@
 #include "RuntimeEnabledFeatures.h"
 #include "ScaleTransformOperation.h"
 #include "ShadowData.h"
+#include "StyleBuilderConverter.h"
 #include "StyleImage.h"
 #include "StyleInheritedData.h"
 #include "StyleResolver.h"
@@ -58,8 +59,8 @@
 namespace WebCore {
 
 struct SameSizeAsBorderValue {
-    float m_width;
     Color m_color;
+    float m_width;
     int m_restBits;
 };
 
@@ -74,14 +75,14 @@ struct SameSizeAsRenderStyle {
     } m_inheritedFlags;
 
     struct NonInheritedFlags {
-        uint64_t m_flags;
+        unsigned m_bitfields[2];
     } m_nonInheritedFlags;
 #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
     bool deletionCheck;
 #endif
 };
 
-COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
+static_assert(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), "RenderStyle should stay small");
 
 RenderStyle& RenderStyle::defaultStyle()
 {
@@ -109,7 +110,7 @@ std::unique_ptr<RenderStyle> RenderStyle::clonePtr(const RenderStyle& style)
     return std::make_unique<RenderStyle>(style, Clone);
 }
 
-RenderStyle RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle& parentStyle, EDisplay display)
+RenderStyle RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle& parentStyle, DisplayType display)
 {
     auto newStyle = create();
     newStyle.inheritFrom(parentStyle);
@@ -120,13 +121,16 @@ RenderStyle RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle& pare
 
 RenderStyle RenderStyle::createStyleInheritingFromPseudoStyle(const RenderStyle& pseudoStyle)
 {
-    ASSERT(pseudoStyle.styleType() == BEFORE || pseudoStyle.styleType() == AFTER);
+    ASSERT(pseudoStyle.styleType() == PseudoId::Before || pseudoStyle.styleType() == PseudoId::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())
@@ -137,29 +141,55 @@ RenderStyle::RenderStyle(CreateDefaultStyleTag)
     , 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();
+    m_inheritedFlags.emptyCells = static_cast<unsigned>(initialEmptyCells());
+    m_inheritedFlags.captionSide = static_cast<unsigned>(initialCaptionSide());
+    m_inheritedFlags.listStyleType = static_cast<unsigned>(initialListStyleType());
+    m_inheritedFlags.listStylePosition = static_cast<unsigned>(initialListStylePosition());
+    m_inheritedFlags.visibility = static_cast<unsigned>(initialVisibility());
+    m_inheritedFlags.textAlign = static_cast<unsigned>(initialTextAlign());
+    m_inheritedFlags.textTransform = static_cast<unsigned>(initialTextTransform());
+    m_inheritedFlags.textDecorations = initialTextDecoration().toRaw();
+    m_inheritedFlags.cursor = static_cast<unsigned>(initialCursor());
 #if ENABLE(CURSOR_VISIBILITY)
-    m_inheritedFlags.cursorVisibility = initialCursorVisibility();
+    m_inheritedFlags.cursorVisibility = static_cast<unsigned>(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.direction = static_cast<unsigned>(initialDirection());
+    m_inheritedFlags.whiteSpace = static_cast<unsigned>(initialWhiteSpace());
+    m_inheritedFlags.borderCollapse = static_cast<unsigned>(initialBorderCollapse());
+    m_inheritedFlags.rtlOrdering = static_cast<unsigned>(initialRTLOrdering());
+    m_inheritedFlags.boxDirection = static_cast<unsigned>(initialBoxDirection());
+    m_inheritedFlags.printColorAdjust = static_cast<unsigned>(initialPrintColorAdjust());
+    m_inheritedFlags.pointerEvents = static_cast<unsigned>(initialPointerEvents());
+    m_inheritedFlags.insideLink = static_cast<unsigned>(InsideLink::NotInside);
     m_inheritedFlags.insideDefaultButton = false;
     m_inheritedFlags.writingMode = initialWritingMode();
 
+    m_nonInheritedFlags.effectiveDisplay = static_cast<unsigned>(initialDisplay());
+    m_nonInheritedFlags.originalDisplay = static_cast<unsigned>(initialDisplay());
+    m_nonInheritedFlags.overflowX = static_cast<unsigned>(initialOverflowX());
+    m_nonInheritedFlags.overflowY = static_cast<unsigned>(initialOverflowY());
+    m_nonInheritedFlags.verticalAlign = static_cast<unsigned>(initialVerticalAlign());
+    m_nonInheritedFlags.clear = static_cast<unsigned>(initialClear());
+    m_nonInheritedFlags.position = static_cast<unsigned>(initialPosition());
+    m_nonInheritedFlags.unicodeBidi = initialUnicodeBidi();
+    m_nonInheritedFlags.floating = static_cast<unsigned>(initialFloating());
+    m_nonInheritedFlags.tableLayout = static_cast<unsigned>(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 = static_cast<unsigned>(PseudoId::None);
+    m_nonInheritedFlags.pseudoBits = static_cast<unsigned>(PseudoId::None);
+
     static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags does not grow");
     static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags does not grow");
 }
@@ -206,20 +236,10 @@ RenderStyle RenderStyle::replace(RenderStyle&& newStyle)
     return RenderStyle { *this, WTFMove(newStyle) };
 }
 
-bool RenderStyle::isCSSGridLayoutEnabled()
-{
-#if ENABLE(CSS_GRID_LAYOUT)
-    return RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled();
-#else
-    return false;
-#endif
-}
-
 static StyleSelfAlignmentData resolvedSelfAlignment(const StyleSelfAlignmentData& value, ItemPosition normalValueBehavior)
 {
-    ASSERT(value.position() != ItemPositionAuto);
-    if (value.position() == ItemPositionNormal)
-        return { normalValueBehavior, OverflowAlignmentDefault };
+    if (value.position() == ItemPosition::Legacy || value.position() == ItemPosition::Normal || value.position() == ItemPosition::Auto)
+        return { normalValueBehavior, OverflowAlignment::Default };
     return value;
 }
 
@@ -228,42 +248,54 @@ StyleSelfAlignmentData RenderStyle::resolvedAlignItems(ItemPosition normalValueB
     return resolvedSelfAlignment(alignItems(), normalValueBehaviour);
 }
 
-StyleSelfAlignmentData RenderStyle::resolvedAlignSelf(const RenderStyle& parentStyle, ItemPosition normalValueBehaviour) const
+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 (alignSelf().position() == ItemPositionAuto)
-        return parentStyle.resolvedAlignItems(normalValueBehaviour);
-    return resolvedSelfAlignment(alignSelf(), normalValueBehaviour);
+    if (!parentStyle || alignSelf().position() != ItemPosition::Auto)
+        return resolvedSelfAlignment(alignSelf(), normalValueBehaviour);
+    return parentStyle->resolvedAlignItems(normalValueBehaviour);
 }
 
 StyleSelfAlignmentData RenderStyle::resolvedJustifyItems(ItemPosition normalValueBehaviour) const
 {
-    // FIXME: justify-items 'auto' value is allowed only to provide the 'legacy' keyword's behavior, which it's still not implemented for layout.
-    // "If the inherited value of justify-items includes the legacy keyword, auto computes to the inherited value."
-    // https://drafts.csswg.org/css-align/#justify-items-property
-    if (justifyItems().position() == ItemPositionAuto)
-        return { normalValueBehaviour, OverflowAlignmentDefault };
     return resolvedSelfAlignment(justifyItems(), normalValueBehaviour);
 }
 
-StyleSelfAlignmentData RenderStyle::resolvedJustifySelf(const RenderStyle& parentStyle, ItemPosition normalValueBehaviour) const
+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 (justifySelf().position() == ItemPositionAuto)
-        return parentStyle.resolvedJustifyItems(normalValueBehaviour);
-    return resolvedSelfAlignment(justifySelf(), normalValueBehaviour);
+    if (!parentStyle || justifySelf().position() != ItemPosition::Auto)
+        return resolvedSelfAlignment(justifySelf(), normalValueBehaviour);
+    return parentStyle->resolvedJustifyItems(normalValueBehaviour);
+}
+
+static inline StyleContentAlignmentData resolvedContentAlignment(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
+{
+    return (value.position() == ContentPosition::Normal && value.distribution() == ContentDistribution::Default) ? 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();
+    return (value.position() == ContentPosition::Normal && value.distribution() == ContentDistribution::Default) ? normalValueBehavior.position() : value.position();
 }
 
-static inline ContentDistributionType resolvedContentAlignmentDistribution(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
+static inline ContentDistribution resolvedContentAlignmentDistribution(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
 {
-    return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.distribution() : value.distribution();
+    return (value.position() == ContentPosition::Normal && value.distribution() == ContentDistribution::Default) ? normalValueBehavior.distribution() : value.distribution();
 }
 
 ContentPosition RenderStyle::resolvedJustifyContentPosition(const StyleContentAlignmentData& normalValueBehavior) const
@@ -271,7 +303,7 @@ ContentPosition RenderStyle::resolvedJustifyContentPosition(const StyleContentAl
     return resolvedContentAlignmentPosition(justifyContent(), normalValueBehavior);
 }
 
-ContentDistributionType RenderStyle::resolvedJustifyContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
+ContentDistribution RenderStyle::resolvedJustifyContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
 {
     return resolvedContentAlignmentDistribution(justifyContent(), normalValueBehavior);
 }
@@ -281,7 +313,7 @@ ContentPosition RenderStyle::resolvedAlignContentPosition(const StyleContentAlig
     return resolvedContentAlignmentPosition(alignContent(), normalValueBehavior);
 }
 
-ContentDistributionType RenderStyle::resolvedAlignContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
+ContentDistribution RenderStyle::resolvedAlignContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
 {
     return resolvedContentAlignmentDistribution(alignContent(), normalValueBehavior);
 }
@@ -311,6 +343,13 @@ void RenderStyle::copyNonInheritedFrom(const RenderStyle& other)
     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
@@ -328,7 +367,7 @@ bool RenderStyle::operator==(const RenderStyle& other) const
 
 bool RenderStyle::hasUniquePseudoStyle() const
 {
-    if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
+    if (!m_cachedPseudoStyles || styleType() != PseudoId::None)
         return false;
 
     for (auto& pseudoStyle : *m_cachedPseudoStyles) {
@@ -344,7 +383,7 @@ RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
         return nullptr;
 
-    if (styleType() != NOPSEUDO
+    if (styleType() != PseudoId::None
         return nullptr;
 
     for (auto& pseudoStyle : *m_cachedPseudoStyles) {
@@ -360,7 +399,7 @@ RenderStyle* RenderStyle::addCachedPseudoStyle(std::unique_ptr<RenderStyle> pseu
     if (!pseudo)
         return nullptr;
 
-    ASSERT(pseudo->styleType() > NOPSEUDO);
+    ASSERT(pseudo->styleType() > PseudoId::None);
 
     RenderStyle* result = pseudo.get();
 
@@ -419,8 +458,8 @@ unsigned RenderStyle::hashForTextAutosizing() const
     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_nonInheritedFlags.position;
+    hash ^= m_nonInheritedFlags.floating;
     hash ^= m_rareNonInheritedData->textOverflow;
     hash ^= m_rareInheritedData->textSecurity;
     return hash;
@@ -443,8 +482,8 @@ bool RenderStyle::equalForTextAutosizing(const RenderStyle& other) const
         && 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.position == other.m_nonInheritedFlags.position
+        && m_nonInheritedFlags.floating == other.m_nonInheritedFlags.floating
         && m_rareNonInheritedData->textOverflow == other.m_rareNonInheritedData->textOverflow;
 }
 
@@ -454,9 +493,9 @@ 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.get() == other->m_inheritedData.get()
-        && m_svgStyle.get() == other->m_svgStyle.get()
-        && m_rareInheritedData.get() == other->m_rareInheritedData.get();
+        && 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)
@@ -488,23 +527,20 @@ static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b,
 
 inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const
 {
-    if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()
+    if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()
         && !arePointingToEqualData(m_rareNonInheritedData->boxShadow, other.m_rareNonInheritedData->boxShadow))
         return true;
 
-    if (m_rareInheritedData.get() != other.m_rareInheritedData.get()
+    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);
+        || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle
+        || m_rareInheritedData->textDecorationThickness != other.m_rareInheritedData->textDecorationThickness
+        || m_rareInheritedData->textUnderlineOffset != other.m_rareInheritedData->textUnderlineOffset
+        || m_rareInheritedData->textUnderlinePosition != other.m_rareInheritedData->textUnderlinePosition) {
+        return true;
     }
 
     if (hasOutlineInVisualOverflow() != other.hasOutlineInVisualOverflow())
@@ -512,182 +548,243 @@ inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) c
     return false;
 }
 
-bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
+static bool rareNonInheritedDataChangeRequiresLayout(const StyleRareNonInheritedData& first, const StyleRareNonInheritedData& second, OptionSet<StyleDifferenceContextSensitiveProperty>& changedContextSensitiveProperties)
 {
-    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;
+    ASSERT(&first != &second);
 
-    if (m_boxData->verticalAlign() != other.m_boxData->verticalAlign() || m_nonInheritedFlags.verticalAlign() != other.m_nonInheritedFlags.verticalAlign())
+    if (first.appearance != second.appearance
+        || first.marginBeforeCollapse != second.marginBeforeCollapse
+        || first.marginAfterCollapse != second.marginAfterCollapse
+        || first.lineClamp != second.lineClamp
+        || first.initialLetter != second.initialLetter
+        || first.textOverflow != second.textOverflow)
         return true;
 
-    if (m_boxData->boxSizing() != other.m_boxData->boxSizing())
+    if (first.shapeMargin != second.shapeMargin)
         return true;
 
-    if (m_surroundData->margin != other.m_surroundData->margin)
+    if (first.deprecatedFlexibleBox != second.deprecatedFlexibleBox)
         return true;
 
-    if (m_surroundData->padding != other.m_surroundData->padding)
+    if (first.flexibleBox != second.flexibleBox)
         return true;
 
-    // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
-    if (changeAffectsVisualOverflow(other))
+    if (first.order != second.order
+        || first.alignContent != second.alignContent
+        || first.alignItems != second.alignItems
+        || first.alignSelf != second.alignSelf
+        || first.justifyContent != second.justifyContent
+        || first.justifyItems != second.justifyItems
+        || first.justifySelf != second.justifySelf)
         return true;
 
-    if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
-        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 (!arePointingToEqualData(first.boxReflect, second.boxReflect))
+        return true;
 
-        if (m_rareNonInheritedData->regionFragment != other.m_rareNonInheritedData->regionFragment)
-            return true;
+    if (first.multiCol != second.multiCol)
+        return true;
 
-        if (m_rareNonInheritedData->shapeMargin != other.m_rareNonInheritedData->shapeMargin)
+    if (first.transform.ptr() != second.transform.ptr()) {
+        if (first.transform->hasTransform() != second.transform->hasTransform())
             return true;
+        if (*first.transform != *second.transform) {
+            changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::Transform);
+            // Don't return; keep looking for another change
+        }
+    }
 
-        if (m_rareNonInheritedData->deprecatedFlexibleBox != other.m_rareNonInheritedData->deprecatedFlexibleBox)
-            return true;
+    if (first.grid != second.grid
+        || first.gridItem != second.gridItem)
+        return true;
 
-        if (m_rareNonInheritedData->flexibleBox != other.m_rareNonInheritedData->flexibleBox)
-            return true;
+#if ENABLE(DASHBOARD_SUPPORT)
+    // If regions change, trigger a relayout to re-calc regions.
+    if (first.dashboardRegions != second.dashboardRegions)
+        return true;
+#endif
 
-        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(first.willChange, second.willChange)) {
+        changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::WillChange);
+        // Don't return; keep looking for another change
+    }
 
-        if (!arePointingToEqualData(m_rareNonInheritedData->boxReflect, other.m_rareNonInheritedData->boxReflect))
-            return true;
+    if (first.textCombine != second.textCombine)
+        return true;
 
-        if (m_rareNonInheritedData->multiCol != other.m_rareNonInheritedData->multiCol)
-            return true;
+    if (first.breakBefore != second.breakBefore
+        || first.breakAfter != second.breakAfter
+        || first.breakInside != second.breakInside)
+        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 (first.hasOpacity() != second.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 ENABLE(CSS_GRID_LAYOUT)
-        if (m_rareNonInheritedData->grid != other.m_rareNonInheritedData->grid
-            || m_rareNonInheritedData->gridItem != other.m_rareNonInheritedData->gridItem)
-            return true;
+#if ENABLE(CSS_COMPOSITING)
+    if (first.isolation != second.isolation) {
+        // Ideally this would trigger a cheaper layout that just updates layer z-order trees (webit.org/b/190088).
+        return true;
+    }
 #endif
 
-#if ENABLE(DASHBOARD_SUPPORT)
-        // If regions change, trigger a relayout to re-calc regions.
-        if (m_rareNonInheritedData->dashboardRegions != other.m_rareNonInheritedData->dashboardRegions)
-            return true;
+    if (first.hasFilters() != second.hasFilters())
+        return true;
+
+#if ENABLE(FILTERS_LEVEL_2)
+    if (first.hasBackdropFilters() != second.hasBackdropFilters())
+        return true;
 #endif
 
-        if (!arePointingToEqualData(m_rareNonInheritedData->willChange, other.m_rareNonInheritedData->willChange)) {
-            changedContextSensitiveProperties |= ContextSensitivePropertyWillChange;
-            // Don't return; keep looking for another change
-        }
-    }
+    return false;
+}
 
-    if (m_rareInheritedData.get() != other.m_rareInheritedData.get()) {
-        if (m_rareInheritedData->indent != other.m_rareInheritedData->indent
+static bool rareInheritedDataChangeRequiresLayout(const StyleRareInheritedData& first, const StyleRareInheritedData& second)
+{
+    ASSERT(&first != &second);
+
+    if (first.indent != second.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
+        || first.textAlignLast != second.textAlignLast
+        || first.textJustify != second.textJustify
+        || first.textIndentLine != second.textIndentLine
 #endif
-            || m_rareInheritedData->effectiveZoom != other.m_rareInheritedData->effectiveZoom
-            || m_rareInheritedData->textZoom != other.m_rareInheritedData->textZoom
+        || first.effectiveZoom != second.effectiveZoom
+        || first.textZoom != second.textZoom
 #if ENABLE(TEXT_AUTOSIZING)
-            || m_rareInheritedData->textSizeAdjust != other.m_rareInheritedData->textSizeAdjust
+        || first.textSizeAdjust != second.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
+        || first.wordBreak != second.wordBreak
+        || first.overflowWrap != second.overflowWrap
+        || first.nbspMode != second.nbspMode
+        || first.lineBreak != second.lineBreak
+        || first.textSecurity != second.textSecurity
+        || first.hyphens != second.hyphens
+        || first.hyphenationLimitBefore != second.hyphenationLimitBefore
+        || first.hyphenationLimitAfter != second.hyphenationLimitAfter
+        || first.hyphenationString != second.hyphenationString
+        || first.rubyPosition != second.rubyPosition
+        || first.textEmphasisMark != second.textEmphasisMark
+        || first.textEmphasisPosition != second.textEmphasisPosition
+        || first.textEmphasisCustomMark != second.textEmphasisCustomMark
+        || first.textOrientation != second.textOrientation
+        || first.tabSize != second.tabSize
+        || first.lineBoxContain != second.lineBoxContain
+        || first.lineGrid != second.lineGrid
 #if ENABLE(CSS_IMAGE_ORIENTATION)
-            || m_rareInheritedData->imageOrientation != other.m_rareInheritedData->imageOrientation
+        || first.imageOrientation != second.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
+        || first.imageResolutionSource != second.imageResolutionSource
+        || first.imageResolutionSnap != second.imageResolutionSnap
+        || first.imageResolution != second.imageResolution
 #endif
-            || m_rareInheritedData->lineSnap != other.m_rareInheritedData->lineSnap
-            || m_rareInheritedData->lineAlign != other.m_rareInheritedData->lineAlign
-            || m_rareInheritedData->hangingPunctuation != other.m_rareInheritedData->hangingPunctuation
+        || first.lineSnap != second.lineSnap
+        || first.lineAlign != second.lineAlign
+        || first.hangingPunctuation != second.hangingPunctuation
 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
-            || m_rareInheritedData->useTouchOverflowScrolling != other.m_rareInheritedData->useTouchOverflowScrolling
+        || first.useTouchOverflowScrolling != second.useTouchOverflowScrolling
 #endif
-            || m_rareInheritedData->listStyleImage != other.m_rareInheritedData->listStyleImage) // FIXME: needs arePointingToEqualData()?
+        || first.listStyleImage != second.listStyleImage) // FIXME: needs arePointingToEqualData()?
+        return true;
+
+    if (first.textStrokeWidth != second.textStrokeWidth)
+        return true;
+
+    // These properties affect the cached stroke bounding box rects.
+    if (first.capStyle != second.capStyle
+        || first.joinStyle != second.joinStyle
+        || first.strokeWidth != second.strokeWidth
+        || first.miterLimit != second.miterLimit)
+        return true;
+
+    if (!arePointingToEqualData(first.quotes, second.quotes))
+        return true;
+
+    return false;
+}
+
+bool RenderStyle::changeRequiresLayout(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>& changedContextSensitiveProperties) const
+{
+    if (m_boxData.ptr() != other.m_boxData.ptr()) {
+        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())
             return true;
 
-        if (textStrokeWidth() != other.textStrokeWidth())
+        if (m_boxData->boxSizing() != other.m_boxData->boxSizing())
             return true;
     }
 
-    if (m_inheritedData->lineHeight != other.m_inheritedData->lineHeight
+    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()
+        && rareNonInheritedDataChangeRequiresLayout(*m_rareNonInheritedData, *other.m_rareNonInheritedData, changedContextSensitiveProperties))
+        return true;
+
+    if (m_rareInheritedData.ptr() != other.m_rareInheritedData.ptr()
+        && rareInheritedDataChangeRequiresLayout(*m_rareInheritedData, *other.m_rareInheritedData))
+        return true;
+
+    if (m_inheritedData.ptr() != other.m_inheritedData.ptr()) {
+        if (m_inheritedData->lineHeight != other.m_inheritedData->lineHeight
 #if ENABLE(TEXT_AUTOSIZING)
-        || m_inheritedData->specifiedLineHeight != other.m_inheritedData->specifiedLineHeight
+            || 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_inheritedData->fontCascade != other.m_inheritedData->fontCascade
+            || m_inheritedData->horizontalBorderSpacing != other.m_inheritedData->horizontalBorderSpacing
+            || m_inheritedData->verticalBorderSpacing != other.m_inheritedData->verticalBorderSpacing)
+            return true;
+    }
+
+    if (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())
+        || m_nonInheritedFlags.position != other.m_nonInheritedFlags.position
+        || m_nonInheritedFlags.floating != other.m_nonInheritedFlags.floating
+        || m_nonInheritedFlags.originalDisplay != other.m_nonInheritedFlags.originalDisplay
+        || m_nonInheritedFlags.verticalAlign != other.m_nonInheritedFlags.verticalAlign)
         return true;
 
-
-    if ((m_nonInheritedFlags.effectiveDisplay()) >= TABLE) {
+    if (static_cast<DisplayType>(m_nonInheritedFlags.effectiveDisplay) >= DisplayType::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())
+            || 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)))
+            && ((borderTopStyle() == BorderStyle::Hidden && other.borderTopStyle() == BorderStyle::None)
+                || (borderTopStyle() == BorderStyle::None && other.borderTopStyle() == BorderStyle::Hidden)
+                || (borderBottomStyle() == BorderStyle::Hidden && other.borderBottomStyle() == BorderStyle::None)
+                || (borderBottomStyle() == BorderStyle::None && other.borderBottomStyle() == BorderStyle::Hidden)
+                || (borderLeftStyle() == BorderStyle::Hidden && other.borderLeftStyle() == BorderStyle::None)
+                || (borderLeftStyle() == BorderStyle::None && other.borderLeftStyle() == BorderStyle::Hidden)
+                || (borderRightStyle() == BorderStyle::Hidden && other.borderRightStyle() == BorderStyle::None)
+                || (borderRightStyle() == BorderStyle::None && other.borderRightStyle() == BorderStyle::Hidden)))
             return true;
     }
 
-    if (m_nonInheritedFlags.effectiveDisplay() == LIST_ITEM) {
+    if (static_cast<DisplayType>(m_nonInheritedFlags.effectiveDisplay) == DisplayType::ListItem) {
         if (m_inheritedFlags.listStyleType != other.m_inheritedFlags.listStyleType
             || m_inheritedFlags.listStylePosition != other.m_inheritedFlags.listStylePosition)
             return true;
@@ -697,27 +794,17 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& chang
         || 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())
+        || 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())
+    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
@@ -732,35 +819,15 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& chang
     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())
+    if ((visibility() == Visibility::Collapse) != (other.visibility() == Visibility::Collapse))
         return true;
-#endif
 
-    if (!arePointingToEqualData(m_rareInheritedData->quotes, other.m_rareInheritedData->quotes))
-        return true;
-
-    if (position() != StaticPosition) {
+    if (position() != PositionType::Static) {
         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)
+            if (position() != PositionType::Absolute)
                 return true;
 
             // Optimize for the case where a positioned layer is moving but not changing size.
@@ -769,14 +836,14 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& chang
         }
     }
 
-    bool hasFirstLineStyle = hasPseudoStyle(FIRST_LINE);
-    if (hasFirstLineStyle != other.hasPseudoStyle(FIRST_LINE))
+    bool hasFirstLineStyle = hasPseudoStyle(PseudoId::FirstLine);
+    if (hasFirstLineStyle != other.hasPseudoStyle(PseudoId::FirstLine))
         return true;
     if (hasFirstLineStyle) {
-        auto* firstLineStyle = getCachedPseudoStyle(FIRST_LINE);
+        auto* firstLineStyle = getCachedPseudoStyle(PseudoId::FirstLine);
         if (!firstLineStyle)
             return true;
-        auto* otherFirstLineStyle = other.getCachedPseudoStyle(FIRST_LINE);
+        auto* otherFirstLineStyle = other.getCachedPseudoStyle(PseudoId::FirstLine);
         if (!otherFirstLineStyle)
             return true;
         // FIXME: Not all first line style changes actually need layout.
@@ -787,92 +854,139 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& chang
     return false;
 }
 
-bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle& other, unsigned&) const
+bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>&) const
 {
-    if (position() == StaticPosition)
+    if (position() == PositionType::Static)
         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()))
+        if (position() == PositionType::Absolute && positionChangeIsMovementOnly(m_surroundData->offset, other.m_surroundData->offset, m_boxData->width()))
             return true;
     }
     
     return false;
 }
 
-bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
+static bool rareNonInheritedDataChangeRequiresLayerRepaint(const StyleRareNonInheritedData& first, const StyleRareNonInheritedData& second, OptionSet<StyleDifferenceContextSensitiveProperty>& changedContextSensitiveProperties)
+{
+#if ENABLE(CSS_COMPOSITING)
+    if (first.effectiveBlendMode != second.effectiveBlendMode)
+        return true;
+#endif
+
+    if (first.opacity != second.opacity) {
+        changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::Opacity);
+        // Don't return true; keep looking for another change.
+    }
+
+    if (first.filter != second.filter) {
+        changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::Filter);
+        // Don't return true; keep looking for another change.
+    }
+
+#if ENABLE(FILTERS_LEVEL_2)
+    if (first.backdropFilter != second.backdropFilter) {
+        changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::Filter);
+        // Don't return true; keep looking for another change.
+    }
+#endif
+
+    if (first.mask != second.mask || first.maskBoxImage != second.maskBoxImage)
+        return true;
+
+    return false;
+}
+
+bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>& 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 (position() != PositionType::Static) {
         if (m_visualData->clip != other.m_visualData->clip || m_visualData->hasClip != other.m_visualData->hasClip) {
-            changedContextSensitiveProperties |= ContextSensitivePropertyClipRect;
+            changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::ClipRect);
             return true;
         }
     }
 
-#if ENABLE(CSS_COMPOSITING)
-    if (m_rareNonInheritedData->effectiveBlendMode != other.m_rareNonInheritedData->effectiveBlendMode)
+    if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()
+        && rareNonInheritedDataChangeRequiresLayerRepaint(*m_rareNonInheritedData, *other.m_rareNonInheritedData, changedContextSensitiveProperties))
         return true;
-#endif
 
-    if (m_rareNonInheritedData->opacity != other.m_rareNonInheritedData->opacity) {
-        changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
-        // Don't return; keep looking for another change.
-    }
+    return false;
+}
 
-    if (m_rareNonInheritedData->filter != other.m_rareNonInheritedData->filter) {
-        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
-        // Don't return; keep looking for another change.
-    }
+static bool requiresPainting(const RenderStyle& style)
+{
+    if (style.visibility() == Visibility::Hidden)
+        return false;
+    if (!style.opacity())
+        return false;
+    return true;
+}
 
-#if ENABLE(FILTERS_LEVEL_2)
-    if (m_rareNonInheritedData->backdropFilter != other.m_rareNonInheritedData->backdropFilter) {
-        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
-        // Don't return; keep looking for another change.
-    }
-#endif
+static bool rareNonInheritedDataChangeRequiresRepaint(const StyleRareNonInheritedData& first, const StyleRareNonInheritedData& second, OptionSet<StyleDifferenceContextSensitiveProperty>& changedContextSensitiveProperties)
+{
+    if (first.userDrag != second.userDrag
+        || first.borderFit != second.borderFit
+        || first.objectFit != second.objectFit
+        || first.objectPosition != second.objectPosition)
+        return true;
+
+    if (first.isNotFinal != second.isNotFinal)
+        return true;
 
-    if (m_rareNonInheritedData->mask != other.m_rareNonInheritedData->mask
-        || m_rareNonInheritedData->maskBoxImage != other.m_rareNonInheritedData->maskBoxImage)
+    if (first.shapeOutside != second.shapeOutside)
         return true;
 
+    // FIXME: this should probably be moved to changeRequiresLayerRepaint().
+    if (first.clipPath != second.clipPath) {
+        changedContextSensitiveProperties.add(StyleDifferenceContextSensitiveProperty::ClipPath);
+        // Don't return true; keep looking for another change.
+    }
+
     return false;
 }
 
-bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
+static bool rareInheritedDataChangeRequiresRepaint(const StyleRareInheritedData& first, const StyleRareInheritedData& second)
 {
+    return first.userModify != second.userModify
+        || first.userSelect != second.userSelect
+        || first.appleColorFilter != second.appleColorFilter
+        || first.imageRendering != second.imageRendering
+#if ENABLE(DARK_MODE_CSS)
+        || first.supportedColorSchemes != second.supportedColorSchemes
+#endif
+    ;
+}
+
+bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>& 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_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)
+        || !m_backgroundData->isEquivalentForPainting(*other.m_backgroundData))
         return true;
 
-    if (m_rareNonInheritedData->shapeOutside != other.m_rareNonInheritedData->shapeOutside)
+    if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()
+        && rareNonInheritedDataChangeRequiresRepaint(*m_rareNonInheritedData, *other.m_rareNonInheritedData, changedContextSensitiveProperties))
         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.
-    }
+    if (m_rareInheritedData.ptr() != other.m_rareInheritedData.ptr()
+        && rareInheritedDataChangeRequiresRepaint(*m_rareInheritedData, *other.m_rareInheritedData))
+        return true;
 
     return false;
 }
 
-bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle& other, unsigned&) const
+bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>&) const
 {
     if (m_inheritedData->color != other.m_inheritedData->color
         || m_inheritedFlags.textDecorations != other.m_inheritedFlags.textDecorations
@@ -883,15 +997,17 @@ bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle
         || 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->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
+bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>&) const
 {
-    if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
+    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
@@ -903,59 +1019,59 @@ bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle& other, unsig
     return false;
 }
 
-StyleDifference RenderStyle::diff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
+StyleDifference RenderStyle::diff(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>& changedContextSensitiveProperties) const
 {
-    changedContextSensitiveProperties = ContextSensitivePropertyNone;
+    changedContextSensitiveProperties = OptionSet<StyleDifferenceContextSensitiveProperty>();
 
-    StyleDifference svgChange = StyleDifferenceEqual;
+    StyleDifference svgChange = StyleDifference::Equal;
     if (m_svgStyle != other.m_svgStyle) {
         svgChange = m_svgStyle->diff(other.m_svgStyle.get());
-        if (svgChange == StyleDifferenceLayout)
+        if (svgChange == StyleDifference::Layout)
             return svgChange;
     }
 
     if (changeRequiresLayout(other, changedContextSensitiveProperties))
-        return StyleDifferenceLayout;
+        return StyleDifference::Layout;
 
-    // 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)
+    // SVGRenderStyle::diff() might have returned StyleDifference::Repaint, eg. if fill changes.
+    // If eg. the font-size changed at the same time, we're not allowed to return StyleDifference::Repaint,
+    // but have to return StyleDifference::Layout, that's why  this if branch comes after all branches
+    // that are relevant for SVG and might return StyleDifference::Layout.
+    if (svgChange != StyleDifference::Equal)
         return svgChange;
 
     if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
-        return StyleDifferenceLayoutPositionedMovementOnly;
+        return StyleDifference::LayoutPositionedMovementOnly;
 
     if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
-        return StyleDifferenceRepaintLayer;
+        return StyleDifference::RepaintLayer;
 
     if (changeRequiresRepaint(other, changedContextSensitiveProperties))
-        return StyleDifferenceRepaint;
+        return StyleDifference::Repaint;
 
     if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
-        return StyleDifferenceRecompositeLayer;
+        return StyleDifference::RecompositeLayer;
 
     if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
-        return StyleDifferenceRepaintIfTextOrBorderOrOutline;
+        return StyleDifference::RepaintIfTextOrBorderOrOutline;
 
     // 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;
+    return StyleDifference::Equal;
 }
 
 bool RenderStyle::diffRequiresLayerRepaint(const RenderStyle& style, bool isComposited) const
 {
-    unsigned changedContextSensitiveProperties = 0;
+    OptionSet<StyleDifferenceContextSensitiveProperty> changedContextSensitiveProperties;
 
     if (changeRequiresRepaint(style, changedContextSensitiveProperties))
         return true;
 
     if (isComposited && changeRequiresLayerRepaint(style, changedContextSensitiveProperties))
-        return changedContextSensitiveProperties & ContextSensitivePropertyClipRect;
+        return changedContextSensitiveProperties.contains(StyleDifferenceContextSensitiveProperty::ClipRect);
 
     return false;
 }
@@ -1114,24 +1230,20 @@ void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRec
 {
     auto& operations = m_rareNonInheritedData->transform->operations.operations();
     bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
-
-    float offsetX = transformOriginX().isPercent() ? boundingBox.x() : 0;
-    float offsetY = transformOriginY().isPercent() ? boundingBox.y() : 0;
-
+    
+    FloatPoint3D originTranslate;
     if (applyTransformOrigin) {
-        transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
-                              floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
-                              transformOriginZ());
+        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(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
-                              -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
-                              -transformOriginZ());
-    }
+    if (applyTransformOrigin)
+        transform.translate3d(-originTranslate.x(), -originTranslate.y(), -originTranslate.z());
 }
 
 void RenderStyle::setPageScaleTransform(float scale)
@@ -1181,7 +1293,10 @@ static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSiz
     };
 }
 
-StyleImage* RenderStyle::listStyleImage() const { return m_rareInheritedData->listStyleImage.get(); }
+StyleImage* RenderStyle::listStyleImage() const
+{
+    return m_rareInheritedData->listStyleImage.get();
+}
 
 void RenderStyle::setListStyleImage(RefPtr<StyleImage>&& v)
 {
@@ -1266,7 +1381,7 @@ RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
 static bool allLayersAreFixed(const FillLayer& layers)
 {
     for (auto* layer = &layers; layer; layer = layer->next()) {
-        if (!(layer->image() && layer->attachment() == FixedBackgroundAttachment))
+        if (!(layer->image() && layer->attachment() == FillAttachment::FixedBackground))
             return false;
     }
     return true;
@@ -1290,16 +1405,9 @@ CounterDirectiveMap& RenderStyle::accessCounterDirectives()
     return *map;
 }
 
-const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
-{
-    if (const CounterDirectiveMap* directives = counterDirectives())
-        return directives->get(identifier);
-    return CounterDirectives();
-}
-
 const AtomicString& RenderStyle::hyphenString() const
 {
-    ASSERT(hyphens() != HyphensNone);
+    ASSERT(hyphens() != Hyphens::None);
 
     auto& hyphenationString = m_rareInheritedData->hyphenationString;
     if (!hyphenationString.isNull())
@@ -1314,42 +1422,42 @@ const AtomicString& RenderStyle::hyphenString() const
 const AtomicString& RenderStyle::textEmphasisMarkString() const
 {
     switch (textEmphasisMark()) {
-    case TextEmphasisMarkNone:
-        return nullAtom;
-    case TextEmphasisMarkCustom:
+    case TextEmphasisMark::None:
+        return nullAtom();
+    case TextEmphasisMark::Custom:
         return textEmphasisCustomMark();
-    case TextEmphasisMarkDot: {
+    case TextEmphasisMark::Dot: {
         static NeverDestroyed<AtomicString> filledDotString(&bullet, 1);
         static NeverDestroyed<AtomicString> openDotString(&whiteBullet, 1);
-        return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
+        return textEmphasisFill() == TextEmphasisFill::Filled ? filledDotString : openDotString;
     }
-    case TextEmphasisMarkCircle: {
+    case TextEmphasisMark::Circle: {
         static NeverDestroyed<AtomicString> filledCircleString(&blackCircle, 1);
         static NeverDestroyed<AtomicString> openCircleString(&whiteCircle, 1);
-        return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
+        return textEmphasisFill() == TextEmphasisFill::Filled ? filledCircleString : openCircleString;
     }
-    case TextEmphasisMarkDoubleCircle: {
+    case TextEmphasisMark::DoubleCircle: {
         static NeverDestroyed<AtomicString> filledDoubleCircleString(&fisheye, 1);
         static NeverDestroyed<AtomicString> openDoubleCircleString(&bullseye, 1);
-        return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
+        return textEmphasisFill() == TextEmphasisFill::Filled ? filledDoubleCircleString : openDoubleCircleString;
     }
-    case TextEmphasisMarkTriangle: {
+    case TextEmphasisMark::Triangle: {
         static NeverDestroyed<AtomicString> filledTriangleString(&blackUpPointingTriangle, 1);
         static NeverDestroyed<AtomicString> openTriangleString(&whiteUpPointingTriangle, 1);
-        return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
+        return textEmphasisFill() == TextEmphasisFill::Filled ? filledTriangleString : openTriangleString;
     }
-    case TextEmphasisMarkSesame: {
+    case TextEmphasisMark::Sesame: {
         static NeverDestroyed<AtomicString> filledSesameString(&sesameDot, 1);
         static NeverDestroyed<AtomicString> openSesameString(&whiteSesameDot, 1);
-        return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
+        return textEmphasisFill() == TextEmphasisFill::Filled ? filledSesameString : openSesameString;
     }
-    case TextEmphasisMarkAuto:
+    case TextEmphasisMark::Auto:
         ASSERT_NOT_REACHED();
-        return nullAtom;
+        return nullAtom();
     }
 
     ASSERT_NOT_REACHED();
-    return nullAtom;
+    return nullAtom();
 }
 
 #if ENABLE(DASHBOARD_SUPPORT)
@@ -1483,9 +1591,9 @@ float RenderStyle::computedFontSize() const
     return fontDescription().computedSize();
 }
 
-int RenderStyle::fontSize() const
+unsigned RenderStyle::computedFontPixelSize() const
 {
-    return m_inheritedData->fontCascade.pixelSize();
+    return fontDescription().computedPixelSize();
 }
 
 const Length& RenderStyle::wordSpacing() const
@@ -1498,12 +1606,12 @@ float RenderStyle::letterSpacing() const
     return m_inheritedData->fontCascade.letterSpacing();
 }
 
-bool RenderStyle::setFontDescription(const FontCascadeDescription& description)
+bool RenderStyle::setFontDescription(FontCascadeDescription&& description)
 {
     if (m_inheritedData->fontCascade.fontDescription() == description)
         return false;
     auto& cascade = m_inheritedData.access().fontCascade;
-    cascade = { description, cascade.letterSpacing(), cascade.wordSpacing() };
+    cascade = { WTFMove(description), cascade.letterSpacing(), cascade.wordSpacing() };
     return true;
 }
 
@@ -1544,7 +1652,7 @@ int RenderStyle::computedLineHeight() const
         return fontMetrics().lineSpacing();
 
     if (lh.isPercentOrCalculated())
-        return minimumValueForLength(lh, fontSize());
+        return minimumValueForLength(lh, computedFontPixelSize());
 
     return clampTo<int>(lh.value());
 }
@@ -1592,7 +1700,7 @@ void RenderStyle::setFontSize(float size)
     description.setSpecifiedSize(size);
     description.setComputedSize(size);
 
-    setFontDescription(description);
+    setFontDescription(WTFMove(description));
     fontCascade().update(currentFontSelector);
 }
 
@@ -1603,11 +1711,41 @@ void RenderStyle::setFontVariationSettings(FontVariationSettings settings)
     auto description = fontDescription();
     description.setVariationSettings(WTFMove(settings));
 
-    setFontDescription(description);
+    setFontDescription(WTFMove(description));
     fontCascade().update(currentFontSelector);
 }
 #endif
 
+void RenderStyle::setFontWeight(FontSelectionValue value)
+{
+    FontSelector* currentFontSelector = fontCascade().fontSelector();
+    auto description = fontDescription();
+    description.setWeight(value);
+
+    setFontDescription(WTFMove(description));
+    fontCascade().update(currentFontSelector);
+}
+
+void RenderStyle::setFontStretch(FontSelectionValue value)
+{
+    FontSelector* currentFontSelector = fontCascade().fontSelector();
+    auto description = fontDescription();
+    description.setStretch(value);
+
+    setFontDescription(WTFMove(description));
+    fontCascade().update(currentFontSelector);
+}
+
+void RenderStyle::setFontItalic(std::optional<FontSelectionValue> value)
+{
+    FontSelector* currentFontSelector = fontCascade().fontSelector();
+    auto description = fontDescription();
+    description.setItalic(value);
+
+    setFontDescription(WTFMove(description));
+    fontCascade().update(currentFontSelector);
+}
+
 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
 {
     top = 0;
@@ -1645,7 +1783,7 @@ LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) cons
         left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
     }
 
-    return LayoutBoxExtent(top, right, bottom, left);
+    return LayoutBoxExtent(WTFMove(top), WTFMove(right), WTFMove(bottom), WTFMove(left));
 }
 
 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
@@ -1678,10 +1816,10 @@ void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &
     }
 }
 
-Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
+Color RenderStyle::colorIncludingFallback(CSSPropertyID colorProperty, bool visitedLink) const
 {
     Color result;
-    EBorderStyle borderStyle = BNONE;
+    BorderStyle borderStyle = BorderStyle::None;
     switch (colorProperty) {
     case CSSPropertyBackgroundColor:
         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
@@ -1701,6 +1839,9 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
         borderStyle = borderBottomStyle();
         break;
+    case CSSPropertyCaretColor:
+        result = visitedLink ? visitedLinkCaretColor() : caretColor();
+        break;
     case CSSPropertyColor:
         result = visitedLink ? visitedLinkColor() : color();
         break;
@@ -1710,7 +1851,7 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
     case CSSPropertyColumnRuleColor:
         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
         break;
-    case CSSPropertyWebkitTextDecorationColor:
+    case CSSPropertyTextDecorationColor:
         // Text decoration color fallback is handled in RenderObject::decorationColor.
         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
     case CSSPropertyWebkitTextEmphasisColor:
@@ -1722,13 +1863,16 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
     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))
+        if (!visitedLink && (borderStyle == BorderStyle::Inset || borderStyle == BorderStyle::Outset || borderStyle == BorderStyle::Ridge || borderStyle == BorderStyle::Groove))
             result = Color(238, 238, 238);
         else
             result = visitedLink ? visitedLinkColor() : color();
@@ -1736,16 +1880,16 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
     return result;
 }
 
-Color RenderStyle::visitedDependentColor(int colorProperty) const
+Color RenderStyle::visitedDependentColor(CSSPropertyID colorProperty) const
 {
     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
-    if (insideLink() != InsideVisitedLink)
+    if (insideLink() != InsideLink::InsideVisited)
         return unvisitedColor;
 
     Color visitedColor = colorIncludingFallback(colorProperty, true);
 
     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
-    if (colorProperty == CSSPropertyWebkitTextDecorationColor)
+    if (colorProperty == CSSPropertyTextDecorationColor)
         return visitedColor;
 
     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
@@ -1760,6 +1904,21 @@ Color RenderStyle::visitedDependentColor(int colorProperty) const
     return visitedColor.colorWithAlpha(unvisitedColor.alphaAsFloat());
 }
 
+Color RenderStyle::visitedDependentColorWithColorFilter(CSSPropertyID colorProperty) const
+{
+    if (!hasAppleColorFilter())
+        return visitedDependentColor(colorProperty);
+
+    return colorByApplyingColorFilter(visitedDependentColor(colorProperty));
+}
+
+Color RenderStyle::colorByApplyingColorFilter(const Color& color) const
+{
+    Color transformedColor = color;
+    appleColorFilter().transformColor(transformedColor);
+    return transformedColor;
+}
+
 const BorderValue& RenderStyle::borderBefore() const
 {
     switch (writingMode()) {
@@ -1885,11 +2044,11 @@ void RenderStyle::setMarginEnd(Length&& margin)
 TextEmphasisMark RenderStyle::textEmphasisMark() const
 {
     auto mark = static_cast<TextEmphasisMark>(m_rareInheritedData->textEmphasisMark);
-    if (mark != TextEmphasisMarkAuto)
+    if (mark != TextEmphasisMark::Auto)
         return mark;
     if (isHorizontalWritingMode())
-        return TextEmphasisMarkDot;
-    return TextEmphasisMarkSesame;
+        return TextEmphasisMark::Dot;
+    return TextEmphasisMark::Sesame;
 }
 
 #if ENABLE(TOUCH_EVENTS)
@@ -1914,18 +2073,18 @@ std::pair<FontOrientation, NonCJKGlyphOrientation> RenderStyle::fontAndGlyphOrie
     // FIXME: TextOrientationSideways should map to sideways-left in vertical-lr, which is not supported yet.
 
     if (isHorizontalWritingMode())
-        return { Horizontal, NonCJKGlyphOrientation::Mixed };
+        return { FontOrientation::Horizontal, NonCJKGlyphOrientation::Mixed };
 
     switch (textOrientation()) {
     case TextOrientation::Mixed:
-        return { Vertical, NonCJKGlyphOrientation::Mixed };
+        return { FontOrientation::Vertical, NonCJKGlyphOrientation::Mixed };
     case TextOrientation::Upright:
-        return { Vertical, NonCJKGlyphOrientation::Upright };
+        return { FontOrientation::Vertical, NonCJKGlyphOrientation::Upright };
     case TextOrientation::Sideways:
-        return { Horizontal, NonCJKGlyphOrientation::Mixed };
+        return { FontOrientation::Horizontal, NonCJKGlyphOrientation::Mixed };
     default:
         ASSERT_NOT_REACHED();
-        return { Horizontal, NonCJKGlyphOrientation::Mixed };
+        return { FontOrientation::Horizontal, NonCJKGlyphOrientation::Mixed };
     }
 }
 
@@ -1962,36 +2121,36 @@ void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& pagi
     if (paginationMode == Pagination::Unpaginated)
         return;
     
-    setColumnFill(ColumnFillAuto);
+    setColumnFill(ColumnFill::Auto);
     
     switch (paginationMode) {
     case Pagination::LeftToRightPaginated:
-        setColumnAxis(HorizontalColumnAxis);
+        setColumnAxis(ColumnAxis::Horizontal);
         if (isHorizontalWritingMode())
-            setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
+            setColumnProgression(isLeftToRightDirection() ? ColumnProgression::Normal : ColumnProgression::Reverse);
         else
-            setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
+            setColumnProgression(isFlippedBlocksWritingMode() ? ColumnProgression::Reverse : ColumnProgression::Normal);
         break;
     case Pagination::RightToLeftPaginated:
-        setColumnAxis(HorizontalColumnAxis);
+        setColumnAxis(ColumnAxis::Horizontal);
         if (isHorizontalWritingMode())
-            setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
+            setColumnProgression(isLeftToRightDirection() ? ColumnProgression::Reverse : ColumnProgression::Normal);
         else
-            setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
+            setColumnProgression(isFlippedBlocksWritingMode() ? ColumnProgression::Normal : ColumnProgression::Reverse);
         break;
     case Pagination::TopToBottomPaginated:
-        setColumnAxis(VerticalColumnAxis);
+        setColumnAxis(ColumnAxis::Vertical);
         if (isHorizontalWritingMode())
-            setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
+            setColumnProgression(isFlippedBlocksWritingMode() ? ColumnProgression::Reverse : ColumnProgression::Normal);
         else
-            setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
+            setColumnProgression(isLeftToRightDirection() ? ColumnProgression::Normal : ColumnProgression::Reverse);
         break;
     case Pagination::BottomToTopPaginated:
-        setColumnAxis(VerticalColumnAxis);
+        setColumnAxis(ColumnAxis::Vertical);
         if (isHorizontalWritingMode())
-            setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
+            setColumnProgression(isFlippedBlocksWritingMode() ? ColumnProgression::Normal : ColumnProgression::Reverse);
         else
-            setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
+            setColumnProgression(isLeftToRightDirection() ? ColumnProgression::Reverse : ColumnProgression::Normal);
         break;
     case Pagination::Unpaginated:
         ASSERT_NOT_REACHED();
@@ -2141,62 +2300,20 @@ bool RenderStyle::hasReferenceFilterOnly() const
     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)
+    if (m_backgroundData->outline.style() == BorderStyle::None)
         return 0;
-    if (outlineStyleIsAuto())
+    if (outlineStyleIsAuto() == OutlineIsAuto::On)
         return std::max(m_backgroundData->outline.width(), RenderTheme::platformFocusRingWidth());
     return m_backgroundData->outline.width();
 }
 
 float RenderStyle::outlineOffset() const
 {
-    if (m_backgroundData->outline.style() == BNONE)
+    if (m_backgroundData->outline.style() == BorderStyle::None)
         return 0;
-    if (outlineStyleIsAuto())
+    if (outlineStyleIsAuto() == OutlineIsAuto::On)
         return (m_backgroundData->outline.offset() + RenderTheme::platformFocusRingOffset(outlineWidth()));
     return m_backgroundData->outline.offset();
 }
@@ -2217,4 +2334,85 @@ void RenderStyle::setDashboardRegion(int type, const String& label, Length&& top
 
 #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