Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /* base class for nsCounterList and nsQuoteList */
7 :
8 : #ifndef nsGenConList_h___
9 : #define nsGenConList_h___
10 :
11 : #include "mozilla/LinkedList.h"
12 : #include "nsIFrame.h"
13 : #include "nsStyleStruct.h"
14 : #include "nsCSSPseudoElements.h"
15 : #include "nsTextNode.h"
16 :
17 : class nsGenConList;
18 :
19 : struct nsGenConNode : public mozilla::LinkedListElement<nsGenConNode> {
20 : // The wrapper frame for all of the pseudo-element's content. This
21 : // frame generally has useful style data and has the
22 : // NS_FRAME_GENERATED_CONTENT bit set (so we use it to track removal),
23 : // but does not necessarily for |nsCounterChangeNode|s.
24 : nsIFrame* mPseudoFrame;
25 :
26 : // Index within the list of things specified by the 'content' property,
27 : // which is needed to do 'content: open-quote open-quote' correctly,
28 : // and needed for similar cases for counters.
29 : const int32_t mContentIndex;
30 :
31 : // null for 'content:no-open-quote', 'content:no-close-quote' and for
32 : // counter nodes for increments and resets (rather than uses)
33 : RefPtr<nsTextNode> mText;
34 :
35 0 : explicit nsGenConNode(int32_t aContentIndex)
36 0 : : mPseudoFrame(nullptr)
37 0 : , mContentIndex(aContentIndex)
38 : {
39 0 : }
40 :
41 : /**
42 : * Finish initializing the generated content node once we know the
43 : * relevant text frame. This must be called just after
44 : * the textframe has been initialized. This need not be called at all
45 : * for nodes that don't generate text. This will generally set the
46 : * mPseudoFrame, insert the node into aList, and set aTextFrame up
47 : * with the correct text.
48 : * @param aList the list the node belongs to
49 : * @param aPseudoFrame the :before or :after frame
50 : * @param aTextFrame the textframe where the node contents will render
51 : * @return true iff this marked the list dirty
52 : */
53 0 : virtual bool InitTextFrame(nsGenConList* aList, nsIFrame* aPseudoFrame,
54 : nsIFrame* aTextFrame)
55 : {
56 0 : mPseudoFrame = aPseudoFrame;
57 0 : CheckFrameAssertions();
58 0 : return false;
59 : }
60 :
61 0 : virtual ~nsGenConNode() {} // XXX Avoid, perhaps?
62 :
63 : protected:
64 0 : void CheckFrameAssertions() {
65 0 : NS_ASSERTION(mContentIndex <
66 : int32_t(mPseudoFrame->StyleContent()->ContentCount()),
67 : "index out of range");
68 : // We allow negative values of mContentIndex for 'counter-reset' and
69 : // 'counter-increment'.
70 :
71 0 : NS_ASSERTION(mContentIndex < 0 ||
72 : mPseudoFrame->StyleContext()->GetPseudo() ==
73 : nsCSSPseudoElements::before ||
74 : mPseudoFrame->StyleContext()->GetPseudo() ==
75 : nsCSSPseudoElements::after,
76 : "not :before/:after generated content and not counter change");
77 0 : NS_ASSERTION(mContentIndex < 0 ||
78 : mPseudoFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT,
79 : "not generated content and not counter change");
80 0 : }
81 : };
82 :
83 : class nsGenConList {
84 : protected:
85 : mozilla::LinkedList<nsGenConNode> mList;
86 : uint32_t mSize;
87 :
88 : public:
89 28 : nsGenConList() : mSize(0), mLastInserted(nullptr) {}
90 4 : ~nsGenConList() { Clear(); }
91 : void Clear();
92 0 : static nsGenConNode* Next(nsGenConNode* aNode) {
93 0 : MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
94 0 : return aNode->getNext();
95 : }
96 0 : static nsGenConNode* Prev(nsGenConNode* aNode) {
97 0 : MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
98 0 : return aNode->getPrevious();
99 : }
100 : void Insert(nsGenConNode* aNode);
101 :
102 : // Destroy all nodes with aFrame as parent. Returns true if some nodes
103 : // have been destroyed; otherwise false.
104 : bool DestroyNodesFor(nsIFrame* aFrame);
105 :
106 : // Return true if |aNode1| is after |aNode2|.
107 : static bool NodeAfter(const nsGenConNode* aNode1,
108 : const nsGenConNode* aNode2);
109 :
110 0 : bool IsFirst(nsGenConNode* aNode) {
111 0 : MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
112 0 : return aNode == mList.getFirst();
113 : }
114 :
115 0 : bool IsLast(nsGenConNode* aNode) {
116 0 : MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
117 0 : return aNode == mList.getLast();
118 : }
119 :
120 : private:
121 0 : void Destroy(nsGenConNode* aNode)
122 : {
123 0 : MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
124 0 : delete aNode;
125 0 : mSize--;
126 0 : }
127 :
128 : // Map from frame to the first nsGenConNode of it in the list.
129 : nsDataHashtable<nsPtrHashKey<nsIFrame>, nsGenConNode*> mNodes;
130 :
131 : // A weak pointer to the node most recently inserted, used to avoid repeated
132 : // list traversals in Insert().
133 : nsGenConNode* mLastInserted;
134 : };
135 :
136 : #endif /* nsGenConList_h___ */
|