Bug 641341. Speed up CalculateHypotheticalBox for the case of a block containing a bunch of lines but absolutely no in-flows anywhere. r=roc

This commit is contained in:
Boris Zbarsky 2011-10-04 23:47:08 -04:00
Родитель 61a0d1f4ca
Коммит 5b68e3365d
6 изменённых файлов: 46 добавлений и 30 удалений

Просмотреть файл

@ -55,6 +55,8 @@
#include "nsIServiceManager.h"
#include "nsIPercentHeightObserver.h"
#include "nsLayoutUtils.h"
#include "nsPlaceholderFrame.h"
#include "nsFrameManager.h"
#include "mozilla/Preferences.h"
#ifdef IBMBIDI
#include "nsBidiUtils.h"
@ -847,7 +849,7 @@ static bool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
// cbrs->frame is the actual containing block
void
nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
nsPlaceholderFrame* aPlaceholderFrame,
nsIFrame* aContainingBlock,
nscoord aBlockLeftContentEdge,
nscoord aBlockContentWidth,
@ -930,17 +932,12 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
nsLayoutUtils::GetAsBlock(aContainingBlock->GetContentInsertionFrame());
if (blockFrame) {
nscoord blockYOffset = blockFrame->GetOffsetTo(aContainingBlock).y;
bool isValid;
nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid);
if (!isValid) {
const nsLineBox* lineBox = aPlaceholderFrame->GetCachedLineBox();
if (!lineBox) {
// Give up. We're probably dealing with somebody using
// position:absolute inside native-anonymous content anyway.
aHypotheticalBox.mTop = placeholderOffset.y;
} else {
NS_ASSERTION(iter.GetContainer() == blockFrame,
"Found placeholder in wrong block!");
nsBlockFrame::line_iterator lineBox = iter.GetLine();
// How we determine the hypothetical box depends on whether the element
// would have been inline-level or block-level
if (mStyleDisplay->IsOriginalDisplayInlineOutside()) {
@ -954,10 +951,10 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// have been just before this line.
// XXXbz the line box is not fully reflowed yet if our
// containing block is relatively positioned...
if (lineBox != iter.End()) {
bool allEmpty = true;
if (!lineBox->IsValidCachedIsEmpty() || !lineBox->CachedIsEmpty()) {
nsIFrame * firstFrame = lineBox->mFirstChild;
bool found = false;
bool allEmpty = true;
while (firstFrame) { // See bug 223064
allEmpty = AreAllEarlierInFlowFramesEmpty(firstFrame,
aPlaceholderFrame, &found);
@ -966,20 +963,17 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
firstFrame = firstFrame->GetNextSibling();
}
NS_ASSERTION(firstFrame, "Couldn't find placeholder!");
}
if (allEmpty) {
// The top of the hypothetical box is the top of the line
// containing the placeholder, since there is nothing in the
// line before our placeholder except empty frames.
aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset;
} else {
// The top of the hypothetical box is just below the line
// containing the placeholder.
aHypotheticalBox.mTop = lineBox->mBounds.YMost() + blockYOffset;
}
if (allEmpty) {
// The top of the hypothetical box is the top of the line
// containing the placeholder, since there is nothing in the
// line before our placeholder except empty frames.
aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset;
} else {
// Just use the placeholder's y-offset wrt the containing block
aHypotheticalBox.mTop = placeholderOffset.y;
// The top of the hypothetical box is just below the line
// containing the placeholder.
aHypotheticalBox.mTop = lineBox->mBounds.YMost() + blockYOffset;
}
}
}
@ -1105,9 +1099,10 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
"Why are we here?");
// Get the placeholder frame
nsIFrame* placeholderFrame;
nsPlaceholderFrame* placeholderFrame;
placeholderFrame = aPresContext->PresShell()->GetPlaceholderFrameFor(frame);
placeholderFrame =
aPresContext->PresShell()->FrameManager()->GetPlaceholderFrameFor(frame);
NS_ASSERTION(nsnull != placeholderFrame, "no placeholder frame");
// If both 'left' and 'right' are 'auto' or both 'top' and 'bottom' are

Просмотреть файл

@ -49,6 +49,7 @@ class nsRenderingContext;
class nsFloatManager;
class nsLineLayout;
class nsIPercentHeightObserver;
class nsPlaceholderFrame;
struct nsStyleDisplay;
struct nsStyleVisibility;
@ -511,7 +512,7 @@ protected:
nscoord& aCBWidth);
void CalculateHypotheticalBox(nsPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
nsPlaceholderFrame* aPlaceholderFrame,
nsIFrame* aContainingBlock,
nscoord aBlockLeftContentEdge,
nscoord aBlockContentWidth,

Просмотреть файл

@ -289,7 +289,7 @@ nsLineBox::IsEmpty() const
}
bool
nsLineBox::CachedIsEmpty()
nsLineBox::CachedIsEmpty() const
{
if (mFlags.mDirty) {
return IsEmpty();

Просмотреть файл

@ -486,14 +486,14 @@ public:
// Call this only while in Reflow() for the block the line belongs
// to, only between reflowing the line (or sliding it, if we skip
// reflowing it) and the end of reflowing the block.
bool CachedIsEmpty();
bool CachedIsEmpty() const;
void InvalidateCachedIsEmpty() {
mFlags.mEmptyCacheValid = PR_FALSE;
}
// For debugging purposes
bool IsValidCachedIsEmpty() {
bool IsValidCachedIsEmpty() const {
return mFlags.mEmptyCacheValid;
}
@ -514,8 +514,8 @@ public:
PRUint32 mLineWrapped: 1;
PRUint32 mInvalidateTextRuns : 1;
PRUint32 mResizeReflowOptimizationDisabled: 1; // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
PRUint32 mEmptyCacheValid: 1;
PRUint32 mEmptyCacheState: 1;
mutable PRUint32 mEmptyCacheValid: 1;
mutable PRUint32 mEmptyCacheState: 1;
// mHasBullet indicates that this is an inline line whose block's
// bullet is adjacent to this line and non-empty.
PRUint32 mHasBullet : 1;

Просмотреть файл

@ -145,6 +145,15 @@ nsPlaceholderFrame::Reflow(nsPresContext* aPresContext,
aDesiredSize.width = 0;
aDesiredSize.height = 0;
// Cache our line box.
mCachedLineBox = nsnull;
if (aReflowState.mLineLayout) {
nsLineList::iterator* line = aReflowState.mLineLayout->GetLine();
if (line) {
mCachedLineBox = line->get();
}
}
aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK;

Просмотреть файл

@ -69,6 +69,8 @@
#include "nsFrame.h"
#include "nsGkAtoms.h"
class nsLineBox;
nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
nsFrameState aTypeBit);
@ -200,8 +202,17 @@ public:
return outOfFlow;
}
// GetCachedLineBox is only OK to call if you're sure this
// placeholder has has Reflow() called since any changes to the
// frame tree that could have affected which line box the
// placeholder is in.
const nsLineBox* GetCachedLineBox() const {
return mCachedLineBox;
}
protected:
nsIFrame* mOutOfFlowFrame;
nsLineBox* mCachedLineBox;
};
#endif /* nsPlaceholderFrame_h___ */