summaryrefslogtreecommitdiffstats
path: root/layout/base/ContainStyleScopeManager.h
blob: 890344c93e76c8289e0b65fd44ccd7853aadc871 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef ContainStyleScopeManager_h_
#define ContainStyleScopeManager_h_

#include "nsClassHashtable.h"
#include "nsTHashSet.h"
#include "nsQuoteList.h"
#include "nsCounterManager.h"
#include <memory>

class nsIContent;
class nsAtom;

namespace mozilla {

namespace dom {
class Element;
}

class ContainStyleScopeManager;

/* Implementation of a self-contained `contain: style` scope which manages its
 * own counters and quotes. Since the `counters()` function has read access to
 * other `contain: style` scopes, USE counter nodes may link across `contain:
 * style` scopes. */
class ContainStyleScope final {
 public:
  ContainStyleScope(ContainStyleScopeManager* aManager,
                    ContainStyleScope* aParent, nsIContent* aContent)
      : mQuoteList(this),
        mCounterManager(this),
        mScopeManager(aManager),
        mParent(aParent),
        mContent(aContent) {
    MOZ_ASSERT(aManager);
    if (mParent) {
      mParent->AddChild(this);
    }
  }

  ~ContainStyleScope() {
    if (mParent) {
      mParent->RemoveChild(this);
    }
  }

  nsQuoteList& GetQuoteList() { return mQuoteList; }
  nsCounterManager& GetCounterManager() { return mCounterManager; }
  ContainStyleScopeManager& GetScopeManager() { return *mScopeManager; }
  ContainStyleScope* GetParent() { return mParent; }
  nsIContent* GetContent() { return mContent; }

  void AddChild(ContainStyleScope* aScope) { mChildren.AppendElement(aScope); }
  void RemoveChild(ContainStyleScope* aScope) {
    mChildren.RemoveElement(aScope);
  }
  const nsTArray<ContainStyleScope*>& GetChildren() const { return mChildren; }

  void RecalcAllCounters();
  void RecalcAllQuotes();

  // Find the element in the given nsGenConList that directly precedes
  // the mContent node of this ContainStyleScope in the flat tree. Can
  // return null if no element in the list precedes the content.
  nsGenConNode* GetPrecedingElementInGenConList(nsGenConList*);

 private:
  nsQuoteList mQuoteList;
  nsCounterManager mCounterManager;

  // We are owned by the |mScopeManager|, so this is guaranteed to be a live
  // pointer as long as we are alive as well.
  ContainStyleScopeManager* mScopeManager;

  // Although parent and child relationships are represented as raw pointers
  // here, |mScopeManager| is responsible for managing creation and deletion of
  // all these data structures and also that it happens in the correct order.
  ContainStyleScope* mParent;
  nsTArray<ContainStyleScope*> mChildren;

  // |mContent| is guaranteed to outlive this scope because mScopeManager will
  // delete the scope when the corresponding frame for |mContent| is destroyed.
  nsIContent* mContent;
};

/* Management of the tree `contain: style` scopes. This class ensures that
 * recalculation is done top-down, so that nodes that rely on other nodes in
 * ancestor `contain: style` scopes are calculated properly. */
class ContainStyleScopeManager {
 public:
  ContainStyleScopeManager() : mRootScope(this, nullptr, nullptr) {}
  ContainStyleScope& GetRootScope() { return mRootScope; }
  ContainStyleScope& GetOrCreateScopeForContent(nsIContent*);
  ContainStyleScope& GetScopeForContent(nsIContent*);

  void Clear();

  // If this frame creates a `contain: style` scope, destroy that scope and
  // all of its child scopes.
  void DestroyScopesFor(nsIFrame*);

  // Destroy this scope and all its children starting from the leaf nodes.
  void DestroyScope(ContainStyleScope*);

  bool DestroyCounterNodesFor(nsIFrame*);
  bool AddCounterChanges(nsIFrame* aNewFrame);
  nsCounterList* GetOrCreateCounterList(dom::Element&, nsAtom* aCounterName);

  bool CounterDirty(nsAtom* aCounterName);
  void SetCounterDirty(nsAtom* aCounterName);
  void RecalcAllCounters();
  void SetAllCountersDirty();

  bool DestroyQuoteNodesFor(nsIFrame*);
  nsQuoteList* QuoteListFor(dom::Element&);
  void RecalcAllQuotes();

#if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
  void DumpCounters();
#endif

#ifdef ACCESSIBILITY
  void GetSpokenCounterText(nsIFrame* aFrame, nsAString& aText);
#endif

 private:
  ContainStyleScope mRootScope;
  nsClassHashtable<nsPtrHashKey<nsIContent>, ContainStyleScope> mScopes;
  nsTHashSet<RefPtr<nsAtom>> mDirtyCounters;
};

}  // namespace mozilla

#endif /* ContainStyleScopeManager_h_ */