1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ContainStyleScopeManager.h"
9 #include "mozilla/ComputedStyle.h"
10 #include "mozilla/ServoStyleSet.h"
11 #include "CounterStyleManager.h"
12 #include "nsCounterManager.h"
13 #include "nsIContent.h"
14 #include "nsIContentInlines.h"
16 #include "nsLayoutUtils.h"
17 #include "nsQuoteList.h"
21 nsGenConNode
* ContainStyleScope::GetPrecedingElementInGenConList(
22 nsGenConList
* aList
) {
23 auto IsAfter
= [this](nsGenConNode
* aNode
) {
24 return nsLayoutUtils::CompareTreePosition(
25 mContent
, aNode
->mPseudoFrame
->GetContent()) > 0;
27 return aList
->BinarySearch(IsAfter
);
30 void ContainStyleScope::RecalcAllCounters() {
31 GetCounterManager().RecalcAll();
32 for (auto* child
: mChildren
) {
33 child
->RecalcAllCounters();
37 void ContainStyleScope::RecalcAllQuotes() {
38 GetQuoteList().RecalcAll();
39 for (auto* child
: mChildren
) {
40 child
->RecalcAllQuotes();
44 ContainStyleScope
& ContainStyleScopeManager::GetOrCreateScopeForContent(
45 nsIContent
* aContent
) {
46 for (; aContent
; aContent
= aContent
->GetFlattenedTreeParent()) {
47 auto* element
= dom::Element::FromNode(*aContent
);
52 // Do not allow elements which have `display: contents` to create style
53 // boundaries. See https://github.com/w3c/csswg-drafts/issues/7392.
54 if (element
->IsDisplayContents()) {
58 const auto* style
= Servo_Element_GetMaybeOutOfDateStyle(element
);
63 if (!style
->SelfOrAncestorHasContainStyle()) {
64 return GetRootScope();
67 if (!style
->StyleDisplay()->IsContainStyle()) {
71 if (auto* scope
= mScopes
.Get(aContent
)) {
76 GetOrCreateScopeForContent(aContent
->GetFlattenedTreeParent());
77 return *mScopes
.InsertOrUpdate(
78 aContent
, MakeUnique
<ContainStyleScope
>(this, &parentScope
, aContent
));
81 return GetRootScope();
84 ContainStyleScope
& ContainStyleScopeManager::GetScopeForContent(
85 nsIContent
* aContent
) {
88 if (auto* element
= dom::Element::FromNode(*aContent
)) {
89 if (const auto* style
= Servo_Element_GetMaybeOutOfDateStyle(element
)) {
90 if (!style
->SelfOrAncestorHasContainStyle()) {
91 return GetRootScope();
96 for (; aContent
; aContent
= aContent
->GetFlattenedTreeParent()) {
97 if (auto* scope
= mScopes
.Get(aContent
)) {
102 return GetRootScope();
105 void ContainStyleScopeManager::Clear() {
106 GetRootScope().GetQuoteList().Clear();
107 GetRootScope().GetCounterManager().Clear();
109 DestroyScope(&GetRootScope());
110 MOZ_DIAGNOSTIC_ASSERT(mScopes
.IsEmpty(),
111 "Destroying the root scope should destroy all scopes.");
114 void ContainStyleScopeManager::DestroyScopesFor(nsIFrame
* aFrame
) {
115 if (auto* scope
= mScopes
.Get(aFrame
->GetContent())) {
120 void ContainStyleScopeManager::DestroyScope(ContainStyleScope
* aScope
) {
121 // Deleting a scope modifies the array of children in its parent, so we don't
122 // use an iterator here.
123 while (!aScope
->GetChildren().IsEmpty()) {
124 DestroyScope(aScope
->GetChildren().ElementAt(0));
126 mScopes
.Remove(aScope
->GetContent());
129 bool ContainStyleScopeManager::DestroyCounterNodesFor(nsIFrame
* aFrame
) {
131 for (auto* scope
= &GetScopeForContent(aFrame
->GetContent()); scope
;
132 scope
= scope
->GetParent()) {
133 result
|= scope
->GetCounterManager().DestroyNodesFor(aFrame
);
138 bool ContainStyleScopeManager::AddCounterChanges(nsIFrame
* aNewFrame
) {
139 return GetOrCreateScopeForContent(
140 aNewFrame
->GetContent()->GetFlattenedTreeParent())
142 .AddCounterChanges(aNewFrame
);
145 nsCounterList
* ContainStyleScopeManager::GetOrCreateCounterList(
146 dom::Element
& aElement
, nsAtom
* aCounterName
) {
147 return GetOrCreateScopeForContent(&aElement
)
149 .GetOrCreateCounterList(aCounterName
);
152 bool ContainStyleScopeManager::CounterDirty(nsAtom
* aCounterName
) {
153 return mDirtyCounters
.Contains(aCounterName
);
156 void ContainStyleScopeManager::SetCounterDirty(nsAtom
* aCounterName
) {
157 mDirtyCounters
.Insert(aCounterName
);
160 void ContainStyleScopeManager::RecalcAllCounters() {
161 GetRootScope().RecalcAllCounters();
162 mDirtyCounters
.Clear();
165 #if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
166 void ContainStyleScopeManager::DumpCounters() {
167 GetRootScope().GetCounterManager().Dump();
168 for (auto& entry
: mScopes
) {
169 entry
.GetWeak()->GetCounterManager().Dump();
175 static bool GetFirstCounterValueForScopeAndFrame(ContainStyleScope
* aScope
,
177 CounterValue
& aOrdinal
) {
178 if (aScope
->GetCounterManager().GetFirstCounterValueForFrame(aFrame
,
182 for (auto* child
: aScope
->GetChildren()) {
183 if (GetFirstCounterValueForScopeAndFrame(child
, aFrame
, aOrdinal
)) {
191 void ContainStyleScopeManager::GetSpokenCounterText(nsIFrame
* aFrame
,
193 CounterValue ordinal
= 1;
194 GetFirstCounterValueForScopeAndFrame(&GetRootScope(), aFrame
, ordinal
);
196 CounterStyle
* counterStyle
=
197 aFrame
->PresContext()->CounterStyleManager()->ResolveCounterStyle(
198 aFrame
->StyleList()->mCounterStyle
);
201 counterStyle
->GetSpokenCounterText(ordinal
, aFrame
->GetWritingMode(), text
,
205 if (!counterStyle
->IsNone()) {
209 counterStyle
->GetPrefix(aText
);
212 counterStyle
->GetSuffix(suffix
);
218 void ContainStyleScopeManager::SetAllCountersDirty() {
219 GetRootScope().GetCounterManager().SetAllDirty();
220 for (auto& entry
: mScopes
) {
221 entry
.GetWeak()->GetCounterManager().SetAllDirty();
225 bool ContainStyleScopeManager::DestroyQuoteNodesFor(nsIFrame
* aFrame
) {
227 for (auto* scope
= &GetScopeForContent(aFrame
->GetContent()); scope
;
228 scope
= scope
->GetParent()) {
229 result
|= scope
->GetQuoteList().DestroyNodesFor(aFrame
);
234 nsQuoteList
* ContainStyleScopeManager::QuoteListFor(dom::Element
& aElement
) {
235 return &GetOrCreateScopeForContent(&aElement
).GetQuoteList();
238 void ContainStyleScopeManager::RecalcAllQuotes() {
239 GetRootScope().RecalcAllQuotes();
242 } // namespace mozilla