Keep track of the line container and forget the current line if it's for a different container. b=444027 r+sr=roc a1.9.1=dbaron
authorMats Palmgren <mats.palmgren@bredband.net>
Thu, 26 Feb 2009 12:48:12 +0100
changeset 23470 8fed6a0625cebd6e6542f004ee5616cf1646ee88
parent 23469 a0a505a53c1983faa918b276e29bb0d5bd8cb92c
child 23471 39460eaf5d0601dfd93067b44ac7b43a582e4ab2
push id780
push usermpalmgren@mozilla.com
push dateThu, 26 Feb 2009 12:10:14 +0000
bugs444027
milestone1.9.1b3pre
Keep track of the line container and forget the current line if it's for a different container. b=444027 r+sr=roc a1.9.1=dbaron
layout/generic/nsBlockFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsLineBox.h
layout/generic/nsTextFrameThebes.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -682,16 +682,17 @@ nsBlockFrame::GetMinWidth(nsIRenderingCo
             line == curFrame->begin_lines()) {
           const nsStyleCoord &indent = GetStyleText()->mTextIndent;
           if (indent.GetUnit() == eStyleUnit_Coord)
             data.currentLine += indent.GetCoordValue();
         }
         // XXX Bug NNNNNN Should probably handle percentage text-indent.
 
         data.line = &line;
