mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 928403 - optimize nsFrameConstructorState::ProcessFrameInsertions, r=roc
--HG-- rename : testing/mochitest/b2g-debug.json => testing/mochitest/b2g.json extra : rebase_source : c45d39f4b50f248b28a6ebfb50128084bb59ebe4
This commit is contained in:
parent
6e507300dc
commit
2d19654cb3
@ -1241,23 +1241,67 @@ nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
|
||||
// so this will make out-of-flows respect the ordering of placeholders,
|
||||
// which is great because it takes care of anonymous content.
|
||||
nsIFrame* firstNewFrame = aFrameItems.FirstChild();
|
||||
|
||||
// Cache the ancestor chain so that we can reuse it if needed.
|
||||
nsAutoTArray<nsIFrame*, 20> firstNewFrameAncestors;
|
||||
nsIFrame* notCommonAncestor = nullptr;
|
||||
if (lastChild) {
|
||||
notCommonAncestor = nsLayoutUtils::FillAncestors(firstNewFrame,
|
||||
containingBlock,
|
||||
&firstNewFrameAncestors);
|
||||
}
|
||||
|
||||
if (!lastChild ||
|
||||
nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame, containingBlock) < 0) {
|
||||
nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame,
|
||||
firstNewFrameAncestors,
|
||||
notCommonAncestor ?
|
||||
containingBlock : nullptr) < 0) {
|
||||
// no lastChild, or lastChild comes before the new children, so just append
|
||||
rv = mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
|
||||
} else {
|
||||
// try the other children
|
||||
nsIFrame* insertionPoint = nullptr;
|
||||
// Try the other children. First collect them to an array so that a
|
||||
// reasonable fast binary search can be used to find the insertion point.
|
||||
nsAutoTArray<nsIFrame*, 128> children;
|
||||
for (nsIFrame* f = childList.FirstChild(); f != lastChild;
|
||||
f = f->GetNextSibling()) {
|
||||
children.AppendElement(f);
|
||||
}
|
||||
|
||||
nsIFrame* insertionPoint = nullptr;
|
||||
int32_t imin = 0;
|
||||
int32_t max = children.Length();
|
||||
while (max > imin) {
|
||||
int32_t imid = imin + ((max - imin) / 2);
|
||||
nsIFrame* f = children[imid];
|
||||
int32_t compare =
|
||||
nsLayoutUtils::CompareTreePosition(f, firstNewFrame, containingBlock);
|
||||
nsLayoutUtils::CompareTreePosition(f, firstNewFrame, firstNewFrameAncestors,
|
||||
notCommonAncestor ? containingBlock : nullptr);
|
||||
if (compare > 0) {
|
||||
// f comes after the new children, so stop here and insert after
|
||||
// the previous frame
|
||||
// f is after the new frame.
|
||||
max = imid;
|
||||
insertionPoint = imid > 0 ? children[imid - 1] : nullptr;
|
||||
} else if (compare < 0) {
|
||||
// f is before the new frame.
|
||||
imin = imid + 1;
|
||||
insertionPoint = f;
|
||||
} else {
|
||||
// This is for the old behavior. Should be removed once it is
|
||||
// guaranteed that CompareTreePosition can't return 0!
|
||||
// See bug 928645.
|
||||
NS_WARNING("Something odd happening???");
|
||||
insertionPoint = nullptr;
|
||||
for (uint32_t i = 0; i < children.Length(); ++i) {
|
||||
nsIFrame* f = children[i];
|
||||
if (nsLayoutUtils::CompareTreePosition(f, firstNewFrame,
|
||||
firstNewFrameAncestors,
|
||||
notCommonAncestor ?
|
||||
containingBlock : nullptr) > 0) {
|
||||
break;
|
||||
}
|
||||
insertionPoint = f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
insertionPoint = f;
|
||||
}
|
||||
rv = mFrameManager->InsertFrames(containingBlock, aChildListID,
|
||||
insertionPoint, aFrameItems);
|
||||
|
@ -1002,9 +1002,11 @@ nsLayoutUtils::DoCompareTreePosition(nsIContent* aContent1,
|
||||
return index1 - index2;
|
||||
}
|
||||
|
||||
static nsIFrame* FillAncestors(nsIFrame* aFrame,
|
||||
nsIFrame* aStopAtAncestor,
|
||||
nsTArray<nsIFrame*>* aAncestors)
|
||||
// static
|
||||
nsIFrame*
|
||||
nsLayoutUtils::FillAncestors(nsIFrame* aFrame,
|
||||
nsIFrame* aStopAtAncestor,
|
||||
nsTArray<nsIFrame*>* aAncestors)
|
||||
{
|
||||
while (aFrame && aFrame != aStopAtAncestor) {
|
||||
aAncestors->AppendElement(aFrame);
|
||||
@ -1036,6 +1038,27 @@ nsLayoutUtils::DoCompareTreePosition(nsIFrame* aFrame1,
|
||||
NS_PRECONDITION(aFrame1, "aFrame1 must not be null");
|
||||
NS_PRECONDITION(aFrame2, "aFrame2 must not be null");
|
||||
|
||||
nsAutoTArray<nsIFrame*,20> frame2Ancestors;
|
||||
nsIFrame* nonCommonAncestor =
|
||||
FillAncestors(aFrame2, aCommonAncestor, &frame2Ancestors);
|
||||
|
||||
return DoCompareTreePosition(aFrame1, aFrame2, frame2Ancestors,
|
||||
aIf1Ancestor, aIf2Ancestor,
|
||||
nonCommonAncestor ? aCommonAncestor : nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t
|
||||
nsLayoutUtils::DoCompareTreePosition(nsIFrame* aFrame1,
|
||||
nsIFrame* aFrame2,
|
||||
nsTArray<nsIFrame*>& aFrame2Ancestors,
|
||||
int32_t aIf1Ancestor,
|
||||
int32_t aIf2Ancestor,
|
||||
nsIFrame* aCommonAncestor)
|
||||
{
|
||||
NS_PRECONDITION(aFrame1, "aFrame1 must not be null");
|
||||
NS_PRECONDITION(aFrame2, "aFrame2 must not be null");
|
||||
|
||||
nsPresContext* presContext = aFrame1->PresContext();
|
||||
if (presContext != aFrame2->PresContext()) {
|
||||
NS_ERROR("no common ancestor at all, different documents");
|
||||
@ -1043,25 +1066,18 @@ nsLayoutUtils::DoCompareTreePosition(nsIFrame* aFrame1,
|
||||
}
|
||||
|
||||
nsAutoTArray<nsIFrame*,20> frame1Ancestors;
|
||||
if (!FillAncestors(aFrame1, aCommonAncestor, &frame1Ancestors)) {
|
||||
if (aCommonAncestor &&
|
||||
!FillAncestors(aFrame1, aCommonAncestor, &frame1Ancestors)) {
|
||||
// We reached the root of the frame tree ... if aCommonAncestor was set,
|
||||
// it is wrong
|
||||
aCommonAncestor = nullptr;
|
||||
}
|
||||
|
||||
nsAutoTArray<nsIFrame*,20> frame2Ancestors;
|
||||
if (!FillAncestors(aFrame2, aCommonAncestor, &frame2Ancestors) &&
|
||||
aCommonAncestor) {
|
||||
// We reached the root of the frame tree ... aCommonAncestor was wrong.
|
||||
// Try again with no hint.
|
||||
return DoCompareTreePosition(aFrame1, aFrame2,
|
||||
aIf1Ancestor, aIf2Ancestor, nullptr);
|
||||
}
|
||||
|
||||
int32_t last1 = int32_t(frame1Ancestors.Length()) - 1;
|
||||
int32_t last2 = int32_t(frame2Ancestors.Length()) - 1;
|
||||
int32_t last2 = int32_t(aFrame2Ancestors.Length()) - 1;
|
||||
while (last1 >= 0 && last2 >= 0 &&
|
||||
frame1Ancestors[last1] == frame2Ancestors[last2]) {
|
||||
frame1Ancestors[last1] == aFrame2Ancestors[last2]) {
|
||||
last1--;
|
||||
last2--;
|
||||
}
|
||||
@ -1081,7 +1097,7 @@ nsLayoutUtils::DoCompareTreePosition(nsIFrame* aFrame1,
|
||||
}
|
||||
|
||||
nsIFrame* ancestor1 = frame1Ancestors[last1];
|
||||
nsIFrame* ancestor2 = frame2Ancestors[last2];
|
||||
nsIFrame* ancestor2 = aFrame2Ancestors[last2];
|
||||
// Now we should be able to walk sibling chains to find which one is first
|
||||
if (IsFrameAfter(ancestor2, ancestor1))
|
||||
return -1;
|
||||
|
@ -263,6 +263,15 @@ public:
|
||||
return DoCompareTreePosition(aFrame1, aFrame2, -1, 1, aCommonAncestor);
|
||||
}
|
||||
|
||||
static int32_t CompareTreePosition(nsIFrame* aFrame1,
|
||||
nsIFrame* aFrame2,
|
||||
nsTArray<nsIFrame*>& aFrame2Ancestors,
|
||||
nsIFrame* aCommonAncestor = nullptr)
|
||||
{
|
||||
return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors,
|
||||
-1, 1, aCommonAncestor);
|
||||
}
|
||||
|
||||
/*
|
||||
* More generic version of |CompareTreePosition|. |aIf1Ancestor|
|
||||
* gives the value to return when 1 is an ancestor of 2, and likewise
|
||||
@ -275,6 +284,17 @@ public:
|
||||
int32_t aIf2Ancestor,
|
||||
nsIFrame* aCommonAncestor = nullptr);
|
||||
|
||||
static nsIFrame* FillAncestors(nsIFrame* aFrame,
|
||||
nsIFrame* aStopAtAncestor,
|
||||
nsTArray<nsIFrame*>* aAncestors);
|
||||
|
||||
static int32_t DoCompareTreePosition(nsIFrame* aFrame1,
|
||||
nsIFrame* aFrame2,
|
||||
nsTArray<nsIFrame*>& aFrame2Ancestors,
|
||||
int32_t aIf1Ancestor,
|
||||
int32_t aIf2Ancestor,
|
||||
nsIFrame* aCommonAncestor);
|
||||
|
||||
/**
|
||||
* LastContinuationWithChild gets the last continuation in aFrame's chain
|
||||
* that has a child, or the first continuation if the frame has no children.
|
||||
|
Loading…
Reference in New Issue
Block a user