Bug 1793826 Part 1 - Change nsFrameList::ExtractHead and ExtractTail to take nsIFrame* argument. r=emilio

This is a preparation to remove nsFrameList::FrameLinkEnumerator in the next
part.

Differential Revision: https://phabricator.services.mozilla.com/D158700
This commit is contained in:
Ting-Yu Lin
2022-10-06 06:47:25 +00:00
parent 2c54eaad13
commit 6656a45e40
6 changed files with 93 additions and 122 deletions

View File

@@ -11007,13 +11007,17 @@ nsIFrame* nsCSSFrameConstructor::ConstructInline(
ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
/* aParentIsWrapperAnonBox = */ false, childList);
nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childList);
nsIFrame* firstBlock = nullptr;
if (!aItem.mIsAllInline) {
firstBlockEnumerator.Find(
[](nsIFrame* aFrame) { return aFrame->IsBlockOutside(); });
for (nsIFrame* f : childList) {
if (f->IsBlockOutside()) {
firstBlock = f;
break;
}
}
}
if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) {
if (aItem.mIsAllInline || !firstBlock) {
// This part is easy. We either already know we have no non-inline kids,
// or haven't found any when constructing actual frames (the latter can
// happen only if out-of-flows that we thought had no containing block
@@ -11029,7 +11033,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructInline(
// has to be chopped into several pieces, as described above.
// Grab the first inline's kids
nsFrameList firstInlineKids = childList.ExtractHead(firstBlockEnumerator);
nsFrameList firstInlineKids = childList.ExtractHead(firstBlock);
newFrame->SetInitialChildList(kPrincipalList, firstInlineKids);
aFrameList.AppendFrame(nullptr, newFrame);

View File

@@ -733,10 +733,8 @@ static bool RemoveFirstLine(nsLineList& aFromLines, nsFrameList& aFromFrames,
*aOutLine = removedLine;
nsLineList_iterator next = aFromLines.erase(removedLine);
bool isLastLine = next == aFromLines.end();
nsIFrame* lastFrame = isLastLine ? aFromFrames.LastChild()
: next->mFirstChild->GetPrevSibling();
nsFrameList::FrameLinkEnumerator linkToBreak(aFromFrames, lastFrame);
*aOutFrames = aFromFrames.ExtractHead(linkToBreak);
nsIFrame* firstFrameInNextLine = isLastLine ? nullptr : next->mFirstChild;
*aOutFrames = aFromFrames.ExtractHead(firstFrameInNextLine);
return isLastLine;
}

View File

@@ -1421,26 +1421,21 @@ nsFrameList nsContainerFrame::StealFramesAfter(nsIFrame* aChild) {
NS_ASSERTION(!IsBlockFrame(), "unexpected call");
if (!aChild) {
nsFrameList copy(mFrames);
mFrames.Clear();
return copy;
return std::move(mFrames);
}
for (nsFrameList::FrameLinkEnumerator iter(mFrames); !iter.AtEnd();
iter.Next()) {
if (iter.PrevFrame() == aChild) {
return mFrames.ExtractTail(iter);
for (nsIFrame* f : mFrames) {
if (f == aChild) {
return mFrames.ExtractTail(f->GetNextSibling());
}
}
// We didn't find the child in the principal child list.
// Maybe it's on the overflow list?
nsFrameList* overflowFrames = GetOverflowFrames();
if (overflowFrames) {
for (nsFrameList::FrameLinkEnumerator iter(*overflowFrames); !iter.AtEnd();
iter.Next()) {
if (iter.PrevFrame() == aChild) {
return overflowFrames->ExtractTail(iter);
if (nsFrameList* overflowFrames = GetOverflowFrames()) {
for (nsIFrame* f : *overflowFrames) {
if (f == aChild) {
return mFrames.ExtractTail(f->GetNextSibling());
}
}
}

View File

@@ -163,71 +163,50 @@ nsFrameList::Slice nsFrameList::InsertFrames(nsContainerFrame* aParent,
return Slice(*this, firstNewFrame, nextSibling);
}
nsFrameList nsFrameList::ExtractHead(FrameLinkEnumerator& aLink) {
MOZ_ASSERT(&aLink.List() == this, "Unexpected list");
MOZ_ASSERT(!aLink.PrevFrame() ||
aLink.PrevFrame()->GetNextSibling() == aLink.NextFrame(),
"Unexpected PrevFrame()");
MOZ_ASSERT(aLink.PrevFrame() || aLink.NextFrame() == FirstChild(),
"Unexpected NextFrame()");
MOZ_ASSERT(!aLink.PrevFrame() || aLink.NextFrame() != FirstChild(),
"Unexpected NextFrame()");
MOZ_ASSERT(aLink.mEnd == nullptr,
"Unexpected mEnd for frame link enumerator");
nsFrameList nsFrameList::ExtractHead(nsIFrame* aFrame) {
MOZ_ASSERT(!aFrame || ContainsFrame(aFrame), "aFrame is not on this list!");
if (!aFrame) {
// We handed over the whole list.
return std::move(*this);
}
if (aFrame == mFirstChild) {
// aFrame is our first child. Nothing to extract.
return nsFrameList();
}
// Extract all previous siblings of aFrame as a new list.
nsIFrame* prev = aFrame->GetPrevSibling();
nsIFrame* newFirstChild = mFirstChild;
nsIFrame* newLastChild = prev;
nsIFrame* prev = aLink.PrevFrame();
nsIFrame* newFirstFrame = nullptr;
if (prev) {
// Truncate the list after |prev| and hand the first part to our new list.
prev->SetNextSibling(nullptr);
newFirstFrame = mFirstChild;
mFirstChild = aLink.NextFrame();
if (!mFirstChild) { // we handed over the whole list
mLastChild = nullptr;
mFirstChild = aFrame;
return nsFrameList(newFirstChild, newLastChild);
}
// Now make sure aLink doesn't point to a frame we no longer have.
aLink.mPrev = nullptr;
}
// else aLink is pointing to before our first frame. Nothing to do.
nsFrameList nsFrameList::ExtractTail(nsIFrame* aFrame) {
MOZ_ASSERT(!aFrame || ContainsFrame(aFrame), "aFrame is not on this list!");
return nsFrameList(newFirstFrame, prev);
if (!aFrame) {
return nsFrameList();
}
nsFrameList nsFrameList::ExtractTail(FrameLinkEnumerator& aLink) {
MOZ_ASSERT(&aLink.List() == this, "Unexpected list");
MOZ_ASSERT(!aLink.PrevFrame() ||
aLink.PrevFrame()->GetNextSibling() == aLink.NextFrame(),
"Unexpected PrevFrame()");
MOZ_ASSERT(aLink.PrevFrame() || aLink.NextFrame() == FirstChild(),
"Unexpected NextFrame()");
MOZ_ASSERT(!aLink.PrevFrame() || aLink.NextFrame() != FirstChild(),
"Unexpected NextFrame()");
MOZ_ASSERT(aLink.mEnd == nullptr,
"Unexpected mEnd for frame link enumerator");
if (aFrame == mFirstChild) {
// We handed over the whole list.
return std::move(*this);
}
nsIFrame* prev = aFrame->GetPrevSibling();
nsIFrame* newFirstChild = aFrame;
nsIFrame* newLastChild = mLastChild;
nsIFrame* prev = aLink.PrevFrame();
nsIFrame* newFirstFrame;
nsIFrame* newLastFrame;
if (prev) {
// Truncate the list after |prev| and hand the second part to our new list
prev->SetNextSibling(nullptr);
newFirstFrame = aLink.NextFrame();
newLastFrame = newFirstFrame ? mLastChild : nullptr;
mLastChild = prev;
} else {
// Hand the whole list over to our new list
newFirstFrame = mFirstChild;
newLastFrame = mLastChild;
Clear();
}
// Now make sure aLink doesn't point to a frame we no longer have.
aLink.mFrame = nullptr;
MOZ_ASSERT(aLink.AtEnd(), "What's going on here?");
return nsFrameList(newFirstFrame, newLastFrame);
return nsFrameList(newFirstChild, newLastChild);
}
nsIFrame* nsFrameList::FrameAt(int32_t aIndex) const {

View File

@@ -72,6 +72,9 @@ struct PostFrameDestroyData {
*/
class nsFrameList {
public:
class Iterator;
class Slice;
nsFrameList() : mFirstChild(nullptr), mLastChild(nullptr) {}
nsFrameList(nsIFrame* aFirstFrame, nsIFrame* aLastFrame)
@@ -138,8 +141,6 @@ class nsFrameList {
aFrameList.Clear();
}
class Slice;
/**
* Append aFrameList to this list. If aParent is not null,
* reparents the newly added frames. Clears out aFrameList and
@@ -259,24 +260,29 @@ class nsFrameList {
nsIFrame*>::value,
"aPredicate should be of this function signature: bool(nsIFrame*)");
FrameLinkEnumerator link(*this);
link.Find(aPredicate);
return ExtractHead(link);
for (nsIFrame* f : *this) {
if (aPredicate(f)) {
return ExtractHead(f);
}
}
return std::move(*this);
}
/**
* Split this frame list such that all the frames before the link pointed to
* by aLink end up in the returned list, while the remaining frames stay in
* this list. After this call, aLink points to the beginning of this list.
* Split this frame list such that all the previous siblings of aFrame end up
* in the returned list, while aFrame and all its next siblings stay in this
* list. If aFrame is nullptr, extract the entire frame list.
* Note: aFrame must be in this frame list!
*/
nsFrameList ExtractHead(FrameLinkEnumerator& aLink);
nsFrameList ExtractHead(nsIFrame* aFrame);
/**
* Split this frame list such that all the frames coming after the link
* pointed to by aLink end up in the returned list, while the frames before
* that link stay in this list. After this call, aLink is at end.
* Split this frame list such that aFrame and all its next siblings end up in
* the returned list; all the previous siblings of aFrame stay in this list.
* If aFrame is nullptr, return an empty frame list.
* Note: aFrame must be in this frame list!
*/
nsFrameList ExtractTail(FrameLinkEnumerator& aLink);
nsFrameList ExtractTail(nsIFrame* aFrame);
nsIFrame* FirstChild() const { return mFirstChild; }

View File

@@ -18,6 +18,7 @@
#include "gfxContext.h"
#include "nsCOMPtr.h"
#include "mozilla/ComputedStyle.h"
#include "nsFrameList.h"
#include "nsStyleConsts.h"
#include "nsIContent.h"
#include "nsCellMap.h"
@@ -2169,12 +2170,6 @@ void nsTableFrame::AppendFrames(ChildListID aListID, nsFrameList& aFrameList) {
SetGeometryDirty();
}
// Needs to be at file scope or ArrayLength fails to compile.
struct ChildListInsertions {
nsIFrame::ChildListID mID;
nsFrameList mList;
};
void nsTableFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
const nsLineList::iterator* aPrevFrameLine,
nsFrameList& aFrameList) {
@@ -2196,34 +2191,28 @@ void nsTableFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
// Collect ColGroupFrames into a separate list and insert those separately
// from the other frames (bug 759249).
ChildListInsertions insertions[2]; // ColGroup, other
const nsStyleDisplay* display = aFrameList.FirstChild()->StyleDisplay();
nsFrameList::FrameLinkEnumerator e(aFrameList);
for (; !aFrameList.IsEmpty(); e.Next()) {
nsIFrame* next = e.NextFrame();
if (!next || next->StyleDisplay()->mDisplay != display->mDisplay) {
nsFrameList head = aFrameList.ExtractHead(e);
if (display->mDisplay == mozilla::StyleDisplay::TableColumnGroup) {
insertions[0].mID = kColGroupList;
insertions[0].mList.AppendFrames(nullptr, head);
nsFrameList colGroupList;
nsFrameList principalList;
do {
const auto display = aFrameList.FirstChild()->StyleDisplay()->mDisplay;
nsFrameList head = aFrameList.Split([display](nsIFrame* aFrame) {
return aFrame->StyleDisplay()->mDisplay != display;
});
if (display == mozilla::StyleDisplay::TableColumnGroup) {
colGroupList.AppendFrames(nullptr, head);
} else {
insertions[1].mID = kPrincipalList;
insertions[1].mList.AppendFrames(nullptr, head);
principalList.AppendFrames(nullptr, head);
}
if (!next) {
break;
}
display = next->StyleDisplay();
}
}
for (uint32_t i = 0; i < ArrayLength(insertions); ++i) {
} while (aFrameList.NotEmpty());
// We pass aPrevFrame for both ColGroup and other frames since
// HomogenousInsertFrames will only use it if it's a suitable
// prev-sibling for the frames in the frame list.
if (!insertions[i].mList.IsEmpty()) {
HomogenousInsertFrames(insertions[i].mID, aPrevFrame,
insertions[i].mList);
if (colGroupList.NotEmpty()) {
HomogenousInsertFrames(kColGroupList, aPrevFrame, colGroupList);
}
if (principalList.NotEmpty()) {
HomogenousInsertFrames(kPrincipalList, aPrevFrame, principalList);
}
}