mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-02-18 21:30:42 +00:00
#387: pulled nsGenConList.* with relevant deps up to mozilla-central
This commit is contained in:
parent
922a327382
commit
b1831fc750
@ -186,11 +186,7 @@ nsCounterList::RecalcAll()
|
||||
{
|
||||
mDirty = false;
|
||||
|
||||
nsCounterNode *node = First();
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
do {
|
||||
for (nsCounterNode* node = First(); node; node = Next(node)) {
|
||||
SetScope(node);
|
||||
node->Calc(this);
|
||||
|
||||
@ -205,7 +201,7 @@ nsCounterList::RecalcAll()
|
||||
useNode->mText->SetData(text);
|
||||
}
|
||||
}
|
||||
} while ((node = Next(node)) != First());
|
||||
}
|
||||
}
|
||||
|
||||
nsCounterManager::nsCounterManager()
|
||||
@ -291,21 +287,17 @@ nsCounterManager::SetAllCounterStylesDirty()
|
||||
{
|
||||
for (auto iter = mNames.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCounterList* list = iter.UserData();
|
||||
nsCounterNode* first = list->First();
|
||||
if (first) {
|
||||
bool changed = false;
|
||||
nsCounterNode* node = first;
|
||||
do {
|
||||
if (node->mType == nsCounterNode::USE) {
|
||||
node->UseNode()->SetCounterStyleDirty();
|
||||
changed = true;
|
||||
}
|
||||
} while ((node = list->Next(node)) != first);
|
||||
|
||||
if (changed) {
|
||||
list->SetDirty();
|
||||
bool changed = false;
|
||||
for (nsCounterNode* node = list->First(); node; node = list->Next(node)) {
|
||||
if (node->mType == nsCounterNode::USE) {
|
||||
node->UseNode()->SetCounterStyleDirty();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
list->SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,32 +319,29 @@ nsCounterManager::DestroyNodesFor(nsIFrame *aFrame)
|
||||
void
|
||||
nsCounterManager::Dump()
|
||||
{
|
||||
printf("\n\nCounter Manager Lists:\n");
|
||||
for (auto iter = mNames.Iter(); !iter.Done(); iter.Next()) {
|
||||
printf("Counter named \"%s\":\n",
|
||||
NS_ConvertUTF16toUTF8(iter.Key()).get());
|
||||
printf("\n\nCounter Manager Lists:\n");
|
||||
for (auto iter = mNames.Iter(); !iter.Done(); iter.Next()) {
|
||||
printf("Counter named \"%s\":\n",
|
||||
NS_ConvertUTF16toUTF8(iter.Key()).get());
|
||||
|
||||
nsCounterList* list = iter.UserData();
|
||||
nsCounterNode* node = list->First();
|
||||
if (node) {
|
||||
int32_t i = 0;
|
||||
do {
|
||||
const char* types[] = { "RESET", "INCREMENT", "USE" };
|
||||
printf(" Node #%d @%p frame=%p index=%d type=%s valAfter=%d\n"
|
||||
" scope-start=%p scope-prev=%p",
|
||||
i++, (void*)node, (void*)node->mPseudoFrame,
|
||||
node->mContentIndex, types[node->mType],
|
||||
node->mValueAfter, (void*)node->mScopeStart,
|
||||
(void*)node->mScopePrev);
|
||||
if (node->mType == nsCounterNode::USE) {
|
||||
nsAutoString text;
|
||||
node->UseNode()->GetText(text);
|
||||
printf(" text=%s", NS_ConvertUTF16toUTF8(text).get());
|
||||
}
|
||||
printf("\n");
|
||||
} while ((node = list->Next(node)) != list->First());
|
||||
}
|
||||
nsCounterList* list = iter.UserData();
|
||||
int32_t i = 0;
|
||||
for (nsCounterNode* node = list->First(); node; node = list->Next(node)) {
|
||||
const char* types[] = { "RESET", "INCREMENT", "USE" };
|
||||
printf(" Node #%d @%p frame=%p index=%d type=%s valAfter=%d\n"
|
||||
" scope-start=%p scope-prev=%p",
|
||||
i++, (void*)node, (void*)node->mPseudoFrame,
|
||||
node->mContentIndex, types[node->mType],
|
||||
node->mValueAfter, (void*)node->mScopeStart,
|
||||
(void*)node->mScopePrev);
|
||||
if (node->mType == nsCounterNode::USE) {
|
||||
nsAutoString text;
|
||||
node->UseNode()->GetText(text);
|
||||
printf(" text=%s", NS_ConvertUTF16toUTF8(text).get());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -187,7 +187,7 @@ public:
|
||||
}
|
||||
|
||||
nsCounterNode* First() {
|
||||
return static_cast<nsCounterNode*>(mFirstNode);
|
||||
return static_cast<nsCounterNode*>(mList.getFirst());
|
||||
}
|
||||
|
||||
static nsCounterNode* Next(nsCounterNode* aNode) {
|
||||
|
@ -13,55 +13,39 @@
|
||||
void
|
||||
nsGenConList::Clear()
|
||||
{
|
||||
//Delete entire list
|
||||
if (!mFirstNode)
|
||||
return;
|
||||
for (nsGenConNode *node = Next(mFirstNode); node != mFirstNode;
|
||||
node = Next(mFirstNode))
|
||||
{
|
||||
Remove(node);
|
||||
// Delete entire list.
|
||||
mNodes.Clear();
|
||||
while (nsGenConNode* node = mList.popFirst()) {
|
||||
delete node;
|
||||
}
|
||||
delete mFirstNode;
|
||||
|
||||
mFirstNode = nullptr;
|
||||
mSize = 0;
|
||||
mLastInserted = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
nsGenConList::DestroyNodesFor(nsIFrame* aFrame)
|
||||
{
|
||||
if (!mFirstNode)
|
||||
return false; // list empty
|
||||
nsGenConNode* node;
|
||||
bool destroyed = false;
|
||||
while (mFirstNode->mPseudoFrame == aFrame) {
|
||||
destroyed = true;
|
||||
node = Next(mFirstNode);
|
||||
bool isLastNode = node == mFirstNode; // before they're dangling
|
||||
Remove(mFirstNode);
|
||||
delete mFirstNode;
|
||||
if (isLastNode) {
|
||||
mFirstNode = nullptr;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
mFirstNode = node;
|
||||
}
|
||||
// This algorithm relies on the invariant that nodes of a frame are
|
||||
// put contiguously in the linked list. This is guaranteed because
|
||||
// each frame is mapped to only one (nsIContent, pseudoType) pair,
|
||||
// and the nodes in the linked list are put in the tree order based
|
||||
// on that pair and offset inside frame.
|
||||
nsGenConNode* node = mNodes.GetAndRemove(aFrame).valueOr(nullptr);
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
node = Next(mFirstNode);
|
||||
while (node != mFirstNode) {
|
||||
if (node->mPseudoFrame == aFrame) {
|
||||
destroyed = true;
|
||||
nsGenConNode *nextNode = Next(node);
|
||||
Remove(node);
|
||||
delete node;
|
||||
node = nextNode;
|
||||
} else {
|
||||
node = Next(node);
|
||||
}
|
||||
MOZ_ASSERT(node->mPseudoFrame == aFrame);
|
||||
|
||||
while (node && node->mPseudoFrame == aFrame) {
|
||||
nsGenConNode* nextNode = Next(node);
|
||||
Destroy(node);
|
||||
node = nextNode;
|
||||
}
|
||||
return destroyed;
|
||||
|
||||
// Modification of the list invalidates the cached pointer.
|
||||
mLastInserted = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,62 +102,101 @@ nsGenConList::NodeAfter(const nsGenConNode* aNode1, const nsGenConNode* aNode2)
|
||||
// XXX Switch to the frame version of DoCompareTreePosition?
|
||||
int32_t cmp = nsLayoutUtils::DoCompareTreePosition(content1, content2,
|
||||
pseudoType1, -pseudoType2);
|
||||
NS_ASSERTION(cmp != 0, "same content, different frames");
|
||||
MOZ_ASSERT(cmp != 0, "same content, different frames");
|
||||
return cmp > 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenConList::Insert(nsGenConNode* aNode)
|
||||
{
|
||||
if (mFirstNode) {
|
||||
// Check for append.
|
||||
if (NodeAfter(aNode, Prev(mFirstNode))) {
|
||||
PR_INSERT_BEFORE(aNode, mFirstNode);
|
||||
}
|
||||
else {
|
||||
// Binary search.
|
||||
// Check for append.
|
||||
if (mList.isEmpty() || NodeAfter(aNode, mList.getLast())) {
|
||||
mList.insertBack(aNode);
|
||||
} else if (mLastInserted && mLastInserted != mList.getLast() &&
|
||||
NodeAfter(aNode, mLastInserted) &&
|
||||
NodeAfter(Next(mLastInserted), aNode)) {
|
||||
// Fast path for inserting many consecutive nodes in one place
|
||||
mLastInserted->setNext(aNode);
|
||||
} else {
|
||||
// Binary search.
|
||||
|
||||
// the range of indices at which |aNode| could end up.
|
||||
// (We already know it can't be at index mSize.)
|
||||
uint32_t first = 0, last = mSize - 1;
|
||||
// the range of indices at which |aNode| could end up.
|
||||
// (We already know it can't be at index mSize.)
|
||||
uint32_t first = 0, last = mSize - 1;
|
||||
|
||||
// A cursor to avoid walking more than the length of the list.
|
||||
nsGenConNode *curNode = Prev(mFirstNode);
|
||||
uint32_t curIndex = mSize - 1;
|
||||
// A cursor to avoid walking more than the length of the list.
|
||||
nsGenConNode* curNode = mList.getLast();
|
||||
uint32_t curIndex = mSize - 1;
|
||||
|
||||
while (first != last) {
|
||||
uint32_t test = (first + last) / 2;
|
||||
if (last == curIndex) {
|
||||
for ( ; curIndex != test; --curIndex)
|
||||
curNode = Prev(curNode);
|
||||
} else {
|
||||
for ( ; curIndex != test; ++curIndex)
|
||||
curNode = Next(curNode);
|
||||
}
|
||||
|
||||
if (NodeAfter(aNode, curNode)) {
|
||||
first = test + 1;
|
||||
// if we exit the loop, we need curNode to be right
|
||||
++curIndex;
|
||||
while (first != last) {
|
||||
uint32_t test = (first + last) / 2;
|
||||
if (last == curIndex) {
|
||||
for ( ; curIndex != test; --curIndex)
|
||||
curNode = Prev(curNode);
|
||||
} else {
|
||||
for ( ; curIndex != test; ++curIndex)
|
||||
curNode = Next(curNode);
|
||||
} else {
|
||||
last = test;
|
||||
}
|
||||
}
|
||||
PR_INSERT_BEFORE(aNode, curNode);
|
||||
if (curNode == mFirstNode) {
|
||||
mFirstNode = aNode;
|
||||
|
||||
if (NodeAfter(aNode, curNode)) {
|
||||
first = test + 1;
|
||||
// if we exit the loop, we need curNode to be right
|
||||
++curIndex;
|
||||
curNode = Next(curNode);
|
||||
} else {
|
||||
last = test;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// initialize list with first node
|
||||
PR_INIT_CLIST(aNode);
|
||||
mFirstNode = aNode;
|
||||
curNode->setPrevious(aNode);
|
||||
}
|
||||
++mSize;
|
||||
|
||||
NS_ASSERTION(aNode == mFirstNode || NodeAfter(aNode, Prev(aNode)),
|
||||
mLastInserted = aNode;
|
||||
|
||||
// Set the mapping only if it is the first node of the frame.
|
||||
// The DEBUG blocks below are for ensuring the invariant required by
|
||||
// nsGenConList::DestroyNodesFor. See comment there.
|
||||
if (IsFirst(aNode) ||
|
||||
Prev(aNode)->mPseudoFrame != aNode->mPseudoFrame) {
|
||||
#ifdef DEBUG
|
||||
if (nsGenConNode* oldFrameFirstNode = mNodes.Get(aNode->mPseudoFrame)) {
|
||||
MOZ_ASSERT(Next(aNode) == oldFrameFirstNode,
|
||||
"oldFrameFirstNode should now be immediately after "
|
||||
"the newly-inserted one.");
|
||||
} else {
|
||||
// If the node is not the only node in the list.
|
||||
if (!IsFirst(aNode) || !IsLast(aNode)) {
|
||||
nsGenConNode* nextNode = Next(aNode);
|
||||
MOZ_ASSERT(!nextNode || nextNode->mPseudoFrame != aNode->mPseudoFrame,
|
||||
"There shouldn't exist any node for this frame.");
|
||||
// If the node is neither the first nor the last node
|
||||
if (!IsFirst(aNode) && !IsLast(aNode)) {
|
||||
MOZ_ASSERT(Prev(aNode)->mPseudoFrame != nextNode->mPseudoFrame,
|
||||
"New node should not break contiguity of nodes of "
|
||||
"the same frame.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mNodes.Put(aNode->mPseudoFrame, aNode);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsGenConNode* frameFirstNode = mNodes.Get(aNode->mPseudoFrame);
|
||||
MOZ_ASSERT(frameFirstNode, "There should exist node map for the frame.");
|
||||
for (nsGenConNode* curNode = Prev(aNode);
|
||||
curNode != frameFirstNode; curNode = Prev(curNode)) {
|
||||
MOZ_ASSERT(curNode->mPseudoFrame == aNode->mPseudoFrame,
|
||||
"Every node between frameFirstNode and the new node inserted "
|
||||
"should refer to the same frame.");
|
||||
MOZ_ASSERT(!IsFirst(curNode),
|
||||
"The newly-inserted node should be in a contiguous run after "
|
||||
"frameFirstNode, thus frameFirstNode should be reached before "
|
||||
"the first node of mList.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_ASSERTION(IsFirst(aNode) || NodeAfter(aNode, Prev(aNode)),
|
||||
"sorting error");
|
||||
NS_ASSERTION(IsLast(aNode) || NodeAfter(Next(aNode), aNode),
|
||||
"sorting error");
|
||||
|
@ -8,15 +8,15 @@
|
||||
#ifndef nsGenConList_h___
|
||||
#define nsGenConList_h___
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "prclist.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsTextNode.h"
|
||||
|
||||
class nsGenConList;
|
||||
|
||||
struct nsGenConNode : public PRCList {
|
||||
struct nsGenConNode : public mozilla::LinkedListElement<nsGenConNode> {
|
||||
// The wrapper frame for all of the pseudo-element's content. This
|
||||
// frame generally has useful style data and has the
|
||||
// NS_FRAME_GENERATED_CONTENT bit set (so we use it to track removal),
|
||||
@ -51,7 +51,7 @@ struct nsGenConNode : public PRCList {
|
||||
* @return true iff this marked the list dirty
|
||||
*/
|
||||
virtual bool InitTextFrame(nsGenConList* aList, nsIFrame* aPseudoFrame,
|
||||
nsIFrame* aTextFrame)
|
||||
nsIFrame* aTextFrame)
|
||||
{
|
||||
mPseudoFrame = aPseudoFrame;
|
||||
CheckFrameAssertions();
|
||||
@ -82,28 +82,55 @@ protected:
|
||||
|
||||
class nsGenConList {
|
||||
protected:
|
||||
nsGenConNode* mFirstNode;
|
||||
mozilla::LinkedList<nsGenConNode> mList;
|
||||
uint32_t mSize;
|
||||
|
||||
public:
|
||||
nsGenConList() : mFirstNode(nullptr), mSize(0) {}
|
||||
nsGenConList() : mSize(0), mLastInserted(nullptr) {}
|
||||
~nsGenConList() { Clear(); }
|
||||
void Clear();
|
||||
static nsGenConNode* Next(nsGenConNode* aNode) {
|
||||
return static_cast<nsGenConNode*>(PR_NEXT_LINK(aNode));
|
||||
MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
|
||||
return aNode->getNext();
|
||||
}
|
||||
static nsGenConNode* Prev(nsGenConNode* aNode) {
|
||||
return static_cast<nsGenConNode*>(PR_PREV_LINK(aNode));
|
||||
MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
|
||||
return aNode->getPrevious();
|
||||
}
|
||||
void Insert(nsGenConNode* aNode);
|
||||
// returns whether any nodes have been destroyed
|
||||
bool DestroyNodesFor(nsIFrame* aFrame); //destroy all nodes with aFrame as parent
|
||||
|
||||
// Destroy all nodes with aFrame as parent. Returns true if some nodes
|
||||
// have been destroyed; otherwise false.
|
||||
bool DestroyNodesFor(nsIFrame* aFrame);
|
||||
|
||||
// Return true if |aNode1| is after |aNode2|.
|
||||
static bool NodeAfter(const nsGenConNode* aNode1,
|
||||
const nsGenConNode* aNode2);
|
||||
const nsGenConNode* aNode2);
|
||||
|
||||
void Remove(nsGenConNode* aNode) { PR_REMOVE_LINK(aNode); mSize--; }
|
||||
bool IsLast(nsGenConNode* aNode) { return (Next(aNode) == mFirstNode); }
|
||||
bool IsFirst(nsGenConNode* aNode) {
|
||||
MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
|
||||
return aNode == mList.getFirst();
|
||||
}
|
||||
|
||||
bool IsLast(nsGenConNode* aNode) {
|
||||
MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
|
||||
return aNode == mList.getLast();
|
||||
}
|
||||
|
||||
private:
|
||||
void Destroy(nsGenConNode* aNode)
|
||||
{
|
||||
MOZ_ASSERT(aNode, "aNode cannot be nullptr!");
|
||||
delete aNode;
|
||||
mSize--;
|
||||
}
|
||||
|
||||
// Map from frame to the first nsGenConNode of it in the list.
|
||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, nsGenConNode*> mNodes;
|
||||
|
||||
// A weak pointer to the node most recently inserted, used to avoid repeated
|
||||
// list traversals in Insert().
|
||||
nsGenConNode* mLastInserted;
|
||||
};
|
||||
|
||||
#endif /* nsGenConList_h___ */
|
||||
|
@ -73,20 +73,13 @@ nsQuoteList::Calc(nsQuoteNode* aNode)
|
||||
void
|
||||
nsQuoteList::RecalcAll()
|
||||
{
|
||||
nsQuoteNode *node = FirstNode();
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
do {
|
||||
for (nsQuoteNode* node = FirstNode(); node; node = Next(node)) {
|
||||
int32_t oldDepth = node->mDepthBefore;
|
||||
Calc(node);
|
||||
|
||||
if (node->mDepthBefore != oldDepth && node->mText && node->IsRealQuote())
|
||||
node->mText->SetData(*node->Text());
|
||||
|
||||
// Next node
|
||||
node = Next(node);
|
||||
} while (node != FirstNode());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -94,11 +87,7 @@ void
|
||||
nsQuoteList::PrintChain()
|
||||
{
|
||||
printf("Chain: \n");
|
||||
if (!FirstNode()) {
|
||||
return;
|
||||
}
|
||||
nsQuoteNode* node = FirstNode();
|
||||
do {
|
||||
for (nsQuoteNode* node = FirstNode(); node; node = Next(node)) {
|
||||
printf(" %p %d - ", static_cast<void*>(node), node->mDepthBefore);
|
||||
switch(node->mType) {
|
||||
case (eStyleContentType_OpenQuote):
|
||||
@ -123,7 +112,6 @@ nsQuoteList::PrintChain()
|
||||
printf(" \"%s\",", NS_ConvertUTF16toUTF8(data).get());
|
||||
}
|
||||
printf("\n");
|
||||
node = Next(node);
|
||||
} while (node != FirstNode());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -70,7 +70,7 @@ struct nsQuoteNode : public nsGenConNode {
|
||||
|
||||
class nsQuoteList : public nsGenConList {
|
||||
private:
|
||||
nsQuoteNode* FirstNode() { return static_cast<nsQuoteNode*>(mFirstNode); }
|
||||
nsQuoteNode* FirstNode() { return static_cast<nsQuoteNode*>(mList.getFirst()); }
|
||||
public:
|
||||
// assign the correct |mDepthBefore| value to a node that has been inserted
|
||||
// Should be called immediately after calling |Insert|.
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsBaseHashtable.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
/**
|
||||
* templated hashtable class maps keys to simple datatypes.
|
||||
@ -22,12 +23,36 @@ template<class KeyClass, class DataType>
|
||||
class nsDataHashtable
|
||||
: public nsBaseHashtable<KeyClass, DataType, DataType>
|
||||
{
|
||||
private:
|
||||
typedef nsBaseHashtable<KeyClass, DataType, DataType> BaseClass;
|
||||
|
||||
public:
|
||||
using typename BaseClass::KeyType;
|
||||
using typename BaseClass::EntryType;
|
||||
|
||||
nsDataHashtable() {}
|
||||
explicit nsDataHashtable(uint32_t aInitLength)
|
||||
: nsBaseHashtable<KeyClass, DataType, DataType>(aInitLength)
|
||||
: BaseClass(aInitLength)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value for a key and remove the corresponding entry at
|
||||
* the same time.
|
||||
*
|
||||
* @param aKey the key to retrieve and remove
|
||||
* @return the found value, or Nothing if no entry was found with the
|
||||
* given key.
|
||||
*/
|
||||
mozilla::Maybe<DataType> GetAndRemove(KeyType aKey)
|
||||
{
|
||||
mozilla::Maybe<DataType> value;
|
||||
if (EntryType* ent = this->GetEntry(aKey)) {
|
||||
value.emplace(mozilla::Move(ent->mData));
|
||||
this->RemoveEntry(ent);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // nsDataHashtable_h__
|
||||
|
Loading…
x
Reference in New Issue
Block a user