diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc | 304 |
1 files changed, 191 insertions, 113 deletions
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 7f3d5192c27..cb4b09e0e2e 100644 --- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc @@ -30,10 +30,13 @@ #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" +#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h" #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.h" #include "third_party/blink/renderer/core/animation/css/css_animations.h" +#include "third_party/blink/renderer/core/animation/document_animations.h" #include "third_party/blink/renderer/core/animation/element_animations.h" #include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h" +#include "third_party/blink/renderer/core/css/container_query_evaluator.h" #include "third_party/blink/renderer/core/css/css_default_style_sheets.h" #include "third_party/blink/renderer/core/css/css_font_selector.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" @@ -114,10 +117,20 @@ void SetAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) { // If any changes to CSS Animations were detected, stash the update away for // application after the layout object is updated if we're in the appropriate // scope. - if (!state.AnimationUpdate().IsEmpty()) { - auto& element_animations = element.EnsureElementAnimations(); - element_animations.CssAnimations().SetPendingUpdate( - state.AnimationUpdate()); + if (state.AnimationUpdate().IsEmpty()) + return; + + auto& element_animations = element.EnsureElementAnimations(); + auto& document_animations = state.GetDocument().GetDocumentAnimations(); + + element_animations.CssAnimations().SetPendingUpdate(state.AnimationUpdate()); + + if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) { + if (document_animations.AnimationUpdatesAllowed()) { + state.GetDocument() + .GetDocumentAnimations() + .AddElementWithPendingAnimationUpdate(element); + } } } @@ -127,6 +140,12 @@ bool HasAnimationsOrTransitions(const StyleResolverState& state) { state.GetAnimatingElement()->HasAnimations()); } +bool IsAnimationStyleChange(Element& element) { + if (auto* element_animations = element.GetElementAnimations()) + return element_animations->IsAnimationStyleChange(); + return false; +} + bool ShouldComputeBaseComputedStyle(const ComputedStyle* base_computed_style) { #if DCHECK_IS_ON() // The invariant in the base computed style optimization is that as long as @@ -197,6 +216,25 @@ void MaybeResetCascade(StyleCascade& cascade) { #endif // DCHECK_IS_ON() } +void PreserveTextAutosizingMultiplierIfNeeded( + StyleResolverState& state, + const StyleRequest& style_request) { + const ComputedStyle* old_style = state.GetElement().GetComputedStyle(); + if (!style_request.IsPseudoStyleRequest() && old_style) { + state.Style()->SetTextAutosizingMultiplier( + old_style->TextAutosizingMultiplier()); + } +} + +bool TextAutosizingMultiplierChanged(const StyleResolverState& state, + const ComputedStyle& base_computed_style) { + // Note that |old_style| can be a style replaced by + // TextAutosizer::ApplyMultiplier. + const ComputedStyle* old_style = state.GetElement().GetComputedStyle(); + return old_style && (old_style->TextAutosizingMultiplier() != + base_computed_style.TextAutosizingMultiplier()); +} + } // namespace static CSSPropertyValueSet* LeftToRightDeclaration() { @@ -570,7 +608,7 @@ void StyleResolver::MatchUARules(const Element& element, CSSDefaultStyleSheets::Instance(); if (!print_media_type_) { if (LIKELY(element.IsHTMLElement() || element.IsVTTElement())) { - MatchRuleSet(collector, default_style_sheets.DefaultStyle()); + MatchRuleSet(collector, default_style_sheets.DefaultHtmlStyle()); if (UNLIKELY(IsInMediaUAShadow(element))) { MatchRuleSet(collector, default_style_sheets.DefaultMediaControlsStyle()); @@ -586,7 +624,7 @@ void StyleResolver::MatchUARules(const Element& element, // In quirks mode, we match rules from the quirks user agent sheet. if (GetDocument().InQuirksMode()) - MatchRuleSet(collector, default_style_sheets.DefaultQuirksStyle()); + MatchRuleSet(collector, default_style_sheets.DefaultHtmlQuirksStyle()); // If document uses view source styles (in view source mode or in xml viewer // mode), then we match rules from the view source style sheet. @@ -688,40 +726,19 @@ static ElementAnimations* GetElementAnimations( return state.GetAnimatingElement()->GetElementAnimations(); } -static const ComputedStyle* CachedAnimationBaseComputedStyle( - StyleResolverState& state) { - ElementAnimations* element_animations = GetElementAnimations(state); - if (!element_animations) +static StyleBaseData* GetBaseData(const StyleResolverState& state) { + Element* animating_element = state.GetAnimatingElement(); + if (!animating_element) return nullptr; - - return element_animations->BaseComputedStyle(); + auto* old_style = animating_element->GetComputedStyle(); + return old_style ? old_style->BaseData().get() : nullptr; } -static void UpdateAnimationBaseComputedStyle(StyleResolverState& state, - StyleCascade& cascade, - bool forced_update) { - if (!state.GetAnimatingElement()) - return; - - if (!state.CanCacheBaseStyle()) - return; - - if (forced_update) - state.GetAnimatingElement()->EnsureElementAnimations(); - - ElementAnimations* element_animations = - state.GetAnimatingElement()->GetElementAnimations(); - if (!element_animations) - return; - - if (element_animations->IsAnimationStyleChange() && - element_animations->BaseComputedStyle()) { - return; - } - - std::unique_ptr<CSSBitset> important_set = cascade.GetImportantSet(); - element_animations->UpdateBaseComputedStyle(state.Style(), - std::move(important_set)); +static const ComputedStyle* CachedAnimationBaseComputedStyle( + StyleResolverState& state) { + if (auto* base_data = GetBaseData(state)) + return base_data->GetBaseComputedStyle(); + return nullptr; } static void IncrementResolvedStyleCounters(const StyleRequest& style_request, @@ -753,7 +770,8 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle( SelectorFilterParentScope::EnsureParentStackIsPushed(); - StyleResolverState state(GetDocument(), *element, style_request); + StyleResolverState state(GetDocument(), *element, style_recalc_context, + style_request); STACK_UNINITIALIZED StyleCascade cascade(state); @@ -779,6 +797,22 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle( if (element->IsMathMLElement()) ApplyMathMLCustomStyleProperties(element, state); + } else if (IsHighlightPseudoElement(style_request.pseudo_id)) { + if (element->GetComputedStyle() && + element->GetComputedStyle()->TextShadow() != + state.Style()->TextShadow()) { + // This counts the usage of text-shadow in CSS highlight pseudos. + UseCounter::Count(GetDocument(), + WebFeature::kTextShadowInHighlightPseudo); + if (state.Style()->TextShadow()) { + // This counts the cases in which text-shadow is not "none" in CSS + // highlight pseudos, as the most common use case is using it to disable + // text-shadow, and that won't be need once some painting issues related + // to highlight pseudos are fixed. + UseCounter::Count(GetDocument(), + WebFeature::kTextShadowNotNoneInHighlightPseudo); + } + } } if (Element* animating_element = state.GetAnimatingElement()) @@ -787,6 +821,11 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle( if (state.Style()->HasViewportUnits()) GetDocument().SetHasViewportUnits(); + if (state.Style()->HasContainerRelativeUnits()) { + state.Style()->SetDependsOnContainerQueries(true); + GetDocument().GetStyleEngine().SetUsesContainerRelativeUnits(); + } + if (state.Style()->HasRemUnits()) GetDocument().GetStyleEngine().SetUsesRemUnit(true); @@ -950,16 +989,11 @@ void StyleResolver::ApplyBaseStyle( return; } - if (!style_request.IsPseudoStyleRequest() && element->GetComputedStyle() && - element->GetComputedStyle()->TextAutosizingMultiplier() != - state.Style()->TextAutosizingMultiplier()) { - // Preserve the text autosizing multiplier on style recalc. Autosizer will - // update it during layout if needed. - // NOTE: this must occur before ApplyMatchedProperties for correct - // computation of font-relative lengths. - state.Style()->SetTextAutosizingMultiplier( - element->GetComputedStyle()->TextAutosizingMultiplier()); - } + // Preserve the text autosizing multiplier on style recalc. Autosizer will + // update it during layout if needed. + // NOTE: This must occur before CascadeAndApplyMatchedProperties for correct + // computation of font-relative lengths. + PreserveTextAutosizingMultiplierIfNeeded(state, style_request); CascadeAndApplyMatchedProperties(state, cascade); @@ -981,6 +1015,8 @@ void StyleResolver::ApplyBaseStyle( if (base_is_usable) { DCHECK(animation_base_computed_style); state.SetStyle(ComputedStyle::Clone(*animation_base_computed_style)); + state.StyleRef().SetBaseData( + scoped_refptr<StyleBaseData>(GetBaseData(state))); state.Style()->SetStyleType(style_request.pseudo_id); if (!state.ParentStyle()) { state.SetParentStyle(InitialStyleForElement()); @@ -1001,14 +1037,16 @@ CompositorKeyframeValue* StyleResolver::CreateCompositorKeyframeValueSnapshot( double offset) { // TODO(alancutter): Avoid creating a StyleResolverState just to apply a // single value on a ComputedStyle. - StyleResolverState state(element.GetDocument(), element, + // TOOD(crbug.com/1223030): Propagate a real StyleRecalcContext to handle + // container relative units. + StyleResolverState state(element.GetDocument(), element, StyleRecalcContext(), StyleRequest(parent_style)); state.SetStyle(ComputedStyle::Clone(base_style)); if (value) { STACK_UNINITIALIZED StyleCascade cascade(state); auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>(state.GetParserMode()); - set->SetProperty(property.GetCSSProperty().PropertyID(), *value); + set->SetProperty(property.GetCSSPropertyName(), *value); cascade.MutableMatchResult().FinishAddingUARules(); cascade.MutableMatchResult().FinishAddingUserRules(); cascade.MutableMatchResult().AddMatchedProperties(set); @@ -1028,6 +1066,7 @@ scoped_refptr<const ComputedStyle> StyleResolver::StyleForPage( return initial_style; StyleResolverState state(GetDocument(), *GetDocument().documentElement(), + StyleRecalcContext(), StyleRequest(initial_style.get())); scoped_refptr<ComputedStyle> style = CreateComputedStyle(); @@ -1154,6 +1193,13 @@ StyleResolver::CascadedValuesForElement(Element* element, PseudoId pseudo_id) { return cascade.GetCascadedValues(); } +Element* StyleResolver::FindContainerForElement( + Element* element, + const AtomicString& container_name) { + auto context = StyleRecalcContext::FromAncestors(*element); + return ContainerQueryEvaluator::FindContainer(context, container_name); +} + RuleIndexList* StyleResolver::PseudoCSSRulesForElement( Element* element, PseudoId pseudo_id, @@ -1161,8 +1207,8 @@ RuleIndexList* StyleResolver::PseudoCSSRulesForElement( DCHECK(element); StyleResolverState state(GetDocument(), *element); MatchResult match_result; - // TODO(crbug.com/1145970): Use actual StyleRecalcContext. - StyleRecalcContext style_recalc_context; + StyleRecalcContext style_recalc_context = + StyleRecalcContext::FromAncestors(*element); ElementRuleCollector collector(state.ElementContext(), style_recalc_context, selector_filter_, match_result, state.Style(), EInsideLink::kNotInsideLink); @@ -1223,12 +1269,13 @@ bool StyleResolver::ApplyAnimatedStyle(StyleResolverState& state, DCHECK(animating_element == &element || animating_element->ParentOrShadowHostElement() == element); - if (!HasAnimationsOrTransitions(state)) { - // Ensure that the base computed style is not stale even if not currently - // running an animation or transition. This ensures that any new transitions - // use the correct starting point based on the "before change" style. - UpdateAnimationBaseComputedStyle(state, cascade, false); + if (!HasAnimationsOrTransitions(state)) return false; + + if (!IsAnimationStyleChange(*animating_element) || + !state.StyleRef().BaseData()) { + state.StyleRef().SetBaseData(StyleBaseData::Create( + ComputedStyle::Clone(state.StyleRef()), cascade.GetImportantSet())); } CSSAnimations::CalculateAnimationUpdate( @@ -1237,35 +1284,22 @@ bool StyleResolver::ApplyAnimatedStyle(StyleResolverState& state, CSSAnimations::CalculateCompositorAnimationUpdate( state.AnimationUpdate(), *animating_element, element, *state.Style(), state.ParentStyle(), WasViewportResized()); - CSSAnimations::CalculateTransitionUpdate( - state.AnimationUpdate(), CSSAnimations::PropertyPass::kStandard, - *animating_element, *state.Style()); CSSAnimations::CalculateTransitionUpdate(state.AnimationUpdate(), - CSSAnimations::PropertyPass::kCustom, *animating_element, *state.Style()); CSSAnimations::SnapshotCompositorKeyframes( element, state.AnimationUpdate(), *state.Style(), state.ParentStyle()); - bool has_update = !state.AnimationUpdate().IsEmpty(); - UpdateAnimationBaseComputedStyle(state, cascade, has_update); - - if (!has_update) + if (state.AnimationUpdate().IsEmpty()) return false; - const ActiveInterpolationsMap& standard_animations = - state.AnimationUpdate().ActiveInterpolationsForStandardAnimations(); - const ActiveInterpolationsMap& standard_transitions = - state.AnimationUpdate().ActiveInterpolationsForStandardTransitions(); - const ActiveInterpolationsMap& custom_animations = - state.AnimationUpdate().ActiveInterpolationsForCustomAnimations(); - const ActiveInterpolationsMap& custom_transitions = - state.AnimationUpdate().ActiveInterpolationsForCustomTransitions(); + const ActiveInterpolationsMap& animations = + state.AnimationUpdate().ActiveInterpolationsForAnimations(); + const ActiveInterpolationsMap& transitions = + state.AnimationUpdate().ActiveInterpolationsForTransitions(); - cascade.AddInterpolations(&standard_animations, CascadeOrigin::kAnimation); - cascade.AddInterpolations(&standard_transitions, CascadeOrigin::kTransition); - cascade.AddInterpolations(&custom_animations, CascadeOrigin::kAnimation); - cascade.AddInterpolations(&custom_transitions, CascadeOrigin::kTransition); + cascade.AddInterpolations(&animations, CascadeOrigin::kAnimation); + cascade.AddInterpolations(&transitions, CascadeOrigin::kTransition); CascadeFilter filter; if (state.Style()->StyleType() == kPseudoIdMarker) @@ -1428,10 +1462,11 @@ bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) { return false; ElementAnimations* element_animations = GetElementAnimations(state); - if (!element_animations || !element_animations->BaseComputedStyle()) + if (!element_animations || !element_animations->IsAnimationStyleChange()) return false; - if (!element_animations->IsAnimationStyleChange()) + StyleBaseData* base_data = GetBaseData(state); + if (!base_data || !base_data->GetBaseComputedStyle()) return false; // Animating a custom property can have side effects on other properties @@ -1449,10 +1484,8 @@ bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) { // animation. We cannot use the base computed style optimization in such // cases. if (CSSAnimations::IsAnimatingFontAffectingProperties(element_animations)) { - if (element_animations->BaseComputedStyle() && - element_animations->BaseComputedStyle()->HasFontRelativeUnits()) { + if (base_data->GetBaseComputedStyle()->HasFontRelativeUnits()) return false; - } } // Normally, we apply all active animation effects on top of the style created @@ -1462,11 +1495,16 @@ bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) { // style, we disable the base computed style optimization. // [1] https://drafts.csswg.org/css-cascade-4/#cascade-origin if (CSSAnimations::IsAnimatingStandardProperties( - element_animations, element_animations->BaseImportantSet(), + element_animations, base_data->GetBaseImportantSet(), KeyframeEffect::kDefaultPriority)) { return false; } + if (TextAutosizingMultiplierChanged(state, + *base_data->GetBaseComputedStyle())) { + return false; + } + return true; } @@ -1480,11 +1518,7 @@ const CSSValue* StyleResolver::ComputeValue( state.SetStyle(ComputedStyle::Clone(*base_style)); auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>(state.GetParserMode()); - if (property_name.IsCustomProperty()) { - set->SetProperty(CSSPropertyValue(property_name, value)); - } else { - set->SetProperty(property_name.Id(), value); - } + set->SetProperty(property_name, value); cascade.MutableMatchResult().FinishAddingUARules(); cascade.MutableMatchResult().FinishAddingUserRules(); cascade.MutableMatchResult().AddMatchedProperties(set); @@ -1497,15 +1531,37 @@ const CSSValue* StyleResolver::ComputeValue( *state.Style()); } +FilterOperations StyleResolver::ComputeFilterOperations( + Element* element, + const Font& font, + const CSSValue& filter_value) { + scoped_refptr<ComputedStyle> parent = CreateComputedStyle(); + parent->SetFont(font); + + // TODO(crbug.com/1145970): Use actual StyleRecalcContext. + StyleResolverState state(GetDocument(), *element, StyleRecalcContext(), + StyleRequest(parent.get())); + + state.SetStyle(ComputedStyle::Clone(*parent)); + + StyleBuilder::ApplyProperty(GetCSSPropertyFilter(), state, + ScopedCSSValue(filter_value, &GetDocument())); + + state.LoadPendingResources(); + + return state.Style()->Filter(); +} + scoped_refptr<ComputedStyle> StyleResolver::StyleForInterpolations( Element& element, ActiveInterpolationsMap& interpolations) { + // TODO(crbug.com/1145970): Use actual StyleRecalcContext. + StyleRecalcContext style_recalc_context; StyleRequest style_request; - StyleResolverState state(GetDocument(), element, style_request); + StyleResolverState state(GetDocument(), element, style_recalc_context, + style_request); STACK_UNINITIALIZED StyleCascade cascade(state); - // TODO(crbug.com/1145970): Use actual StyleRecalcContext. - StyleRecalcContext style_recalc_context; ApplyBaseStyle(&element, style_recalc_context, style_request, state, cascade); ApplyInterpolations(state, cascade, interpolations); @@ -1613,7 +1669,8 @@ void StyleResolver::ComputeFont(Element& element, }; // TODO(timloh): This is weird, the style is being used as its own parent - StyleResolverState state(GetDocument(), element, StyleRequest(style)); + StyleResolverState state(GetDocument(), element, StyleRecalcContext(), + StyleRequest(style)); state.SetStyle(style); for (const CSSProperty* property : properties) { @@ -1715,17 +1772,43 @@ bool PropagateScrollSnapStyleToViewport( } // namespace +bool StyleResolver::ShouldStopBodyPropagation(const Element& body_or_html) { + DCHECK(!body_or_html.NeedsReattachLayoutTree()) + << "This method relies on LayoutObject to be attached and up-to-date"; + DCHECK(IsA<HTMLBodyElement>(body_or_html) || + IsA<HTMLHtmlElement>(body_or_html)); + LayoutObject* layout_object = body_or_html.GetLayoutObject(); + if (!layout_object) + return true; + bool contained = layout_object->ShouldApplyAnyContainment(); + if (contained) { + UseCounter::Count(GetDocument(), IsA<HTMLHtmlElement>(body_or_html) + ? WebFeature::kHTMLRootContained + : WebFeature::kHTMLBodyContained); + } + if (!RuntimeEnabledFeatures::CSSContainedBodyPropagationEnabled()) + return false; + DCHECK_EQ(contained, + layout_object->StyleRef().ShouldApplyAnyContainment(body_or_html)) + << "Applied containment must give the same result from LayoutObject and " + "ComputedStyle"; + return contained; +} + void StyleResolver::PropagateStyleToViewport() { DCHECK(GetDocument().InStyleRecalc()); - HTMLBodyElement* body = GetDocument().FirstBodyElement(); Element* document_element = GetDocument().documentElement(); - const ComputedStyle* document_element_style = document_element && document_element->GetLayoutObject() ? document_element->GetComputedStyle() : nullptr; - const ComputedStyle* body_style = - body && body->GetLayoutObject() ? body->GetComputedStyle() : nullptr; + const ComputedStyle* body_style = nullptr; + if (HTMLBodyElement* body = GetDocument().FirstBodyElement()) { + if (!ShouldStopBodyPropagation(*document_element) && + !ShouldStopBodyPropagation(*body)) { + body_style = body->GetComputedStyle(); + } + } const ComputedStyle& viewport_style = GetDocument().GetLayoutView()->StyleRef(); @@ -1751,10 +1834,8 @@ void StyleResolver::PropagateStyleToViewport() { // <html> root element with no background steals background from its first // <body> child. // Also see LayoutBoxModelObject::BackgroundTransfersToView() - if (body_style && IsA<HTMLHtmlElement>(document_element) && - !background_style->HasBackground()) { + if (body_style && !background_style->HasBackground()) background_style = body_style; - } Color background_color = Color::kTransparent; FillLayer background_layers(EFillLayerType::kBackground, true); @@ -1794,22 +1875,17 @@ void StyleResolver::PropagateStyleToViewport() { // Overflow { - const ComputedStyle* overflow_style = nullptr; - if (Element* viewport_element = GetDocument().ViewportDefiningElement()) { - if (viewport_element == body) { + const ComputedStyle* overflow_style = document_element_style; + if (body_style) { + if (document_element_style->IsOverflowVisibleAlongBothAxes()) { overflow_style = body_style; - } else { - DCHECK_EQ(viewport_element, document_element); - overflow_style = document_element_style; - + } else if (body_style->IsScrollContainer()) { // The body element has its own scrolling box, independent from the - // viewport. This is a bit of a weird edge case in the CSS spec that we - // might want to try to eliminate some day (eg. for ScrollTopLeftInterop - // - see http://crbug.com/157855). - if (body_style && body_style->IsScrollContainer()) { - UseCounter::Count(GetDocument(), - WebFeature::kBodyScrollsInAdditionToViewport); - } + // viewport. This is a bit of a weird edge case in the CSS spec that + // we might want to try to eliminate some day (e.g. for + // ScrollTopLeftInterop - see http://crbug.com/157855). + UseCounter::Count(GetDocument(), + WebFeature::kBodyScrollsInAdditionToViewport); } } @@ -1900,6 +1976,8 @@ void StyleResolver::PropagateStyleToViewport() { false); PROPAGATE_FROM(document_element_style, ScrollbarGutter, SetScrollbarGutter, kScrollbarGutterAuto); + PROPAGATE_FROM(document_element_style, ForcedColorAdjust, + SetForcedColorAdjust, EForcedColorAdjust::kAuto); } changed |= PropagateScrollSnapStyleToViewport( |