+        data.lineContainer = curFrame;
         nsIFrame *kid = line->mFirstChild;
         for (PRInt32 i = 0, i_end = line->GetChildCount(); i != i_end;
              ++i, kid = kid->GetNextSibling()) {
           kid->AddInlineMinWidth(aRenderingContext, &data);
         }
       }
 #ifdef DEBUG
       if (gNoisyIntrinsic) {
@@ -756,16 +757,17 @@ nsBlockFrame::GetPrefWidth(nsIRenderingC
             line == curFrame->begin_lines()) {
           const nsStyleCoord &indent = GetStyleText()->mTextIndent;
           if (indent.GetUnit() == eStyleUnit_Coord)
             data.currentLine += indent.GetCoordValue();
         }
         // XXX Bug NNNNNN Should probably handle percentage text-indent.
 
         data.line = &line;
+        data.lineContainer = curFrame;
         nsIFrame *kid = line->mFirstChild;
         for (PRInt32 i = 0, i_end = line->GetChildCount(); i != i_end;
              ++i, kid = kid->GetNextSibling()) {
           kid->AddInlinePrefWidth(aRenderingContext, &data);
         }
       }
 #ifdef DEBUG
       if (gNoisyIntrinsic) {
@@ -5246,17 +5248,17 @@ nsBlockInFlowLineIterator::Prev()
   }
 }
 
 PRBool
 nsBlockInFlowLineIterator::FindValidLine()
 {
   line_iterator end = mInOverflowLines ? mInOverflowLines->end() : mFrame->end_lines();
   if (mLine != end)
-    return PR_TRUE; 
+    return PR_TRUE;
   PRBool currentlyInOverflowLines = mInOverflowLines != nsnull;
   while (PR_TRUE) {
     if (currentlyInOverflowLines) {
       mFrame = static_cast<nsBlockFrame*>(mFrame->GetNextInFlow());
       if (!mFrame)
         return PR_FALSE;
       mInOverflowLines = nsnull;
       mLine = mFrame->begin_lines();
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1168,26 +1168,30 @@ public:
    * in inline layout.  Code that determines the intrinsic width of a
    * region of inline layout accumulates the result into this structure.
    * This pattern is needed because we need to maintain state
    * information about whitespace (for both collapsing and trimming).
    */
   struct InlineIntrinsicWidthData {
     InlineIntrinsicWidthData()
       : line(nsnull)
+      , lineContainer(nsnull)
       , prevLines(0)
       , currentLine(0)
       , skipWhitespace(PR_TRUE)
       , trailingWhitespace(0)
     {}
 
     // The line. This may be null if the inlines are not associated with
     // a block or if we just don't know the line.
     const nsLineList_iterator* line;
 
+    // The line container.
+    nsIFrame* lineContainer;
+
     // The maximum intrinsic width for all previous lines.
     nscoord prevLines;
 
     // The maximum intrinsic width for the current line.  At a line
     // break (mandatory for preferred width; allowed for minimum width),
     // the caller should call |Break()|.
     nscoord currentLine;
 
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -666,32 +666,32 @@ class nsLineList_iterator {
       iterator_self_type copy(*this);
       return --copy;
     }
 
     // Passing by value rather than by reference and reference to const
     // to keep AIX happy.
     PRBool operator==(const iterator_self_type aOther) const
     {
-      NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+      NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
       return mCurrent == aOther.mCurrent;
     }
     PRBool operator!=(const iterator_self_type aOther) const
     {
-      NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+      NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
       return mCurrent != aOther.mCurrent;
     }
     PRBool operator==(const iterator_self_type aOther)
     {
-      NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+      NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
       return mCurrent == aOther.mCurrent;
     }
     PRBool operator!=(const iterator_self_type aOther)
     {
-      NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+      NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
       return mCurrent != aOther.mCurrent;
     }
 
   private:
     link_type *mCurrent;
 #ifdef DEBUG
     link_type *mListLink; // the list's link, i.e., the end
 #endif
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -943,30 +943,38 @@ BuildTextRunsScanner::FindBoundaries(nsI
 #define NUM_LINES_TO_BUILD_TEXT_RUNS 200
 
 /**
  * General routine for building text runs. This is hairy because of the need
  * to build text runs that span content nodes.
  * 
  * @param aForFrameLine the line containing aForFrame; if null, we'll figure
  * out the line (slowly)
- * @param aBlockFrame the block containing aForFrame; if null, we'll figure
- * out the block (slowly)
+ * @param aLineContainer the line container containing aForFrame; if null,
+ * we'll walk the ancestors to find it.  It's required to be non-null when
+ * aForFrameLine is non-null.
  */
 static void
 BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame,
-              nsIFrame* aLineContainer, const nsLineList::iterator* aForFrameLine)
-{
-  NS_ASSERTION(aForFrame || (aForFrameLine && aLineContainer),
-               "One of aForFrame or aForFrameLine+aLineContainer must be set!");
+              nsIFrame* aLineContainer,
+              const nsLineList::iterator* aForFrameLine)
+{
+  NS_ASSERTION(aForFrame || aLineContainer,
+               "One of aForFrame or aLineContainer must be set!");
+  NS_ASSERTION(!aForFrameLine || aLineContainer,
+               "line but no line container");
   
-  if (!aLineContainer || !aForFrameLine) {
+  if (!aLineContainer) {
     aLineContainer = FindLineContainer(aForFrame);
   } else {
-    NS_ASSERTION(!aForFrame || aLineContainer == FindLineContainer(aForFrame), "Wrong line container hint");
+    NS_ASSERTION(!aForFrame ||
+                 (aLineContainer == FindLineContainer(aForFrame) ||
+                  (aLineContainer->GetType() == nsGkAtoms::letterFrame &&
+                   aLineContainer->GetStyleDisplay()->IsFloating())),
+                 "Wrong line container hint");
   }
 
   nsPresContext* presContext = aLineContainer->PresContext();
   BuildTextRunsScanner scanner(presContext, aContext, aLineContainer);
 
   nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aLineContainer);
 
   if (!block) {
@@ -5350,17 +5358,17 @@ void nsTextFrame::MarkIntrinsicWidthsDir
 // temporarily override the "current line ending" settings.
 void
 nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
                                       nsIFrame::InlineMinWidthData *aData)
 {
   PRUint32 flowEndInTextRun;
   gfxContext* ctx = aRenderingContext->ThebesContext();
   gfxSkipCharsIterator iter =
-    EnsureTextRun(ctx, nsnull, aData->line, &flowEndInTextRun);
+    EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   const nsStyleText* textStyle = GetStyleText();
   const nsTextFragment* frag = mContent->GetText();
   PropertyProvider provider(mTextRun, textStyle, frag, this,
@@ -5452,33 +5460,42 @@ nsTextFrame::AddInlineMinWidth(nsIRender
   gfxTextRun* lastTextRun = nsnull;
   // nsContinuingTextFrame does nothing for AddInlineMinWidth; all text frames
   // in the flow are handled right here.
   for (f = this; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
     // f->mTextRun could be null if we haven't set up textruns yet for f.
     // Except in OOM situations, lastTextRun will only be null for the first
     // text frame.
     if (f == this || f->mTextRun != lastTextRun) {
+      nsIFrame* lc;
+      if (aData->lineContainer &&
+          aData->lineContainer != (lc = FindLineContainer(f))) {
+        NS_ASSERTION(f != this, "wrong InlineMinWidthData container"
+                                " for first continuation");
+        aData->line = nsnull;
+        aData->lineContainer = lc;
+      }
+
       // This will process all the text frames that share the same textrun as f.
       f->AddInlineMinWidthForFlow(aRenderingContext, aData);
       lastTextRun = f->mTextRun;
     }
   }
 }
 
 // XXX this doesn't handle characters shaped by line endings. We need to
 // temporarily override the "current line ending" settings.
 void
 nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
                                        nsIFrame::InlinePrefWidthData *aData)
 {
   PRUint32 flowEndInTextRun;
   gfxContext* ctx = aRenderingContext->ThebesContext();
   gfxSkipCharsIterator iter =
-    EnsureTextRun(ctx, nsnull, aData->line, &flowEndInTextRun);
+    EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   
   const nsStyleText* textStyle = GetStyleText();
   const nsTextFragment* frag = mContent->GetText();
@@ -5567,16 +5584,25 @@ nsTextFrame::AddInlinePrefWidth(nsIRende
   gfxTextRun* lastTextRun = nsnull;
   // nsContinuingTextFrame does nothing for AddInlineMinWidth; all text frames
   // in the flow are handled right here.
   for (f = this; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
     // f->mTextRun could be null if we haven't set up textruns yet for f.
     // Except in OOM situations, lastTextRun will only be null for the first
     // text frame.
     if (f == this || f->mTextRun != lastTextRun) {
+      nsIFrame* lc;
+      if (aData->lineContainer &&
+          aData->lineContainer != (lc = FindLineContainer(f))) {
+        NS_ASSERTION(f != this, "wrong InlinePrefWidthData container"
+                                " for first continuation");
+        aData->line = nsnull;
+        aData->lineContainer = lc;
+      }
+
       // This will process all the text frames that share the same textrun as f.
       f->AddInlinePrefWidthForFlow(aRenderingContext, aData);
       lastTextRun = f->mTextRun;
     }
   }
 }
 
 /* virtual */ nsSize