diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp
index 0a533eaf1f38..eae93d08b5f4 100644
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -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
diff --git a/layout/generic/nsHTMLReflowState.h b/layout/generic/nsHTMLReflowState.h
index 57d9378dd108..fd6445874347 100644
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -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,
diff --git a/layout/generic/nsLineBox.cpp b/layout/generic/nsLineBox.cpp
index 130ddf9f7c6f..f3f00f8a40fa 100644
--- a/layout/generic/nsLineBox.cpp
+++ b/layout/generic/nsLineBox.cpp
@@ -289,7 +289,7 @@ nsLineBox::IsEmpty() const
}
bool
-nsLineBox::CachedIsEmpty()
+nsLineBox::CachedIsEmpty() const
{
if (mFlags.mDirty) {
return IsEmpty();
diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h
index b2a8c1df6410..5d727a24f5f0 100644
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -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;
diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp
index cbfb5f1162b1..994d8ee8f162 100644
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -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;
diff --git a/layout/generic/nsPlaceholderFrame.h b/layout/generic/nsPlaceholderFrame.h
index e53d44e5af0d..82e5c4e0246f 100644
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -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___ */