diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/style/RenderStyle.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/rendering/style/RenderStyle.cpp')
-rw-r--r-- | Source/WebCore/rendering/style/RenderStyle.cpp | 2007 |
1 files changed, 1176 insertions, 831 deletions
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp index fffd1c19f..eb4447957 100644 --- a/Source/WebCore/rendering/style/RenderStyle.cpp +++ b/Source/WebCore/rendering/style/RenderStyle.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * 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 @@ -24,217 +24,302 @@ #include "RenderStyle.h" #include "ContentData.h" -#include "CursorList.h" +#include "CSSCustomPropertyValue.h" +#include "CSSParser.h" #include "CSSPropertyNames.h" -#include "Font.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" -#if ENABLE(TOUCH_EVENTS) -#include "RenderTheme.h" -#endif +#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(IOS_TEXT_AUTOSIZING) -#include <wtf/text/StringHash.h> -#endif - #if ENABLE(TEXT_AUTOSIZING) -#include "TextAutosizer.h" +#include <wtf/text/StringHash.h> #endif namespace WebCore { struct SameSizeAsBorderValue { - RGBA32 m_color; - unsigned m_width; + float m_width; + Color m_color; + int m_restBits; }; COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow); -struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> { +struct SameSizeAsRenderStyle { void* dataRefs[7]; void* ownPtrs[1]; -#if ENABLE(SVG) void* dataRefSvgStyle; -#endif struct InheritedFlags { unsigned m_bitfields[2]; - } inherited_flags; + } m_inheritedFlags; struct NonInheritedFlags { - unsigned m_bitfields[2]; - } noninherited_flags; + uint64_t m_flags; + } m_nonInheritedFlags; +#if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS) + bool deletionCheck; +#endif }; COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small); -inline RenderStyle& defaultStyle() +RenderStyle& RenderStyle::defaultStyle() { - static RenderStyle& style = RenderStyle::createDefaultStyle().leakRef(); + static NeverDestroyed<RenderStyle> style { CreateDefaultStyle }; return style; } -PassRef<RenderStyle> RenderStyle::create() +RenderStyle RenderStyle::create() { - return adoptRef(*new RenderStyle()); + return clone(defaultStyle()); } -PassRef<RenderStyle> RenderStyle::createDefaultStyle() +std::unique_ptr<RenderStyle> RenderStyle::createPtr() { - return adoptRef(*new RenderStyle(true)); + return clonePtr(defaultStyle()); } -PassRef<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display) +RenderStyle RenderStyle::clone(const RenderStyle& style) { - auto newStyle = RenderStyle::create(); - newStyle.get().inheritFrom(parentStyle); - newStyle.get().inheritUnicodeBidiFrom(parentStyle); - newStyle.get().setDisplay(display); - return newStyle; + return RenderStyle(style, Clone); } -PassRef<RenderStyle> RenderStyle::clone(const RenderStyle* other) +std::unique_ptr<RenderStyle> RenderStyle::clonePtr(const RenderStyle& style) { - return adoptRef(*new RenderStyle(*other)); + return std::make_unique<RenderStyle>(style, Clone); } -PassRef<RenderStyle> RenderStyle::createStyleInheritingFromPseudoStyle(const RenderStyle& pseudoStyle) +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); - // Images are special and must inherit the pseudoStyle so the width and height of - // the pseudo element doesn't change the size of the image. In all other cases we - // can just share the style. - auto style = RenderStyle::create(); - style.get().inheritFrom(&pseudoStyle); + auto style = create(); + style.inheritFrom(pseudoStyle); return style; } -ALWAYS_INLINE RenderStyle::RenderStyle() - : m_box(defaultStyle().m_box) - , visual(defaultStyle().visual) - , m_background(defaultStyle().m_background) - , surround(defaultStyle().surround) - , rareNonInheritedData(defaultStyle().rareNonInheritedData) - , rareInheritedData(defaultStyle().rareInheritedData) - , inherited(defaultStyle().inherited) -#if ENABLE(SVG) - , m_svgStyle(defaultStyle().m_svgStyle) +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(); + + 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) { - setBitDefaults(); // Would it be faster to copy this from the default style? - COMPILE_ASSERT((sizeof(InheritedFlags) <= 8), InheritedFlags_does_not_grow); - COMPILE_ASSERT((sizeof(NonInheritedFlags) <= 8), NonInheritedFlags_does_not_grow); + return RenderStyle { *this, WTFMove(newStyle) }; } -ALWAYS_INLINE RenderStyle::RenderStyle(bool) - : m_box(StyleBoxData::create()) - , visual(StyleVisualData::create()) - , m_background(StyleBackgroundData::create()) - , surround(StyleSurroundData::create()) - , rareNonInheritedData(StyleRareNonInheritedData::create()) - , rareInheritedData(StyleRareInheritedData::create()) - , inherited(StyleInheritedData::create()) -#if ENABLE(SVG) - , m_svgStyle(SVGRenderStyle::create()) -#endif +bool RenderStyle::isCSSGridLayoutEnabled() { - setBitDefaults(); + return RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled(); } -ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o) - : RefCounted<RenderStyle>() - , m_box(o.m_box) - , visual(o.visual) - , m_background(o.m_background) - , surround(o.surround) - , rareNonInheritedData(o.rareNonInheritedData) - , rareInheritedData(o.rareInheritedData) - , inherited(o.inherited) -#if ENABLE(SVG) - , m_svgStyle(o.m_svgStyle) -#endif - , inherited_flags(o.inherited_flags) - , noninherited_flags(o.noninherited_flags) +static StyleSelfAlignmentData resolvedSelfAlignment(const StyleSelfAlignmentData& value, ItemPosition normalValueBehavior) { + ASSERT(value.position() != ItemPositionAuto); + if (value.position() == ItemPositionNormal) + return { normalValueBehavior, OverflowAlignmentDefault }; + return value; } -void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary) +StyleSelfAlignmentData RenderStyle::resolvedAlignItems(ItemPosition normalValueBehaviour) const { - if (isAtShadowBoundary == AtShadowBoundary) { - // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable - EUserModify currentUserModify = userModify(); - rareInheritedData = inheritParent->rareInheritedData; - setUserModify(currentUserModify); - } else - rareInheritedData = inheritParent->rareInheritedData; - inherited = inheritParent->inherited; - inherited_flags = inheritParent->inherited_flags; -#if ENABLE(SVG) - if (m_svgStyle != inheritParent->m_svgStyle) - m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get()); -#endif + return resolvedSelfAlignment(alignItems(), normalValueBehaviour); } -void RenderStyle::copyNonInheritedFrom(const RenderStyle* other) -{ - m_box = other->m_box; - visual = other->visual; - m_background = other->m_background; - surround = other->surround; - rareNonInheritedData = other->rareNonInheritedData; - // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data. - noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay; - noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay; - noninherited_flags._overflowX = other->noninherited_flags._overflowX; - noninherited_flags._overflowY = other->noninherited_flags._overflowY; - noninherited_flags._vertical_align = other->noninherited_flags._vertical_align; - noninherited_flags._clear = other->noninherited_flags._clear; - noninherited_flags._position = other->noninherited_flags._position; - noninherited_flags._floating = other->noninherited_flags._floating; - noninherited_flags._table_layout = other->noninherited_flags._table_layout; - noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi; - noninherited_flags._page_break_before = other->noninherited_flags._page_break_before; - noninherited_flags._page_break_after = other->noninherited_flags._page_break_after; - noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside; - noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance; -#if ENABLE(SVG) - if (m_svgStyle != other->m_svgStyle) - m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get()); -#endif - ASSERT(zoom() == initialZoom()); +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); } -bool RenderStyle::operator==(const RenderStyle& o) const +StyleSelfAlignmentData RenderStyle::resolvedJustifyItems(ItemPosition normalValueBehaviour) const { - // compare everything except the pseudoStyle pointer - return inherited_flags == o.inherited_flags - && noninherited_flags == o.noninherited_flags - && m_box == o.m_box - && visual == o.visual - && m_background == o.m_background - && surround == o.surround - && rareNonInheritedData == o.rareNonInheritedData - && rareInheritedData == o.rareInheritedData - && inherited == o.inherited -#if ENABLE(SVG) - && m_svgStyle == o.m_svgStyle -#endif - ; + // 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 +{ + // 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); +} + +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); } -bool RenderStyle::isStyleAvailable() const +ContentDistributionType RenderStyle::resolvedAlignContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const { - return this != StyleResolver::styleNotYetAvailable(); + 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()); +} + +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 @@ -242,8 +327,7 @@ bool RenderStyle::hasUniquePseudoStyle() const if (!m_cachedPseudoStyles || styleType() != NOPSEUDO) return false; - for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { - RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); + for (auto& pseudoStyle : *m_cachedPseudoStyles) { if (pseudoStyle->unique()) return true; } @@ -254,33 +338,32 @@ bool RenderStyle::hasUniquePseudoStyle() const RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const { if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size()) - return 0; + return nullptr; if (styleType() != NOPSEUDO) - return 0; + return nullptr; - for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { - RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); + for (auto& pseudoStyle : *m_cachedPseudoStyles) { if (pseudoStyle->styleType() == pid) - return pseudoStyle; + return pseudoStyle.get(); } - return 0; + return nullptr; } -RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo) +RenderStyle* RenderStyle::addCachedPseudoStyle(std::unique_ptr<RenderStyle> pseudo) { if (!pseudo) - return 0; + return nullptr; ASSERT(pseudo->styleType() > NOPSEUDO); RenderStyle* result = pseudo.get(); if (!m_cachedPseudoStyles) - m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache); + m_cachedPseudoStyles = std::make_unique<PseudoStyleCache>(); - m_cachedPseudoStyles->append(pseudo); + m_cachedPseudoStyles->append(WTFMove(pseudo)); return result; } @@ -300,81 +383,76 @@ void RenderStyle::removeCachedPseudoStyle(PseudoId pid) bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const { - return inherited_flags != other->inherited_flags - || inherited != other->inherited -#if ENABLE(SVG) - || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) -#endif - || rareInheritedData != other->rareInheritedData; + return m_inheritedFlags != other->m_inheritedFlags + || m_inheritedData != other->m_inheritedData + || m_svgStyle->inheritedNotEqual(other->m_svgStyle) + || m_rareInheritedData != other->m_rareInheritedData; } -#if ENABLE(IOS_TEXT_AUTOSIZING) -inline unsigned computeFontHash(const Font& font) +#if ENABLE(TEXT_AUTOSIZING) + +static inline unsigned computeFontHash(const FontCascade& font) { - unsigned hashCodes[2] = { - CaseFoldingHash::hash(font.fontDescription().firstFamily().impl()), - static_cast<unsigned>(font.fontDescription().specifiedSize()) - }; - return StringHasher::computeHash(reinterpret_cast<UChar*>(hashCodes), 2 * sizeof(unsigned) / sizeof(UChar)); + IntegerHasher hasher; + hasher.add(ASCIICaseInsensitiveHash::hash(font.fontDescription().firstFamily())); + hasher.add(font.fontDescription().specifiedSize()); + return hasher.hash(); } -uint32_t RenderStyle::hashForTextAutosizing() const +unsigned RenderStyle::hashForTextAutosizing() const { // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>. - uint32_t hash = 0; - - hash ^= rareNonInheritedData->m_appearance; - hash ^= rareNonInheritedData->marginBeforeCollapse; - hash ^= rareNonInheritedData->marginAfterCollapse; - hash ^= rareNonInheritedData->lineClamp.value(); - hash ^= rareInheritedData->overflowWrap; - hash ^= rareInheritedData->nbspMode; - hash ^= rareInheritedData->lineBreak; - hash ^= WTF::FloatHash<float>::hash(inherited->specifiedLineHeight.value()); - hash ^= computeFontHash(inherited->font); - hash ^= inherited->horizontal_border_spacing; - hash ^= inherited->vertical_border_spacing; - hash ^= inherited_flags._box_direction; - hash ^= inherited_flags.m_rtlOrdering; - hash ^= noninherited_flags._position; - hash ^= noninherited_flags._floating; - hash ^= rareNonInheritedData->textOverflow; - hash ^= rareInheritedData->textSecurity; + 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 rareNonInheritedData->m_appearance == other->rareNonInheritedData->m_appearance - && rareNonInheritedData->marginBeforeCollapse == other->rareNonInheritedData->marginBeforeCollapse - && rareNonInheritedData->marginAfterCollapse == other->rareNonInheritedData->marginAfterCollapse - && rareNonInheritedData->lineClamp == other->rareNonInheritedData->lineClamp - && rareInheritedData->textSizeAdjust == other->rareInheritedData->textSizeAdjust - && rareInheritedData->overflowWrap == other->rareInheritedData->overflowWrap - && rareInheritedData->nbspMode == other->rareInheritedData->nbspMode - && rareInheritedData->lineBreak == other->rareInheritedData->lineBreak - && rareInheritedData->textSecurity == other->rareInheritedData->textSecurity - && inherited->specifiedLineHeight == other->inherited->specifiedLineHeight - && inherited->font.equalForTextAutoSizing(other->inherited->font) - && inherited->horizontal_border_spacing == other->inherited->horizontal_border_spacing - && inherited->vertical_border_spacing == other->inherited->vertical_border_spacing - && inherited_flags._box_direction == other->inherited_flags._box_direction - && inherited_flags.m_rtlOrdering == other->inherited_flags.m_rtlOrdering - && noninherited_flags._position == other->noninherited_flags._position - && noninherited_flags._floating == other->noninherited_flags._floating - && rareNonInheritedData->textOverflow == other->rareNonInheritedData->textOverflow; -} -#endif // ENABLE(IOS_TEXT_AUTOSIZING) +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 inherited_flags == other->inherited_flags - && inherited.get() == other->inherited.get() -#if ENABLE(SVG) + return m_inheritedFlags == other->m_inheritedFlags + && m_inheritedData.get() == other->m_inheritedData.get() && m_svgStyle.get() == other->m_svgStyle.get() -#endif - && rareInheritedData.get() == other->rareInheritedData.get(); + && m_rareInheritedData.get() == other->m_rareInheritedData.get(); } static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width) @@ -404,250 +482,254 @@ static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, return true; } -bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const +inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const { - if (m_box->width() != other->m_box->width() - || m_box->minWidth() != other->m_box->minWidth() - || m_box->maxWidth() != other->m_box->maxWidth() - || m_box->height() != other->m_box->height() - || m_box->minHeight() != other->m_box->minHeight() - || m_box->maxHeight() != other->m_box->maxHeight()) + if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get() + && !arePointingToEqualData(m_rareNonInheritedData->boxShadow, other.m_rareNonInheritedData->boxShadow)) return true; - if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align) + if (m_rareInheritedData.get() != other.m_rareInheritedData.get() + && !arePointingToEqualData(m_rareInheritedData->textShadow, other.m_rareInheritedData->textShadow)) return true; - if (m_box->boxSizing() != other->m_box->boxSizing()) + 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; +} - if (surround->margin != other->surround->margin) +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 (surround->padding != other->surround->padding) + if (m_boxData->verticalAlign() != other.m_boxData->verticalAlign() || m_nonInheritedFlags.verticalAlign() != other.m_nonInheritedFlags.verticalAlign()) return true; - if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { - if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance - || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse - || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse - || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp - || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow) - return true; + if (m_boxData->boxSizing() != other.m_boxData->boxSizing()) + return true; - if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment) - return true; + if (m_surroundData->margin != other.m_surroundData->margin) + return true; - if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow - || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough) - return true; + if (m_surroundData->padding != other.m_surroundData->padding) + return true; -#if ENABLE(CSS_SHAPES) - if (rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin - || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding) - return true; -#endif + // FIXME: We should add an optimized form of layout that just recomputes visual overflow. + if (changeAffectsVisualOverflow(other)) + return true; - if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get() - && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get()) + 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 (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get() - && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get()) + if (m_rareNonInheritedData->regionFragment != other.m_rareNonInheritedData->regionFragment) return true; - if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order - || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent - || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems - || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf - || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent) + + if (m_rareNonInheritedData->shapeMargin != other.m_rareNonInheritedData->shapeMargin) return true; - // FIXME: We should add an optimized form of layout that just recomputes visual overflow. - if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get())) + if (m_rareNonInheritedData->deprecatedFlexibleBox != other.m_rareNonInheritedData->deprecatedFlexibleBox) return true; - if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get())) + if (m_rareNonInheritedData->flexibleBox != other.m_rareNonInheritedData->flexibleBox) return true; - if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() - && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get()) + 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 (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() - && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) { -#if USE(ACCELERATED_COMPOSITING) - changedContextSensitiveProperties |= ContextSensitivePropertyTransform; - // Don't return; keep looking for another change -#else - UNUSED_PARAM(changedContextSensitiveProperties); + if (!arePointingToEqualData(m_rareNonInheritedData->boxReflect, other.m_rareNonInheritedData->boxReflect)) return true; -#endif - } - if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get() - || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get()) + if (m_rareNonInheritedData->multiCol != other.m_rareNonInheritedData->multiCol) return true; -#if !USE(ACCELERATED_COMPOSITING) - if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { - if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D - || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility - || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective - || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX - || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY) + 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 + } } -#endif + + 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 (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions) + if (m_rareNonInheritedData->dashboardRegions != other.m_rareNonInheritedData->dashboardRegions) return true; #endif -#if ENABLE(CSS_SHAPES) - if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside) - return true; -#endif + if (!arePointingToEqualData(m_rareNonInheritedData->willChange, other.m_rareNonInheritedData->willChange)) { + changedContextSensitiveProperties |= ContextSensitivePropertyWillChange; + // Don't return; keep looking for another change + } } - if (rareInheritedData.get() != other->rareInheritedData.get()) { - if (rareInheritedData->highlight != other->rareInheritedData->highlight - || rareInheritedData->indent != other->rareInheritedData->indent + if (m_rareInheritedData.get() != other.m_rareInheritedData.get()) { + if (m_rareInheritedData->indent != other.m_rareInheritedData->indent #if ENABLE(CSS3_TEXT) - || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast - || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine + || m_rareInheritedData->textAlignLast != other.m_rareInheritedData->textAlignLast + || m_rareInheritedData->textJustify != other.m_rareInheritedData->textJustify + || m_rareInheritedData->textIndentLine != other.m_rareInheritedData->textIndentLine #endif - || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom -#if ENABLE(IOS_TEXT_AUTOSIZING) - || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust + || 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 - || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak - || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap - || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode - || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak - || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity - || rareInheritedData->hyphens != other->rareInheritedData->hyphens - || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore - || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter - || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString - || rareInheritedData->locale != other->rareInheritedData->locale - || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition - || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark - || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition - || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark - || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation - || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize - || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain - || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid + || 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) - || rareInheritedData->m_imageOrientation != other->rareInheritedData->m_imageOrientation + || m_rareInheritedData->imageOrientation != other.m_rareInheritedData->imageOrientation #endif #if ENABLE(CSS_IMAGE_RESOLUTION) - || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource - || rareInheritedData->m_imageResolutionSnap != other->rareInheritedData->m_imageResolutionSnap - || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution + || m_rareInheritedData->imageResolutionSource != other.m_rareInheritedData->imageResolutionSource + || m_rareInheritedData->imageResolutionSnap != other.m_rareInheritedData->imageResolutionSnap + || m_rareInheritedData->imageResolution != other.m_rareInheritedData->imageResolution #endif - || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap - || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign + || 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) - || rareInheritedData->useTouchOverflowScrolling != other->rareInheritedData->useTouchOverflowScrolling + || m_rareInheritedData->useTouchOverflowScrolling != other.m_rareInheritedData->useTouchOverflowScrolling #endif - || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage) - return true; - - if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get())) + || m_rareInheritedData->listStyleImage != other.m_rareInheritedData->listStyleImage) // FIXME: needs arePointingToEqualData()? return true; - if (textStrokeWidth() != other->textStrokeWidth()) + if (textStrokeWidth() != other.textStrokeWidth()) return true; } + if (m_inheritedData->lineHeight != other.m_inheritedData->lineHeight #if ENABLE(TEXT_AUTOSIZING) - if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier) - return true; -#endif - - if (inherited->line_height != other->inherited->line_height -#if ENABLE(IOS_TEXT_AUTOSIZING) - || inherited->specifiedLineHeight != other->inherited->specifiedLineHeight + || m_inheritedData->specifiedLineHeight != other.m_inheritedData->specifiedLineHeight #endif - || inherited->font != other->inherited->font - || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing - || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing - || inherited_flags._box_direction != other->inherited_flags._box_direction - || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering - || noninherited_flags._position != other->noninherited_flags._position - || noninherited_flags._floating != other->noninherited_flags._floating - || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay) + || 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 (((int)noninherited_flags._effectiveDisplay) >= TABLE) { - if (inherited_flags._border_collapse != other->inherited_flags._border_collapse - || inherited_flags._empty_cells != other->inherited_flags._empty_cells - || inherited_flags._caption_side != other->inherited_flags._caption_side - || noninherited_flags._table_layout != other->noninherited_flags._table_layout) + 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 (inherited_flags._border_collapse - && ((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))) + 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 (noninherited_flags._effectiveDisplay == LIST_ITEM) { - if (inherited_flags._list_style_type != other->inherited_flags._list_style_type - || inherited_flags._list_style_position != other->inherited_flags._list_style_position) + if (m_nonInheritedFlags.effectiveDisplay() == LIST_ITEM) { + if (m_inheritedFlags.listStyleType != other.m_inheritedFlags.listStyleType + || m_inheritedFlags.listStylePosition != other.m_inheritedFlags.listStylePosition) return true; } - if (inherited_flags._text_align != other->inherited_flags._text_align - || inherited_flags._text_transform != other->inherited_flags._text_transform - || inherited_flags._direction != other->inherited_flags._direction - || inherited_flags._white_space != other->inherited_flags._white_space - || noninherited_flags._clear != other->noninherited_flags._clear - || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi) + 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 (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode) + if (m_inheritedFlags.writingMode != other.m_inheritedFlags.writingMode) return true; // Check text combine mode. - if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine) + 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 (noninherited_flags._overflowX != other->noninherited_flags._overflowX - || noninherited_flags._overflowY != other->noninherited_flags._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 // only necessitate a repaint. - if (borderLeftWidth() != other->borderLeftWidth() - || borderTopWidth() != other->borderTopWidth() - || borderBottomWidth() != other->borderBottomWidth() - || borderRightWidth() != other->borderRightWidth()) + 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. - const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get(); - const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get(); - if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) + if (!arePointingToEqualData(m_rareNonInheritedData->counterDirectives, other.m_rareNonInheritedData->counterDirectives)) return true; - if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE)) + if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE)) return true; - if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) { + 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). @@ -656,18 +738,19 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& chang return true; } -#if ENABLE(CSS_FILTERS) - if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters()) + 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 - const QuotesData* quotesDataA = rareInheritedData->quotes.get(); - const QuotesData* quotesDataB = other->rareInheritedData->quotes.get(); - if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB))) + if (!arePointingToEqualData(m_rareInheritedData->quotes, other.m_rareInheritedData->quotes)) return true; if (position() != StaticPosition) { - if (surround->offset != other->surround->offset) { + 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). @@ -675,161 +758,183 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& chang return true; // Optimize for the case where a positioned layer is moving but not changing size. - if (!positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width())) + 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 +bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle& other, unsigned&) const { if (position() == StaticPosition) return false; - if (surround->offset != other->surround->offset) { + 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(surround->offset, other->surround->offset, m_box->width())) + 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 +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_box->zIndex() != other->m_box->zIndex() - || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex() - || visual->clip != other->visual->clip - || visual->hasClip != other->visual->hasClip) + if (m_visualData->clip != other.m_visualData->clip || m_visualData->hasClip != other.m_visualData->hasClip) { + changedContextSensitiveProperties |= ContextSensitivePropertyClipRect; return true; + } } #if ENABLE(CSS_COMPOSITING) - if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode) + if (m_rareNonInheritedData->effectiveBlendMode != other.m_rareNonInheritedData->effectiveBlendMode) return true; #endif - if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) { -#if USE(ACCELERATED_COMPOSITING) + if (m_rareNonInheritedData->opacity != other.m_rareNonInheritedData->opacity) { changedContextSensitiveProperties |= ContextSensitivePropertyOpacity; // Don't return; keep looking for another change. -#else - UNUSED_PARAM(changedContextSensitiveProperties); - return true; -#endif } -#if ENABLE(CSS_FILTERS) - if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get() - && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) { -#if USE(ACCELERATED_COMPOSITING) + 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. -#else - return true; -#endif } #endif - if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask - || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage) + if (m_rareNonInheritedData->mask != other.m_rareNonInheritedData->mask + || m_rareNonInheritedData->maskBoxImage != other.m_rareNonInheritedData->maskBoxImage) return true; return false; } -bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const +static bool requiresPainting(const RenderStyle& style) { - if (inherited_flags._visibility != other->inherited_flags._visibility - || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust - || inherited_flags._insideLink != other->inherited_flags._insideLink - || surround->border != other->surround->border - || !m_background->isEquivalentForPainting(*other->m_background) - || rareInheritedData->userModify != other->rareInheritedData->userModify - || rareInheritedData->userSelect != other->rareInheritedData->userSelect - || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag - || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit - || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit - || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering) - return true; + 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 ENABLE(CSS_SHAPES) - // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected - // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout - // the parent container. For sure, I will have to revisit this code, but for now I've added this in order - // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ. - // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991 - if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside) + 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) return true; -#endif - if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath) + 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 +bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle& other, unsigned&) const { - if (inherited->color != other->inherited->color - || inherited_flags._text_decorations != other->inherited_flags._text_decorations - || visual->textDecoration != other->visual->textDecoration - || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle - || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor - || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip - || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor - || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor - || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor - || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill) + 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) return true; return false; } -bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const +bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle& other, unsigned&) const { -#if USE(ACCELERATED_COMPOSITING) - if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { - if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D - || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility - || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective - || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX - || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY) + if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) { + 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; } -#else - UNUSED_PARAM(other); -#endif + return false; } -StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const +StyleDifference RenderStyle::diff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const { changedContextSensitiveProperties = ContextSensitivePropertyNone; -#if ENABLE(SVG) StyleDifference svgChange = StyleDifferenceEqual; - if (m_svgStyle != other->m_svgStyle) { - svgChange = m_svgStyle->diff(other->m_svgStyle.get()); + if (m_svgStyle != other.m_svgStyle) { + svgChange = m_svgStyle->diff(other.m_svgStyle.get()); if (svgChange == StyleDifferenceLayout) return svgChange; } -#endif + + // 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) + return StyleDifferenceLayout; if (changeRequiresLayout(other, changedContextSensitiveProperties)) return StyleDifferenceLayout; -#if ENABLE(SVG) // 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; -#endif if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties)) return StyleDifferenceLayoutPositionedMovementOnly; @@ -840,10 +945,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon if (changeRequiresRepaint(other, changedContextSensitiveProperties)) return StyleDifferenceRepaint; -#if USE(ACCELERATED_COMPOSITING) if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties)) return StyleDifferenceRecompositeLayer; -#endif if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties)) return StyleDifferenceRepaintIfTextOrBorderOrOutline; @@ -856,203 +959,186 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon return StyleDifferenceEqual; } -bool RenderStyle::diffRequiresRepaint(const RenderStyle* style) const +bool RenderStyle::diffRequiresLayerRepaint(const RenderStyle& style, bool isComposited) const { unsigned changedContextSensitiveProperties = 0; - return changeRequiresRepaint(style, changedContextSensitiveProperties); + + 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) +void RenderStyle::setClip(Length&& top, Length&& right, Length&& bottom, Length&& left) { - StyleVisualData* data = visual.access(); - data->clip.m_top = top; - data->clip.m_right = right; - data->clip.m_bottom = bottom; - data->clip.m_left = 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(PassRefPtr<StyleImage> image, const IntPoint& hotSpot) +void RenderStyle::addCursor(RefPtr<StyleImage>&& image, const IntPoint& hotSpot) { - if (!rareInheritedData.access()->cursorData) - rareInheritedData.access()->cursorData = CursorList::create(); - rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot)); + auto& cursorData = m_rareInheritedData.access().cursorData; + if (!cursorData) + cursorData = CursorList::create(); + cursorData->append(CursorData(WTFMove(image), hotSpot)); } -void RenderStyle::setCursorList(PassRefPtr<CursorList> other) +void RenderStyle::setCursorList(RefPtr<CursorList>&& list) { - rareInheritedData.access()->cursorData = other; + m_rareInheritedData.access().cursorData = WTFMove(list); } -void RenderStyle::setQuotes(PassRefPtr<QuotesData> q) +void RenderStyle::setQuotes(RefPtr<QuotesData>&& q) { - if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q)) + if (m_rareInheritedData->quotes == q || (m_rareInheritedData->quotes && q && *m_rareInheritedData->quotes == *q)) return; - rareInheritedData.access()->quotes = q; + 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 (rareInheritedData->cursorData) - rareInheritedData.access()->cursorData = 0; + if (m_rareInheritedData->cursorData) + m_rareInheritedData.access().cursorData = nullptr; } void RenderStyle::clearContent() { - if (rareNonInheritedData->m_content) - rareNonInheritedData.access()->m_content = nullptr; + if (m_rareNonInheritedData->content) + m_rareNonInheritedData.access().content = nullptr; } -void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData) +static inline ContentData& lastContent(ContentData& firstContent) { - auto& content = rareNonInheritedData.access()->m_content; - ContentData* lastContent = content.get(); - while (lastContent && lastContent->next()) - lastContent = lastContent->next(); + auto* lastContent = &firstContent; + for (auto* content = &firstContent; content; content = content->next()) + lastContent = content; + return *lastContent; +} - if (lastContent) - lastContent->setNext(std::move(contentData)); - else - content = std::move(contentData); +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(PassRefPtr<StyleImage> image, bool add) +void RenderStyle::setContent(RefPtr<StyleImage>&& image, bool add) { if (!image) return; - - if (add) { - appendContent(std::make_unique<ImageContentData>(image)); - return; - } - - rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image); - if (!rareNonInheritedData.access()->m_altText.isNull()) - rareNonInheritedData.access()->m_content->setAltText(rareNonInheritedData.access()->m_altText); + setContent(std::make_unique<ImageContentData>(image.releaseNonNull()), add); } void RenderStyle::setContent(const String& string, bool add) { - auto& content = rareNonInheritedData.access()->m_content; - if (add) { - ContentData* lastContent = content.get(); - while (lastContent && lastContent->next()) - lastContent = lastContent->next(); - - if (lastContent) { - // We attempt to merge with the last ContentData if possible. - if (lastContent->isText()) { - TextContentData* textContent = static_cast<TextContentData*>(lastContent); - textContent->setText(textContent->text() + string); - } else - lastContent->setNext(std::make_unique<TextContentData>(string)); - - if (!rareNonInheritedData.access()->m_altText.isNull()) - lastContent->setAltText(rareNonInheritedData.access()->m_altText); - return; + 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); } - - content = std::make_unique<TextContentData>(string); - if (!rareNonInheritedData.access()->m_altText.isNull()) - content->setAltText(rareNonInheritedData.access()->m_altText); } void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add) { if (!counter) return; - - if (add) { - appendContent(std::make_unique<CounterContentData>(std::move(counter))); - return; - } - - rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(std::move(counter)); + setContent(std::make_unique<CounterContentData>(WTFMove(counter)), add); } void RenderStyle::setContent(QuoteType quote, bool add) { - if (add) { - appendContent(std::make_unique<QuoteContentData>(quote)); - return; - } - - rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote); + setContent(std::make_unique<QuoteContentData>(quote), add); } void RenderStyle::setContentAltText(const String& string) { - rareNonInheritedData.access()->m_altText = string; - - if (rareNonInheritedData.access()->m_content) - rareNonInheritedData.access()->m_content->setAltText(string); + auto& data = m_rareNonInheritedData.access(); + data.altText = string; + if (data.content) + data.content->setAltText(string); } const String& RenderStyle::contentAltText() const { - return rareNonInheritedData->m_altText; + return m_rareNonInheritedData->altText; +} + +void RenderStyle::setHasAttrContent() +{ + setUnique(); + SET_VAR(m_rareNonInheritedData, hasAttrContent, true); } -inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin) +static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin) { - // transform-origin brackets the transform with translate operations. - // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant - // in that case. + // 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; - unsigned size = transformOperations.size(); - for (unsigned i = 0; i < size; ++i) { - TransformOperation::OperationType type = transformOperations[i]->type(); - if (type != TransformOperation::TRANSLATE_X + 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 - && type != TransformOperation::TRANSLATE_Z - && type != TransformOperation::TRANSLATE_3D) + && type != TransformOperation::TRANSLATE_Z) return true; } - + return false; } -void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const +void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const { - // FIXME: when subpixel layout is supported (bug 71143) the body of this function could be replaced by - // applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin); - - const Vector<RefPtr<TransformOperation>>& transformOperations = rareNonInheritedData->m_transform->m_operations.operations(); - bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin); + auto& operations = m_rareNonInheritedData->transform->operations.operations(); + bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin); - if (applyTransformOrigin) - transform.translate3d(floatValueForLength(transformOriginX(), borderBoxSize.width()), floatValueForLength(transformOriginY(), borderBoxSize.height()), transformOriginZ()); + float offsetX = transformOriginX().isPercent() ? boundingBox.x() : 0; + float offsetY = transformOriginY().isPercent() ? boundingBox.y() : 0; - unsigned size = transformOperations.size(); - for (unsigned i = 0; i < size; ++i) - transformOperations[i]->apply(transform, borderBoxSize); - - if (applyTransformOrigin) - transform.translate3d(-floatValueForLength(transformOriginX(), borderBoxSize.width()), -floatValueForLength(transformOriginY(), borderBoxSize.height()), -transformOriginZ()); -} - -void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const -{ - const Vector<RefPtr<TransformOperation>>& transformOperations = rareNonInheritedData->m_transform->m_operations.operations(); - bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin); - - float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0; - float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0; - if (applyTransformOrigin) { transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX, floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY, transformOriginZ()); } - - unsigned size = transformOperations.size(); - for (unsigned i = 0; i < size; ++i) - transformOperations[i]->apply(transform, boundingBox.size()); - + + for (auto& operation : operations) + operation->apply(transform, boundingBox.size()); + if (applyTransformOrigin) { transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX, -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY, @@ -1071,101 +1157,96 @@ void RenderStyle::setPageScaleTransform(float scale) setTransformOriginY(Length(0, Fixed)); } -void RenderStyle::setTextShadow(PassOwnPtr<ShadowData> shadowData, bool add) +void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add) { ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal)); - StyleRareInheritedData* rareData = rareInheritedData.access(); + auto& rareData = m_rareInheritedData.access(); if (!add) { - rareData->textShadow = shadowData; + rareData.textShadow = WTFMove(shadowData); return; } - shadowData->setNext(rareData->textShadow.release()); - rareData->textShadow = shadowData; + shadowData->setNext(WTFMove(rareData.textShadow)); + rareData.textShadow = WTFMove(shadowData); } -void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add) +void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add) { - StyleRareNonInheritedData* rareData = rareNonInheritedData.access(); + auto& rareData = m_rareNonInheritedData.access(); if (!add) { - rareData->m_boxShadow = shadowData; + rareData.boxShadow = WTFMove(shadowData); return; } - shadowData->setNext(rareData->m_boxShadow.release()); - rareData->m_boxShadow = shadowData; + shadowData->setNext(WTFMove(rareData.boxShadow)); + rareData.boxShadow = WTFMove(shadowData); } -static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView) +static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size) { - return RoundedRect::Radii( - IntSize(valueForLength(border.topLeft().width(), size.width(), renderView), - valueForLength(border.topLeft().height(), size.height(), renderView)), - IntSize(valueForLength(border.topRight().width(), size.width(), renderView), - valueForLength(border.topRight().height(), size.height(), renderView)), - IntSize(valueForLength(border.bottomLeft().width(), size.width(), renderView), - valueForLength(border.bottomLeft().height(), size.height(), renderView)), - IntSize(valueForLength(border.bottomRight().width(), size.width(), renderView), - valueForLength(border.bottomRight().height(), size.height(), renderView))); + return { + sizeForLengthSize(border.topLeft(), size), + sizeForLengthSize(border.topRight(), size), + sizeForLengthSize(border.bottomLeft(), size), + sizeForLengthSize(border.bottomRight(), size) + }; } -static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii) +StyleImage* RenderStyle::listStyleImage() const { return m_rareInheritedData->listStyleImage.get(); } + +void RenderStyle::setListStyleImage(RefPtr<StyleImage>&& v) { - // Constrain corner radii using CSS3 rules: - // http://www.w3.org/TR/css3-background/#the-border-radius - - float factor = 1; - unsigned radiiSum; - - // top - radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow. - if (radiiSum > static_cast<unsigned>(rect.width())) - factor = std::min(static_cast<float>(rect.width()) / radiiSum, factor); - - // bottom - radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width()); - if (radiiSum > static_cast<unsigned>(rect.width())) - factor = std::min(static_cast<float>(rect.width()) / radiiSum, factor); - - // left - radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height()); - if (radiiSum > static_cast<unsigned>(rect.height())) - factor = std::min(static_cast<float>(rect.height()) / radiiSum, factor); - - // right - radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height()); - if (radiiSum > static_cast<unsigned>(rect.height())) - factor = std::min(static_cast<float>(rect.height()) / radiiSum, factor); - - ASSERT(factor <= 1); - return factor; + if (m_rareInheritedData->listStyleImage != v) + m_rareInheritedData.access().listStyleImage = WTFMove(v); } -StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); } -void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v) +const Color& RenderStyle::color() const { - if (rareInheritedData->listStyleImage != v) - rareInheritedData.access()->listStyleImage = v; + return m_inheritedData->color; } -Color RenderStyle::color() const { return inherited->color; } -Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; } -void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); } -void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); } +const Color& RenderStyle::visitedLinkColor() const +{ + return m_inheritedData->visitedLinkColor; +} -short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; } -short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; } -void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); } -void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); } +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; +} -RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const +float RenderStyle::verticalBorderSpacing() const { - IntRect snappedBorderRect(pixelSnappedIntRect(borderRect)); - RoundedRect roundedRect(snappedBorderRect); + 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(surround->border, snappedBorderRect.size(), renderView); - radii.scale(calcConstraintScaleFor(snappedBorderRect, radii)); + RoundedRect::Radii radii = calcRadiiFor(m_surroundData->border, borderRect.size()); + radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii)); roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge); } return roundedRect; @@ -1174,41 +1255,33 @@ RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, Rende RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const { bool horizontal = isHorizontalWritingMode(); - - int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0; - int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0; - int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0; - int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0; - + 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, - int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const +RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth, + LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const { - LayoutRect innerRect(borderRect.x() + leftWidth, - borderRect.y() + topWidth, - borderRect.width() - leftWidth - rightWidth, - borderRect.height() - topWidth - bottomWidth); - - RoundedRect roundedRect(pixelSnappedIntRect(innerRect)); - + RoundedRect roundedRect { { borderRect.x() + leftWidth, borderRect.y() + topWidth, + borderRect.width() - leftWidth - rightWidth, borderRect.height() - topWidth - bottomWidth } }; if (hasBorderRadius()) { - RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii(); + auto radii = getRoundedBorderFor(borderRect).radii(); radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth); roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge); } return roundedRect; } -static bool allLayersAreFixed(const FillLayer* layer) +static bool allLayersAreFixed(const FillLayer& layers) { - bool allFixed = true; - - for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next()) - allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment); - - return layer && allFixed; + for (auto* layer = &layers; layer; layer = layer->next()) { + if (!(layer->image() && layer->attachment() == FixedBackgroundAttachment)) + return false; + } + return true; } bool RenderStyle::hasEntirelyFixedBackground() const @@ -1218,14 +1291,14 @@ bool RenderStyle::hasEntirelyFixedBackground() const const CounterDirectiveMap* RenderStyle::counterDirectives() const { - return rareNonInheritedData->m_counterDirectives.get(); + return m_rareNonInheritedData->counterDirectives.get(); } CounterDirectiveMap& RenderStyle::accessCounterDirectives() { - OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives; + auto& map = m_rareNonInheritedData.access().counterDirectives; if (!map) - map = adoptPtr(new CounterDirectiveMap); + map = std::make_unique<CounterDirectiveMap>(); return *map; } @@ -1240,14 +1313,14 @@ const AtomicString& RenderStyle::hyphenString() const { ASSERT(hyphens() != HyphensNone); - const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString; + auto& hyphenationString = m_rareInheritedData->hyphenationString; if (!hyphenationString.isNull()) return hyphenationString; // FIXME: This should depend on locale. - DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1)); - DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1)); - return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString; + static NeverDestroyed<AtomicString> hyphenMinusString(&hyphenMinus, 1); + static NeverDestroyed<AtomicString> hyphenString(&hyphen, 1); + return fontCascade().primaryFont().glyphForCharacter(hyphen) ? hyphenString : hyphenMinusString; } const AtomicString& RenderStyle::textEmphasisMarkString() const @@ -1258,28 +1331,28 @@ const AtomicString& RenderStyle::textEmphasisMarkString() const case TextEmphasisMarkCustom: return textEmphasisCustomMark(); case TextEmphasisMarkDot: { - DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1)); - DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1)); + static NeverDestroyed<AtomicString> filledDotString(&bullet, 1); + static NeverDestroyed<AtomicString> openDotString(&whiteBullet, 1); return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString; } case TextEmphasisMarkCircle: { - DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1)); - DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1)); + static NeverDestroyed<AtomicString> filledCircleString(&blackCircle, 1); + static NeverDestroyed<AtomicString> openCircleString(&whiteCircle, 1); return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString; } case TextEmphasisMarkDoubleCircle: { - DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1)); - DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1)); + static NeverDestroyed<AtomicString> filledDoubleCircleString(&fisheye, 1); + static NeverDestroyed<AtomicString> openDoubleCircleString(&bullseye, 1); return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString; } case TextEmphasisMarkTriangle: { - DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1)); - DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1)); + static NeverDestroyed<AtomicString> filledTriangleString(&blackUpPointingTriangle, 1); + static NeverDestroyed<AtomicString> openTriangleString(&whiteUpPointingTriangle, 1); return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString; } case TextEmphasisMarkSesame: { - DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1)); - DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1)); + static NeverDestroyed<AtomicString> filledSesameString(&sesameDot, 1); + static NeverDestroyed<AtomicString> openSesameString(&whiteSesameDot, 1); return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString; } case TextEmphasisMarkAuto: @@ -1292,40 +1365,34 @@ const AtomicString& RenderStyle::textEmphasisMarkString() const } #if ENABLE(DASHBOARD_SUPPORT) + const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions() { - DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ()); + static NeverDestroyed<Vector<StyleDashboardRegion>> emptyList; return emptyList; } const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions() { - DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ()); + static NeverDestroyed<Vector<StyleDashboardRegion>> noneList; static bool noneListInitialized = false; - if (!noneListInitialized) { - StyleDashboardRegion region; - region.label = ""; - region.offset.m_top = Length(); - region.offset.m_right = Length(); - region.offset.m_bottom = Length(); - region.offset.m_left = Length(); - region.type = StyleDashboardRegion::None; - noneList.append(region); + noneList.get().append(StyleDashboardRegion { emptyString(), { }, StyleDashboardRegion::None }); noneListInitialized = true; } return noneList; } + #endif void RenderStyle::adjustAnimations() { - AnimationList* animationList = rareNonInheritedData->m_animations.get(); + auto* animationList = m_rareNonInheritedData->animations.get(); if (!animationList) return; // Get rid of empty animations and anything beyond them - for (size_t i = 0; i < animationList->size(); ++i) { + for (size_t i = 0, size = animationList->size(); i < size; ++i) { if (animationList->animation(i).isEmpty()) { animationList->resize(i); break; @@ -1343,12 +1410,12 @@ void RenderStyle::adjustAnimations() void RenderStyle::adjustTransitions() { - AnimationList* transitionList = rareNonInheritedData->m_transitions.get(); + auto* transitionList = m_rareNonInheritedData->transitions.get(); if (!transitionList) return; // Get rid of empty transitions and anything beyond them - for (size_t i = 0; i < transitionList->size(); ++i) { + for (size_t i = 0, size = transitionList->size(); i < size; ++i) { if (transitionList->animation(i).isEmpty()) { transitionList->resize(i); break; @@ -1363,10 +1430,10 @@ void RenderStyle::adjustTransitions() // 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 very short, so it is probably ok + // 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) { + for (size_t j = i + 1; j < transitionList->size(); ++j) { if (transitionList->animation(i).property() == transitionList->animation(j).property()) { // toss i transitionList->remove(i); @@ -1376,76 +1443,111 @@ void RenderStyle::adjustTransitions() } } -AnimationList* RenderStyle::accessAnimations() +AnimationList& RenderStyle::ensureAnimations() { - if (!rareNonInheritedData.access()->m_animations) - rareNonInheritedData.access()->m_animations = adoptPtr(new AnimationList()); - return rareNonInheritedData->m_animations.get(); + if (!m_rareNonInheritedData.access().animations) + m_rareNonInheritedData.access().animations = std::make_unique<AnimationList>(); + return *m_rareNonInheritedData->animations; } -AnimationList* RenderStyle::accessTransitions() +AnimationList& RenderStyle::ensureTransitions() { - if (!rareNonInheritedData.access()->m_transitions) - rareNonInheritedData.access()->m_transitions = adoptPtr(new AnimationList()); - return rareNonInheritedData->m_transitions.get(); + if (!m_rareNonInheritedData.access().transitions) + m_rareNonInheritedData.access().transitions = std::make_unique<AnimationList>(); + return *m_rareNonInheritedData->transitions; } const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const { - if (transitions()) { - for (size_t i = 0; i < transitions()->size(); ++i) { - const Animation& p = transitions()->animation(i); - if (p.animationMode() == Animation::AnimateAll || p.property() == property) { - return &p; - } - } + 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 0; + return nullptr; } -const Font& RenderStyle::font() const { return inherited->font; } -const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); } -const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); } -float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); } -float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); } -int RenderStyle::fontSize() const { return inherited->font.pixelSize(); } +const FontCascade& RenderStyle::fontCascade() const +{ + return m_inheritedData->fontCascade; +} -const Length& RenderStyle::wordSpacing() const { return rareInheritedData->wordSpacing; } -float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); } +const FontMetrics& RenderStyle::fontMetrics() const +{ + return m_inheritedData->fontCascade.fontMetrics(); +} -bool RenderStyle::setFontDescription(const FontDescription& v) +const FontCascadeDescription& RenderStyle::fontDescription() const { - if (inherited->font.fontDescription() != v) { - inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing()); - return true; - } - return false; + return m_inheritedData->fontCascade.fontDescription(); +} + +float RenderStyle::specifiedFontSize() const +{ + return fontDescription().specifiedSize(); +} + +float RenderStyle::computedFontSize() const +{ + return fontDescription().computedSize(); +} + +int RenderStyle::fontSize() const +{ + return m_inheritedData->fontCascade.pixelSize(); +} + +const Length& RenderStyle::wordSpacing() const +{ + return m_rareInheritedData->wordSpacing; } -#if ENABLE(IOS_TEXT_AUTOSIZING) -const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; } -void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); } +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 -const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; } + return m_inheritedData->lineHeight; #endif +} -Length RenderStyle::lineHeight() const -{ - const Length& lh = inherited->line_height; #if ENABLE(TEXT_AUTOSIZING) - // Unlike fontDescription().computedSize() and hence fontSize(), this is - // recalculated on demand as we only store the specified line height. - // FIXME: Should consider scaling the fixed part of any calc expressions - // too, though this involves messily poking into CalcExpressionLength. - float multiplier = textAutosizingMultiplier(); - if (multiplier > 1 && lh.isFixed()) - return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed); + +void RenderStyle::setSpecifiedLineHeight(Length&& height) +{ + SET_VAR(m_inheritedData, specifiedLineHeight, WTFMove(height)); +} + #endif - return lh; + +const Length& RenderStyle::lineHeight() const +{ + return m_inheritedData->lineHeight; +} + +void RenderStyle::setLineHeight(Length&& height) +{ + SET_VAR(m_inheritedData, lineHeight, WTFMove(height)); } -void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); } -int RenderStyle::computedLineHeight(RenderView* renderView) const +int RenderStyle::computedLineHeight() const { const Length& lh = lineHeight(); @@ -1453,41 +1555,38 @@ int RenderStyle::computedLineHeight(RenderView* renderView) const if (lh.isNegative()) return fontMetrics().lineSpacing(); - if (lh.isPercent()) + if (lh.isPercentOrCalculated()) return minimumValueForLength(lh, fontSize()); - if (lh.isViewportPercentage()) - return valueForLength(lh, 0, renderView); - - return lh.value(); + return clampTo<int>(lh.value()); } -void RenderStyle::setWordSpacing(Length v) +void RenderStyle::setWordSpacing(Length&& value) { float fontWordSpacing; - switch (v.type()) { + switch (value.type()) { case Auto: fontWordSpacing = 0; - FALLTHROUGH; + break; case Percent: - fontWordSpacing = v.getFloatValue() * font().spaceWidth() / 100; + fontWordSpacing = value.percent() * fontCascade().spaceWidth() / 100; break; case Fixed: - fontWordSpacing = v.getFloatValue(); + fontWordSpacing = value.value(); break; case Calculated: - fontWordSpacing = v.nonNanCalculatedValue(maxValueForCssLength); + fontWordSpacing = value.nonNanCalculatedValue(maxValueForCssLength); break; default: ASSERT_NOT_REACHED(); fontWordSpacing = 0; break; } - inherited.access()->font.setWordSpacing(fontWordSpacing); - rareInheritedData.access()->wordSpacing = std::move(v); + m_inheritedData.access().fontCascade.setWordSpacing(fontWordSpacing); + m_rareInheritedData.access().wordSpacing = WTFMove(value); } -void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); } +void RenderStyle::setLetterSpacing(float v) { m_inheritedData.access().fontCascade.setLetterSpacing(v); } void RenderStyle::setFontSize(float size) { @@ -1500,24 +1599,28 @@ void RenderStyle::setFontSize(float size) else size = std::min(maximumAllowedFontSize, size); - FontSelector* currentFontSelector = font().fontSelector(); - FontDescription desc(fontDescription()); - desc.setSpecifiedSize(size); - desc.setComputedSize(size); + FontSelector* currentFontSelector = fontCascade().fontSelector(); + auto description = fontDescription(); + description.setSpecifiedSize(size); + description.setComputedSize(size); -#if ENABLE(TEXT_AUTOSIZING) - float multiplier = textAutosizingMultiplier(); - if (multiplier > 1) { - float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier); - desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize)); - } -#endif + setFontDescription(description); + fontCascade().update(currentFontSelector); +} - setFontDescription(desc); - font().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::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const +void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const { top = 0; right = 0; @@ -1616,7 +1719,7 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c case CSSPropertyOutlineColor: result = visitedLink ? visitedLinkOutlineColor() : outlineColor(); break; - case CSSPropertyWebkitColumnRuleColor: + case CSSPropertyColumnRuleColor: result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor(); break; case CSSPropertyWebkitTextDecorationColor: @@ -1638,7 +1741,7 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c if (!result.isValid()) { if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE)) - result.setRGB(238, 238, 238); + result = Color(238, 238, 238); else result = visitedLink ? visitedLinkColor() : color(); } @@ -1666,7 +1769,7 @@ Color RenderStyle::visitedDependentColor(int colorProperty) const return unvisitedColor; // Take the alpha from the unvisited color, but get the RGB values from the visited color. - return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha()); + return visitedColor.colorWithAlpha(unvisitedColor.alphaAsFloat()); } const BorderValue& RenderStyle::borderBefore() const @@ -1715,7 +1818,7 @@ const BorderValue& RenderStyle::borderEnd() const return isLeftToRightDirection() ? borderBottom() : borderTop(); } -unsigned short RenderStyle::borderBeforeWidth() const +float RenderStyle::borderBeforeWidth() const { switch (writingMode()) { case TopToBottomWritingMode: @@ -1731,7 +1834,7 @@ unsigned short RenderStyle::borderBeforeWidth() const return borderTopWidth(); } -unsigned short RenderStyle::borderAfterWidth() const +float RenderStyle::borderAfterWidth() const { switch (writingMode()) { case TopToBottomWritingMode: @@ -1747,67 +1850,67 @@ unsigned short RenderStyle::borderAfterWidth() const return borderBottomWidth(); } -unsigned short RenderStyle::borderStartWidth() const +float RenderStyle::borderStartWidth() const { if (isHorizontalWritingMode()) return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth(); return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth(); } -unsigned short RenderStyle::borderEndWidth() const +float RenderStyle::borderEndWidth() const { if (isHorizontalWritingMode()) return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth(); return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth(); } -void RenderStyle::setMarginStart(Length margin) +void RenderStyle::setMarginStart(Length&& margin) { if (isHorizontalWritingMode()) { if (isLeftToRightDirection()) - setMarginLeft(margin); + setMarginLeft(WTFMove(margin)); else - setMarginRight(margin); + setMarginRight(WTFMove(margin)); } else { if (isLeftToRightDirection()) - setMarginTop(margin); + setMarginTop(WTFMove(margin)); else - setMarginBottom(margin); + setMarginBottom(WTFMove(margin)); } } -void RenderStyle::setMarginEnd(Length margin) +void RenderStyle::setMarginEnd(Length&& margin) { if (isHorizontalWritingMode()) { if (isLeftToRightDirection()) - setMarginRight(margin); + setMarginRight(WTFMove(margin)); else - setMarginLeft(margin); + setMarginLeft(WTFMove(margin)); } else { if (isLeftToRightDirection()) - setMarginBottom(margin); + setMarginBottom(WTFMove(margin)); else - setMarginTop(margin); + setMarginTop(WTFMove(margin)); } } TextEmphasisMark RenderStyle::textEmphasisMark() const { - TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark); + 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 @@ -1818,78 +1921,61 @@ LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth())); } -void RenderStyle::getFontAndGlyphOrientation(FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation) +std::pair<FontOrientation, NonCJKGlyphOrientation> RenderStyle::fontAndGlyphOrientation() { - if (isHorizontalWritingMode()) { - fontOrientation = Horizontal; - glyphOrientation = NonCJKGlyphOrientationVerticalRight; - return; - } + // FIXME: TextOrientationSideways should map to sideways-left in vertical-lr, which is not supported yet. + + if (isHorizontalWritingMode()) + return { Horizontal, NonCJKGlyphOrientation::Mixed }; switch (textOrientation()) { - case TextOrientationVerticalRight: - fontOrientation = Vertical; - glyphOrientation = NonCJKGlyphOrientationVerticalRight; - return; - case TextOrientationUpright: - fontOrientation = Vertical; - glyphOrientation = NonCJKGlyphOrientationUpright; - return; - case TextOrientationSideways: - if (writingMode() == LeftToRightWritingMode) { - // FIXME: This should map to sideways-left, which is not supported yet. - fontOrientation = Vertical; - glyphOrientation = NonCJKGlyphOrientationVerticalRight; - return; - } - fontOrientation = Horizontal; - glyphOrientation = NonCJKGlyphOrientationVerticalRight; - return; - case TextOrientationSidewaysRight: - fontOrientation = Horizontal; - glyphOrientation = NonCJKGlyphOrientationVerticalRight; - return; + 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(); - fontOrientation = Horizontal; - glyphOrientation = NonCJKGlyphOrientationVerticalRight; - return; + return { Horizontal, NonCJKGlyphOrientation::Mixed }; } } -void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image) +void RenderStyle::setBorderImageSource(RefPtr<StyleImage>&& image) { - if (surround->border.m_image.image() == image.get()) + if (m_surroundData->border.m_image.image() == image.get()) return; - surround.access()->border.m_image.setImage(image); + m_surroundData.access().border.m_image.setImage(WTFMove(image)); } -void RenderStyle::setBorderImageSlices(LengthBox slices) +void RenderStyle::setBorderImageSlices(LengthBox&& slices) { - if (surround->border.m_image.imageSlices() == slices) + if (m_surroundData->border.m_image.imageSlices() == slices) return; - surround.access()->border.m_image.setImageSlices(slices); + m_surroundData.access().border.m_image.setImageSlices(WTFMove(slices)); } -void RenderStyle::setBorderImageWidth(LengthBox slices) +void RenderStyle::setBorderImageWidth(LengthBox&& slices) { - if (surround->border.m_image.borderSlices() == slices) + if (m_surroundData->border.m_image.borderSlices() == slices) return; - surround.access()->border.m_image.setBorderSlices(slices); + m_surroundData.access().border.m_image.setBorderSlices(WTFMove(slices)); } -void RenderStyle::setBorderImageOutset(LengthBox outset) +void RenderStyle::setBorderImageOutset(LengthBox&& outset) { - if (surround->border.m_image.outset() == outset) + if (m_surroundData->border.m_image.outset() == outset) return; - surround.access()->border.m_image.setOutset(outset); + 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); @@ -1925,4 +2011,263 @@ void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& pagi } } +#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() const +{ + Vector<PaintType, 3> paintOrder; + switch (this->paintOrder()) { + case PaintOrderNormal: + FALLTHROUGH; + case PaintOrderFill: + paintOrder.append(PaintTypeFill); + paintOrder.append(PaintTypeStroke); + paintOrder.append(PaintTypeMarkers); + break; + case PaintOrderFillMarkers: + paintOrder.append(PaintTypeFill); + paintOrder.append(PaintTypeMarkers); + paintOrder.append(PaintTypeStroke); + break; + case PaintOrderStroke: + paintOrder.append(PaintTypeStroke); + paintOrder.append(PaintTypeFill); + paintOrder.append(PaintTypeMarkers); + break; + case PaintOrderStrokeMarkers: + paintOrder.append(PaintTypeStroke); + paintOrder.append(PaintTypeMarkers); + paintOrder.append(PaintTypeFill); + break; + case PaintOrderMarkers: + paintOrder.append(PaintTypeMarkers); + paintOrder.append(PaintTypeFill); + paintOrder.append(PaintTypeStroke); + break; + case PaintOrderMarkersStroke: + paintOrder.append(PaintTypeMarkers); + paintOrder.append(PaintTypeStroke); + paintOrder.append(PaintTypeFill); + break; + }; + return paintOrder; +} + + } // namespace WebCore |