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 nsGenConNodensGenConNode35 explicit nsGenConNode(int32_t aContentIndex) 36 : mPseudoFrame(nullptr) 37 , mContentIndex(aContentIndex) 38 { 39 } 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 */ InitTextFramensGenConNode53 virtual bool InitTextFrame(nsGenConList* aList, nsIFrame* aPseudoFrame, 54 nsIFrame* aTextFrame) 55 { 56 mPseudoFrame = aPseudoFrame; 57 CheckFrameAssertions(); 58 return false; 59 } 60 ~nsGenConNodensGenConNode61 virtual ~nsGenConNode() {} // XXX Avoid, perhaps? 62 63 protected: CheckFrameAssertionsnsGenConNode64 void CheckFrameAssertions() { 65 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 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 NS_ASSERTION(mContentIndex < 0 || 78 mPseudoFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT, 79 "not generated content and not counter change"); 80 } 81 }; 82 83 class nsGenConList { 84 protected: 85 mozilla::LinkedList<nsGenConNode> mList; 86 uint32_t mSize; 87 88 public: nsGenConList()89 nsGenConList() : mSize(0) {} ~nsGenConList()90 ~nsGenConList() { Clear(); } 91 void Clear(); Next(nsGenConNode * aNode)92 static nsGenConNode* Next(nsGenConNode* aNode) { 93 MOZ_ASSERT(aNode, "aNode cannot be nullptr!"); 94 return aNode->getNext(); 95 } Prev(nsGenConNode * aNode)96 static nsGenConNode* Prev(nsGenConNode* aNode) { 97 MOZ_ASSERT(aNode, "aNode cannot be nullptr!"); 98 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 IsFirst(nsGenConNode * aNode)110 bool IsFirst(nsGenConNode* aNode) { 111 MOZ_ASSERT(aNode, "aNode cannot be nullptr!"); 112 return aNode == mList.getFirst(); 113 } 114 IsLast(nsGenConNode * aNode)115 bool IsLast(nsGenConNode* aNode) { 116 MOZ_ASSERT(aNode, "aNode cannot be nullptr!"); 117 return aNode == mList.getLast(); 118 } 119 120 private: Destroy(nsGenConNode * aNode)121 void Destroy(nsGenConNode* aNode) 122 { 123 MOZ_ASSERT(aNode, "aNode cannot be nullptr!"); 124 delete aNode; 125 mSize--; 126 } 127 128 // Map from frame to the first nsGenConNode of it in the list. 129 nsDataHashtable<nsPtrHashKey<nsIFrame>, nsGenConNode*> mNodes; 130 }; 131 132 #endif /* nsGenConList_h___ */ 133