diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/style/computed_style.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/style/computed_style.cc | 276 |
1 files changed, 218 insertions, 58 deletions
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style.cc b/chromium/third_party/blink/renderer/core/style/computed_style.cc index 52b16de6bb7..f240ccd0dcf 100644 --- a/chromium/third_party/blink/renderer/core/style/computed_style.cc +++ b/chromium/third_party/blink/renderer/core/style/computed_style.cc @@ -27,9 +27,9 @@ #include <memory> #include <utility> +#include "base/cxx17_backports.h" #include "base/metrics/histogram_functions.h" #include "base/numerics/clamped_math.h" -#include "base/numerics/ranges.h" #include "build/build_config.h" #include "cc/input/overscroll_behavior.h" #include "third_party/blink/renderer/core/animation/css/css_animation_data.h" @@ -37,11 +37,14 @@ #include "third_party/blink/renderer/core/css/css_paint_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_property_equality.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/properties/longhand.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/core/html/html_body_element.h" +#include "third_party/blink/renderer/core/html/html_html_element.h" #include "third_party/blink/renderer/core/html/html_progress_element.h" #include "third_party/blink/renderer/core/layout/layout_theme.h" #include "third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h" @@ -99,11 +102,13 @@ ASSERT_SIZE(BorderValue, SameSizeAsBorderValue); struct SameSizeAsComputedStyleBase { SameSizeAsComputedStyleBase() { base::debug::Alias(&data_refs); + base::debug::Alias(&pointers); base::debug::Alias(&bitfields); } private: - void* data_refs[9]; + void* data_refs[8]; + void* pointers[1]; unsigned bitfields[5]; }; @@ -150,6 +155,25 @@ scoped_refptr<ComputedStyle> ComputedStyle::CreateInitialStyleSingleton() { return base::MakeRefCounted<ComputedStyle>(PassKey()); } +Vector<AtomicString>* ComputedStyle::GetVariableNamesCache() const { + if (cached_data_) + return cached_data_->variable_names_.get(); + return nullptr; +} + +Vector<AtomicString>& ComputedStyle::EnsureVariableNamesCache() const { + if (!cached_data_ || !cached_data_->variable_names_) { + EnsureCachedData().variable_names_ = + std::make_unique<Vector<AtomicString>>(); + } + return *cached_data_->variable_names_; +} + +void ComputedStyle::ClearVariableNamesCache() const { + if (cached_data_) + cached_data_->variable_names_.reset(); +} + scoped_refptr<ComputedStyle> ComputedStyle::Clone(const ComputedStyle& other) { return base::AdoptRef(new ComputedStyle(PassKey(), other)); } @@ -188,6 +212,25 @@ static bool PseudoElementStylesEqual(const ComputedStyle& old_style, return true; } +static bool DiffAffectsContainerQueries(const ComputedStyle& old_style, + const ComputedStyle& new_style) { + if (!old_style.IsContainerForContainerQueries() && + !new_style.IsContainerForContainerQueries()) { + return false; + } + if ((old_style.ContainerName() != new_style.ContainerName()) || + (old_style.ContainerType() != new_style.ContainerType())) { + return true; + } + if (new_style.Display() != old_style.Display()) { + if (new_style.Display() == EDisplay::kNone || + new_style.Display() == EDisplay::kContents) { + return true; + } + } + return false; +} + bool ComputedStyle::NeedsReattachLayoutTree(const Element& element, const ComputedStyle* old_style, const ComputedStyle* new_style) { @@ -223,9 +266,27 @@ bool ComputedStyle::NeedsReattachLayoutTree(const Element& element, // based on appearance. return true; } + + // LayoutObject tree structure for <legend> depends on whether it's a + // rendered legend or not. + if (UNLIKELY(IsA<HTMLLegendElement>(element) && + (old_style->IsFloating() != new_style->IsFloating() || + old_style->HasOutOfFlowPosition() != + new_style->HasOutOfFlowPosition()))) + return true; + if (!RuntimeEnabledFeatures::LayoutNGEnabled()) return false; + // We use LayoutNGTextCombine only for vertical writing mode. + if (RuntimeEnabledFeatures::LayoutNGTextCombineEnabled() && + new_style->HasTextCombine() && + old_style->IsHorizontalWritingMode() != + new_style->IsHorizontalWritingMode()) { + DCHECK_EQ(old_style->HasTextCombine(), new_style->HasTextCombine()); + return true; + } + // LayoutNG needs an anonymous inline wrapper if ::first-line is applied. // Also see |LayoutBlockFlow::NeedsAnonymousInlineWrapper()|. if (new_style->HasPseudoElementStyle(kPseudoIdFirstLine) && @@ -271,7 +332,10 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle( DCHECK_NE(&old_style, &new_style); if (old_style.Display() != new_style.Display() && old_style.BlockifiesChildren() != new_style.BlockifiesChildren()) - return Difference::kDisplayAffectingDescendantStyles; + return Difference::kDescendantAffecting; + // TODO(crbug.com/1213888): Only recalc affected descendants. + if (DiffAffectsContainerQueries(old_style, new_style)) + return Difference::kDescendantAffecting; if (!old_style.NonIndependentInheritedEqual(new_style)) return Difference::kInherited; if (old_style.JustifyItems() != new_style.JustifyItems()) @@ -308,8 +372,11 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle( void ComputedStyle::PropagateIndependentInheritedProperties( const ComputedStyle& parent_style) { ComputedStyleBase::PropagateIndependentInheritedProperties(parent_style); - if (!HasVariableReference() && !HasVariableDeclaration()) - InheritCustomPropertiesFrom(parent_style); + if (!HasVariableReference() && !HasVariableDeclaration() && + (InheritedVariables() != parent_style.InheritedVariables())) { + MutableInheritedVariablesInternal() = + parent_style.InheritedVariablesInternal(); + } } StyleSelfAlignmentData ResolvedSelfAlignment( @@ -529,6 +596,18 @@ void ComputedStyle::ClearCachedPseudoElementStyles() const { cached_data_->pseudo_element_styles_->clear(); } +const ComputedStyle* ComputedStyle::GetBaseComputedStyle() const { + if (auto* base_data = BaseData().get()) + return base_data->GetBaseComputedStyle(); + return nullptr; +} + +const CSSBitset* ComputedStyle::GetBaseImportantSet() const { + if (auto* base_data = BaseData().get()) + return base_data->GetBaseImportantSet(); + return nullptr; +} + bool ComputedStyle::InheritedEqual(const ComputedStyle& other) const { return IndependentInheritedEqual(other) && NonIndependentInheritedEqual(other); @@ -1008,14 +1087,11 @@ void ComputedStyle::ClearCursorList() { static bool HasPropertyThatCreatesStackingContext( const Vector<CSSPropertyID>& properties) { for (CSSPropertyID property : properties) { - switch (property) { + switch (ResolveCSSPropertyID(property)) { case CSSPropertyID::kOpacity: case CSSPropertyID::kTransform: - case CSSPropertyID::kAliasWebkitTransform: case CSSPropertyID::kTransformStyle: - case CSSPropertyID::kAliasWebkitTransformStyle: case CSSPropertyID::kPerspective: - case CSSPropertyID::kAliasWebkitPerspective: case CSSPropertyID::kTranslate: case CSSPropertyID::kRotate: case CSSPropertyID::kScale: @@ -1024,10 +1100,8 @@ static bool HasPropertyThatCreatesStackingContext( case CSSPropertyID::kWebkitMask: case CSSPropertyID::kWebkitMaskBoxImage: case CSSPropertyID::kClipPath: - case CSSPropertyID::kAliasWebkitClipPath: case CSSPropertyID::kWebkitBoxReflect: case CSSPropertyID::kFilter: - case CSSPropertyID::kAliasWebkitFilter: case CSSPropertyID::kBackdropFilter: case CSSPropertyID::kZIndex: case CSSPropertyID::kPosition: @@ -1082,15 +1156,15 @@ void ComputedStyle::SetContent(ContentData* content_data) { } static bool IsWillChangeTransformHintProperty(CSSPropertyID property) { - switch (property) { + switch (ResolveCSSPropertyID(property)) { case CSSPropertyID::kTransform: - case CSSPropertyID::kAliasWebkitTransform: case CSSPropertyID::kPerspective: case CSSPropertyID::kTranslate: case CSSPropertyID::kScale: case CSSPropertyID::kRotate: case CSSPropertyID::kOffsetPath: case CSSPropertyID::kOffsetPosition: + case CSSPropertyID::kTransformStyle: return true; default: break; @@ -1101,10 +1175,9 @@ static bool IsWillChangeTransformHintProperty(CSSPropertyID property) { static bool IsWillChangeCompositingHintProperty(CSSPropertyID property) { if (IsWillChangeTransformHintProperty(property)) return true; - switch (property) { + switch (ResolveCSSPropertyID(property)) { case CSSPropertyID::kOpacity: case CSSPropertyID::kFilter: - case CSSPropertyID::kAliasWebkitFilter: case CSSPropertyID::kBackdropFilter: case CSSPropertyID::kTop: case CSSPropertyID::kLeft: @@ -1342,7 +1415,7 @@ bool ComputedStyle::SetEffectiveZoom(float f) { // real cost to our understanding of the zooms in use. base::UmaHistogramSparse( "Blink.EffectiveZoom", - base::ClampToRange<float>(clamped_effective_zoom * 100, 0, 400)); + base::clamp<float>(clamped_effective_zoom * 100, 0, 400)); return true; } @@ -1368,8 +1441,11 @@ CounterDirectiveMap& ComputedStyle::AccessCounterDirectives() { const CounterDirectives ComputedStyle::GetCounterDirectives( const AtomicString& identifier) const { - if (const CounterDirectiveMap* directives = GetCounterDirectives()) - return directives->at(identifier); + if (GetCounterDirectives()) { + auto it = GetCounterDirectives()->find(identifier); + if (it != GetCounterDirectives()->end()) + return it->value; + } return CounterDirectives(); } @@ -1665,13 +1741,41 @@ CSSTransitionData& ComputedStyle::AccessTransitions() { } FontBaseline ComputedStyle::GetFontBaseline() const { - // TODO(kojii): Incorporate 'dominant-baseline' when we support it. - // https://www.w3.org/TR/css-inline-3/#dominant-baseline-property + // CssDominantBaseline() always returns kAuto for non-SVG elements, + // and never returns kUseScript, kNoChange, and kResetSize. + // See StyleAdjuster::AdjustComputedStyle(). + switch (CssDominantBaseline()) { + case EDominantBaseline::kAuto: + break; + case EDominantBaseline::kMiddle: + return kXMiddleBaseline; + case EDominantBaseline::kAlphabetic: + return kAlphabeticBaseline; + case EDominantBaseline::kHanging: + return kHangingBaseline; + case EDominantBaseline::kCentral: + return kCentralBaseline; + case EDominantBaseline::kTextBeforeEdge: + return kTextOverBaseline; + case EDominantBaseline::kTextAfterEdge: + return kTextUnderBaseline; + case EDominantBaseline::kIdeographic: + return kIdeographicUnderBaseline; + case EDominantBaseline::kMathematical: + return kMathBaseline; + + case EDominantBaseline::kUseScript: + case EDominantBaseline::kNoChange: + case EDominantBaseline::kResetSize: + NOTREACHED(); + break; + } // Vertical flow (except 'text-orientation: sideways') uses ideographic - // baseline. https://drafts.csswg.org/css-writing-modes-3/#intro-baselines + // central baseline. + // https://drafts.csswg.org/css-writing-modes-3/#text-baselines return !GetFontDescription().IsVerticalAnyUpright() ? kAlphabeticBaseline - : kIdeographicBaseline; + : kCentralBaseline; } FontHeight ComputedStyle::GetFontHeight(FontBaseline baseline) const { @@ -1782,7 +1886,18 @@ bool ComputedStyle::HasVariables() const { HasInitialVariables(InitialDataInternal().get()); } -HashSet<AtomicString> ComputedStyle::GetVariableNames() const { +wtf_size_t ComputedStyle::GetVariableNamesCount() const { + if (!HasVariables()) + return 0; + return GetVariableNames().size(); +} + +const Vector<AtomicString>& ComputedStyle::GetVariableNames() const { + if (auto* cache = GetVariableNamesCache()) + return *cache; + + Vector<AtomicString>& cache = EnsureVariableNamesCache(); + HashSet<AtomicString> names; if (auto* initial_data = InitialDataInternal().get()) initial_data->CollectVariableNames(names); @@ -1790,18 +1905,22 @@ HashSet<AtomicString> ComputedStyle::GetVariableNames() const { inherited_variables->CollectNames(names); if (auto* non_inherited_variables = NonInheritedVariables()) non_inherited_variables->CollectNames(names); - return names; + CopyToVector(names, cache); + + return cache; } -StyleInheritedVariables* ComputedStyle::InheritedVariables() const { +const StyleInheritedVariables* ComputedStyle::InheritedVariables() const { return InheritedVariablesInternal().get(); } -StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const { +const StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const { return NonInheritedVariablesInternal().get(); } StyleInheritedVariables& ComputedStyle::MutableInheritedVariables() { + ClearVariableNamesCache(); + scoped_refptr<StyleInheritedVariables>& variables = MutableInheritedVariablesInternal(); if (!variables) @@ -1812,6 +1931,8 @@ StyleInheritedVariables& ComputedStyle::MutableInheritedVariables() { } StyleNonInheritedVariables& ComputedStyle::MutableNonInheritedVariables() { + ClearVariableNamesCache(); + std::unique_ptr<StyleNonInheritedVariables>& variables = MutableNonInheritedVariablesInternal(); if (!variables) @@ -1820,6 +1941,8 @@ StyleNonInheritedVariables& ComputedStyle::MutableNonInheritedVariables() { } void ComputedStyle::SetInitialData(scoped_refptr<StyleInitialData> data) { + ClearVariableNamesCache(); + MutableInitialDataInternal() = std::move(data); } @@ -1971,12 +2094,20 @@ LayoutUnit ComputedStyle::ComputedLineHeightAsFixed(const Font& font) const { if (lh.IsNegative() && font.PrimaryFont()) return font.PrimaryFont()->GetFontMetrics().FixedLineSpacing(); - if (lh.IsPercentOrCalc()) { - return LayoutUnit( - MinimumValueForLength(lh, ComputedFontSizeAsFixed(font)).ToInt()); - } + if (RuntimeEnabledFeatures::FractionalLineHeightEnabled()) { + if (lh.IsPercentOrCalc()) { + return MinimumValueForLength(lh, ComputedFontSizeAsFixed(font)); + } - return LayoutUnit(floorf(lh.Value())); + return LayoutUnit::FromFloatFloor(lh.Value()); + } else { + if (lh.IsPercentOrCalc()) { + return LayoutUnit( + MinimumValueForLength(lh, ComputedFontSizeAsFixed(font)).ToInt()); + } + + return LayoutUnit(floorf(lh.Value())); + } } LayoutUnit ComputedStyle::ComputedLineHeightAsFixed() const { @@ -1996,6 +2127,9 @@ void ComputedStyle::SetLetterSpacing(float letter_spacing) { } void ComputedStyle::SetTextAutosizingMultiplier(float multiplier) { + if (TextAutosizingMultiplier() == multiplier) + return; + SetTextAutosizingMultiplierInternal(multiplier); float size = SpecifiedFontSize(); @@ -2215,24 +2349,41 @@ int ComputedStyle::OutlineOutsetExtent() const { if (!HasOutline()) return 0; if (OutlineStyleIsAuto()) { - return GraphicsContext::FocusRingOutsetExtent( - OutlineOffsetInt(), std::ceil(GetOutlineStrokeWidthForFocusRing())); + // Unlike normal outlines (whole width is outside of the offset), focus + // rings are drawn with only part of it outside of the offset. + return FocusRingOffset() + std::ceil(FocusRingStrokeWidth() / 3.f) * 2; } return base::ClampAdd(OutlineWidthInt(), OutlineOffsetInt()).Max(0); } -float ComputedStyle::GetOutlineStrokeWidthForFocusRing() const { - if (::features::IsFormControlsRefreshEnabled() && OutlineStyleIsAuto()) { - return std::max(EffectiveZoom(), 3.f); - } +float ComputedStyle::FocusRingOuterStrokeWidth() const { + // The focus ring is made of two rings which have a 2:1 ratio. + return FocusRingStrokeWidth() / 3.f * 2; +} + +float ComputedStyle::FocusRingInnerStrokeWidth() const { + return FocusRingStrokeWidth() / 3.f; +} -#if defined(OS_MAC) - return OutlineWidthInt(); -#else - // Draw an outline with thickness in proportion to the zoom level, but never +float ComputedStyle::FocusRingStrokeWidth() const { + DCHECK(OutlineStyleIsAuto()); + // Draw focus ring with thickness in proportion to the zoom level, but never // so narrow that it becomes invisible. - return std::max(EffectiveZoom(), 1.f); -#endif + return std::max(EffectiveZoom(), 3.f); +} + +int ComputedStyle::FocusRingOffset() const { + DCHECK(OutlineStyleIsAuto()); + // How much space the focus ring would like to take from the actual border. + constexpr float kMaxInsideBorderWidth = 1; + int offset = OutlineOffsetInt(); + // Focus ring is dependent on whether the border is large enough to have an + // inset outline. Use the smallest border edge for that test. + float min_border_width = std::min({BorderTopWidth(), BorderBottomWidth(), + BorderLeftWidth(), BorderRightWidth()}); + if (min_border_width >= kMaxInsideBorderWidth) + offset -= kMaxInsideBorderWidth; + return offset; } bool ComputedStyle::StrokeDashArrayDataEquivalent( @@ -2411,27 +2562,15 @@ void ComputedStyle::ClearBackgroundImage() { curr_child->ClearImage(); } -ListStyleTypeData* ComputedStyle::GetListStyleType() const { - return ListStyleTypeInternal(); -} - -EListStyleType ComputedStyle::ListStyleType() const { - if (!GetListStyleType()) - return EListStyleType::kNone; - if (GetListStyleType()->IsString()) - return EListStyleType::kString; - return GetListStyleType()->ToDeprecatedListStyleTypeEnum(); -} - const AtomicString& ComputedStyle::ListStyleStringValue() const { - if (!GetListStyleType() || !GetListStyleType()->IsString()) + if (!ListStyleType() || !ListStyleType()->IsString()) return g_null_atom; - return GetListStyleType()->GetStringValue(); + return ListStyleType()->GetStringValue(); } absl::optional<Color> ComputedStyle::AccentColorResolved() const { const StyleAutoColor& auto_color = AccentColor(); - if (auto_color.IsAutoColor() || ShouldForceColor(auto_color)) + if (auto_color.IsAutoColor()) return absl::nullopt; return auto_color.Resolve(GetCurrentColor(), UsedColorScheme()); } @@ -2475,6 +2614,27 @@ EPaintOrderType ComputedStyle::PaintOrderType(unsigned index) const { return static_cast<EPaintOrderType>(pt); } +bool ComputedStyle::ShouldApplyAnyContainment(const Element& element) const { + DCHECK(IsA<HTMLBodyElement>(element) || IsA<HTMLHtmlElement>(element)) + << "Since elements can override the computed display for which box type " + "to create, this method is not generally correct. Use " + "LayoutObject::ShouldApplyAnyContainment if possible."; + if (ContainsStyle()) + return true; + if (!element.LayoutObjectIsNeeded(*this)) + return false; + if (Display() == EDisplay::kInline) + return false; + if ((ContainsInlineSize() || ContainsBlockSize()) && + (!IsDisplayTableType() || Display() == EDisplay::kTableCaption)) { + return true; + } + return (ContainsLayout() || ContainsPaint()) && + (!IsDisplayTableType() || IsDisplayTableBox() || + Display() == EDisplay::kTableCell || + Display() == EDisplay::kTableCaption); +} + STATIC_ASSERT_ENUM(cc::OverscrollBehavior::Type::kAuto, EOverscrollBehavior::kAuto); STATIC_ASSERT_ENUM(cc::OverscrollBehavior::Type::kContain, |