layout/base/nsGenConList.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 // vim:cindent:ts=2:et:sw=2:
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /* base class for nsCounterList and nsQuoteList */
michael@0 8
michael@0 9 #include "nsGenConList.h"
michael@0 10 #include "nsLayoutUtils.h"
michael@0 11 #include "nsIContent.h"
michael@0 12
michael@0 13 void
michael@0 14 nsGenConList::Clear()
michael@0 15 {
michael@0 16 //Delete entire list
michael@0 17 if (!mFirstNode)
michael@0 18 return;
michael@0 19 for (nsGenConNode *node = Next(mFirstNode); node != mFirstNode;
michael@0 20 node = Next(mFirstNode))
michael@0 21 {
michael@0 22 Remove(node);
michael@0 23 delete node;
michael@0 24 }
michael@0 25 delete mFirstNode;
michael@0 26
michael@0 27 mFirstNode = nullptr;
michael@0 28 mSize = 0;
michael@0 29 }
michael@0 30
michael@0 31 bool
michael@0 32 nsGenConList::DestroyNodesFor(nsIFrame* aFrame)
michael@0 33 {
michael@0 34 if (!mFirstNode)
michael@0 35 return false; // list empty
michael@0 36 nsGenConNode* node;
michael@0 37 bool destroyed = false;
michael@0 38 while (mFirstNode->mPseudoFrame == aFrame) {
michael@0 39 destroyed = true;
michael@0 40 node = Next(mFirstNode);
michael@0 41 bool isLastNode = node == mFirstNode; // before they're dangling
michael@0 42 Remove(mFirstNode);
michael@0 43 delete mFirstNode;
michael@0 44 if (isLastNode) {
michael@0 45 mFirstNode = nullptr;
michael@0 46 return true;
michael@0 47 }
michael@0 48 else {
michael@0 49 mFirstNode = node;
michael@0 50 }
michael@0 51 }
michael@0 52 node = Next(mFirstNode);
michael@0 53 while (node != mFirstNode) {
michael@0 54 if (node->mPseudoFrame == aFrame) {
michael@0 55 destroyed = true;
michael@0 56 nsGenConNode *nextNode = Next(node);
michael@0 57 Remove(node);
michael@0 58 delete node;
michael@0 59 node = nextNode;
michael@0 60 } else {
michael@0 61 node = Next(node);
michael@0 62 }
michael@0 63 }
michael@0 64 return destroyed;
michael@0 65 }
michael@0 66
michael@0 67 /**
michael@0 68 * Compute the type of the pseudo and the content for the pseudo that
michael@0 69 * we'll use for comparison purposes.
michael@0 70 * @param aContent the content to use is stored here; it's the element
michael@0 71 * that generated the ::before or ::after content, or (if not for generated
michael@0 72 * content), the frame's own element
michael@0 73 * @return -1 for ::before, +1 for ::after, and 0 otherwise.
michael@0 74 */
michael@0 75 inline int32_t PseudoCompareType(nsIFrame* aFrame, nsIContent** aContent)
michael@0 76 {
michael@0 77 nsIAtom *pseudo = aFrame->StyleContext()->GetPseudo();
michael@0 78 if (pseudo == nsCSSPseudoElements::before) {
michael@0 79 *aContent = aFrame->GetContent()->GetParent();
michael@0 80 return -1;
michael@0 81 }
michael@0 82 if (pseudo == nsCSSPseudoElements::after) {
michael@0 83 *aContent = aFrame->GetContent()->GetParent();
michael@0 84 return 1;
michael@0 85 }
michael@0 86 *aContent = aFrame->GetContent();
michael@0 87 return 0;
michael@0 88 }
michael@0 89
michael@0 90 /* static */ bool
michael@0 91 nsGenConList::NodeAfter(const nsGenConNode* aNode1, const nsGenConNode* aNode2)
michael@0 92 {
michael@0 93 nsIFrame *frame1 = aNode1->mPseudoFrame;
michael@0 94 nsIFrame *frame2 = aNode2->mPseudoFrame;
michael@0 95 if (frame1 == frame2) {
michael@0 96 NS_ASSERTION(aNode2->mContentIndex != aNode1->mContentIndex, "identical");
michael@0 97 return aNode1->mContentIndex > aNode2->mContentIndex;
michael@0 98 }
michael@0 99 nsIContent *content1;
michael@0 100 nsIContent *content2;
michael@0 101 int32_t pseudoType1 = PseudoCompareType(frame1, &content1);
michael@0 102 int32_t pseudoType2 = PseudoCompareType(frame2, &content2);
michael@0 103 if (pseudoType1 == 0 || pseudoType2 == 0) {
michael@0 104 if (content1 == content2) {
michael@0 105 NS_ASSERTION(pseudoType1 != pseudoType2, "identical");
michael@0 106 return pseudoType2 == 0;
michael@0 107 }
michael@0 108 // We want to treat an element as coming before its :before (preorder
michael@0 109 // traversal), so treating both as :before now works.
michael@0 110 if (pseudoType1 == 0) pseudoType1 = -1;
michael@0 111 if (pseudoType2 == 0) pseudoType2 = -1;
michael@0 112 } else {
michael@0 113 if (content1 == content2) {
michael@0 114 NS_ASSERTION(pseudoType1 != pseudoType2, "identical");
michael@0 115 return pseudoType1 == 1;
michael@0 116 }
michael@0 117 }
michael@0 118 // XXX Switch to the frame version of DoCompareTreePosition?
michael@0 119 int32_t cmp = nsLayoutUtils::DoCompareTreePosition(content1, content2,
michael@0 120 pseudoType1, -pseudoType2);
michael@0 121 NS_ASSERTION(cmp != 0, "same content, different frames");
michael@0 122 return cmp > 0;
michael@0 123 }
michael@0 124
michael@0 125 void
michael@0 126 nsGenConList::Insert(nsGenConNode* aNode)
michael@0 127 {
michael@0 128 if (mFirstNode) {
michael@0 129 // Check for append.
michael@0 130 if (NodeAfter(aNode, Prev(mFirstNode))) {
michael@0 131 PR_INSERT_BEFORE(aNode, mFirstNode);
michael@0 132 }
michael@0 133 else {
michael@0 134 // Binary search.
michael@0 135
michael@0 136 // the range of indices at which |aNode| could end up.
michael@0 137 // (We already know it can't be at index mSize.)
michael@0 138 uint32_t first = 0, last = mSize - 1;
michael@0 139
michael@0 140 // A cursor to avoid walking more than the length of the list.
michael@0 141 nsGenConNode *curNode = Prev(mFirstNode);
michael@0 142 uint32_t curIndex = mSize - 1;
michael@0 143
michael@0 144 while (first != last) {
michael@0 145 uint32_t test = (first + last) / 2;
michael@0 146 if (last == curIndex) {
michael@0 147 for ( ; curIndex != test; --curIndex)
michael@0 148 curNode = Prev(curNode);
michael@0 149 } else {
michael@0 150 for ( ; curIndex != test; ++curIndex)
michael@0 151 curNode = Next(curNode);
michael@0 152 }
michael@0 153
michael@0 154 if (NodeAfter(aNode, curNode)) {
michael@0 155 first = test + 1;
michael@0 156 // if we exit the loop, we need curNode to be right
michael@0 157 ++curIndex;
michael@0 158 curNode = Next(curNode);
michael@0 159 } else {
michael@0 160 last = test;
michael@0 161 }
michael@0 162 }
michael@0 163 PR_INSERT_BEFORE(aNode, curNode);
michael@0 164 if (curNode == mFirstNode) {
michael@0 165 mFirstNode = aNode;
michael@0 166 }
michael@0 167 }
michael@0 168 }
michael@0 169 else {
michael@0 170 // initialize list with first node
michael@0 171 PR_INIT_CLIST(aNode);
michael@0 172 mFirstNode = aNode;
michael@0 173 }
michael@0 174 ++mSize;
michael@0 175
michael@0 176 NS_ASSERTION(aNode == mFirstNode || NodeAfter(aNode, Prev(aNode)),
michael@0 177 "sorting error");
michael@0 178 NS_ASSERTION(IsLast(aNode) || NodeAfter(Next(aNode), aNode),
michael@0 179 "sorting error");
michael@0 180 }

mercurial