blob: c92bb6f2d5d483632e66d209fd9014cb0fc32932 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/style_recalc.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
namespace blink {
bool StyleRecalcChange::TraverseChildren(const Element& element) const {
return RecalcChildren() || RecalcContainerQueryDependent() ||
element.ChildNeedsStyleRecalc();
}
bool StyleRecalcChange::TraversePseudoElements(const Element& element) const {
return UpdatePseudoElements() || RecalcContainerQueryDependent() ||
element.ChildNeedsStyleRecalc();
}
bool StyleRecalcChange::TraverseChild(const Node& node) const {
return ShouldRecalcStyleFor(node) || node.ChildNeedsStyleRecalc() ||
RecalcContainerQueryDependent();
}
bool StyleRecalcChange::ShouldRecalcStyleFor(const Node& node) const {
if (RecalcChildren())
return true;
if (node.NeedsStyleRecalc())
return true;
if (node.GetForceReattachLayoutTree())
return true;
// Early exit before getting the computed style.
if (propagate_ != kClearEnsured && !RecalcContainerQueryDependent())
return false;
if (const ComputedStyle* old_style = node.GetComputedStyle()) {
return (propagate_ == kClearEnsured &&
old_style->IsEnsuredInDisplayNone()) ||
(RecalcContainerQueryDependent() &&
old_style->DependsOnContainerQueries());
}
// Container queries may affect display:none elements, and we since we store
// that dependency on ComputedStyle we need to recalc style for display:none
// subtree roots.
return RecalcContainerQueryDependent();
}
bool StyleRecalcChange::ShouldUpdatePseudoElement(
const PseudoElement& pseudo_element) const {
if (UpdatePseudoElements())
return true;
if (pseudo_element.NeedsStyleRecalc())
return true;
return RecalcContainerQueryDependent() &&
pseudo_element.ComputedStyleRef().DependsOnContainerQueries();
}
bool StyleRecalcChange::RecalcContainerQueryDependentChildren(
const Element& element) const {
// We are at the container root for a container query recalc.
if (propagate_ == kRecalcContainerQueryDependent)
return true;
if (!RecalcContainerQueryDependent())
return false;
// Don't traverse into children if we hit a descendant container while
// recalculating container queries. If the queries for this container also
// changes, we will enter another container query recalc for this subtree from
// layout.
if (LayoutObject* layout_object = element.GetLayoutObject())
return !layout_object->IsContainerForContainerQueries();
return true;
}
StyleRecalcContext StyleRecalcContext::FromAncestors(Element& element) {
Element* ancestor = &element;
// TODO(crbug.com/1145970): Avoid this work if we're not inside a container.
while ((ancestor = DynamicTo<Element>(
LayoutTreeBuilderTraversal::Parent(*ancestor)))) {
ContainerQueryEvaluator* evaluator = ancestor->GetContainerQueryEvaluator();
if (evaluator)
return StyleRecalcContext{evaluator};
}
return StyleRecalcContext();
}
} // namespace blink