Bug 748646 patch 1: Put a block's text-overflow markers in PositionedDescendants() before the rest of the block's display items. r=roc
authorDaniel Holbert <dholbert@cs.stanford.edu>
Sun, 22 Jul 2012 23:08:20 -0700
changeset 105582 e4040216dff916ff8945aad982213eb84e101e56
parent 105581 ec9fd0a08b8b4e1cbca09755165f3a75918b9720
child 105583 7295d036a37b691f3b7e75093784bad7265f4d68
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs748646
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 748646 patch 1: Put a block's text-overflow markers in PositionedDescendants() before the rest of the block's display items. r=roc
layout/generic/TextOverflow.cpp
layout/generic/TextOverflow.h
layout/generic/nsBlockFrame.cpp
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -221,17 +221,16 @@ nsDisplayTextOverflowMarker::PaintTextTo
 
 void
 TextOverflow::Init(nsDisplayListBuilder*   aBuilder,
                    const nsDisplayListSet& aLists,
                    nsIFrame*               aBlockFrame)
 {
   mBuilder = aBuilder;
   mBlock = aBlockFrame;
-  mMarkerList = aLists.PositionedDescendants();
   mContentArea = aBlockFrame->GetContentRectRelativeToSelf();
   mScrollableFrame = nsLayoutUtils::GetScrollableFrameFor(aBlockFrame);
   PRUint8 direction = aBlockFrame->GetStyleVisibility()->mDirection;
   mBlockIsRTL = direction == NS_STYLE_DIRECTION_RTL;
   mAdjustForPixelSnapping = false;
 #ifdef MOZ_XUL
   if (!mScrollableFrame) {
     nsIAtom* pseudoType = aBlockFrame->GetStyleContext()->GetPseudo();
@@ -678,48 +677,48 @@ TextOverflow::CanHaveTextOverflow(nsDisp
   }
   return true;
 }
 
 void
 TextOverflow::CreateMarkers(const nsLineBox* aLine,
                             bool             aCreateLeft,
                             bool             aCreateRight,
-                            const nsRect&    aInsideMarkersArea) const
+                            const nsRect&    aInsideMarkersArea)
 {
   if (aCreateLeft) {
     nsRect markerRect = nsRect(aInsideMarkersArea.x - mLeft.mIntrinsicWidth,
                                aLine->mBounds.y,
                                mLeft.mIntrinsicWidth, aLine->mBounds.height);
     markerRect += mBuilder->ToReferenceFrame(mBlock);
     nsDisplayItem* marker = new (mBuilder)
       nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect,
                                   aLine->GetAscent(), mLeft.mMarkerString, 0);
     if (marker) {
       marker = ClipMarker(mBuilder, mBlock, marker,
                           mContentArea + mBuilder->ToReferenceFrame(mBlock),
                           &markerRect);
     }
-    mMarkerList->AppendNewToTop(marker);
+    mMarkerList.AppendNewToTop(marker);
   }
 
   if (aCreateRight) {
     nsRect markerRect = nsRect(aInsideMarkersArea.XMost(),
                                aLine->mBounds.y,
                                mRight.mIntrinsicWidth, aLine->mBounds.height);
     markerRect += mBuilder->ToReferenceFrame(mBlock);
     nsDisplayItem* marker = new (mBuilder)
       nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect,
                                   aLine->GetAscent(), mRight.mMarkerString, 1);
     if (marker) {
       marker = ClipMarker(mBuilder, mBlock, marker,
                           mContentArea + mBuilder->ToReferenceFrame(mBlock),
                           &markerRect);
     }
-    mMarkerList->AppendNewToTop(marker);
+    mMarkerList.AppendNewToTop(marker);
   }
 }
 
 void
 TextOverflow::Marker::SetupString(nsIFrame* aFrame)
 {
   if (mInitialized) {
     return;
--- a/layout/generic/TextOverflow.h
+++ b/layout/generic/TextOverflow.h
@@ -34,16 +34,22 @@ class TextOverflow {
   /**
    * Analyze the display lists for text overflow and what kind of item is at
    * the content edges.  Add display items for text-overflow markers as needed
    * and remove or clip items that would overlap a marker.
    */
   void ProcessLine(const nsDisplayListSet& aLists, nsLineBox* aLine);
 
   /**
+   * Get the resulting text-overflow markers (the list may be empty).
+   * @return a DisplayList containing any text-overflow markers.
+   */
+  nsDisplayList& GetMarkers() { return mMarkerList; }
+
+  /**
    * @return true if aBlockFrame needs analysis for text overflow.
    */
   static bool CanHaveTextOverflow(nsDisplayListBuilder* aBuilder,
                                   nsIFrame*             aBlockFrame);
 
   typedef nsTHashtable<nsPtrHashKey<nsIFrame> > FrameHashtable;
 
  protected:
@@ -164,32 +170,32 @@ class TextOverflow {
    * @param aInsideMarkersArea is the area inside the markers
    */
   void PruneDisplayListContents(nsDisplayList*        aList,
                                 const FrameHashtable& aFramesToHide,
                                 const nsRect&         aInsideMarkersArea);
 
   /**
    * ProcessLine calls this to create display items for the markers and insert
-   * them into a display list for the block.
+   * them into mMarkerList.
    * @param aLine the line we're processing
    * @param aCreateLeft if true, create a marker on the left side
    * @param aCreateRight if true, create a marker on the right side
    * @param aInsideMarkersArea is the area inside the markers
    */
   void CreateMarkers(const nsLineBox* aLine,
                      bool             aCreateLeft,
                      bool             aCreateRight,
-                     const nsRect&    aInsideMarkersArea) const;
+                     const nsRect&    aInsideMarkersArea);
 
   nsRect                 mContentArea;
   nsDisplayListBuilder*  mBuilder;
   nsIFrame*              mBlock;
   nsIScrollableFrame*    mScrollableFrame;
-  nsDisplayList*         mMarkerList;
+  nsDisplayList          mMarkerList;
   bool                   mBlockIsRTL;
   bool                   mCanHaveHorizontalScrollbar;
   bool                   mAdjustForPixelSnapping;
 
   class Marker {
   public:
     void Init(const nsStyleTextOverflowSide& aStyle) {
       mInitialized = false;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6264,16 +6264,19 @@ nsBlockFrame::BuildDisplayList(nsDisplay
   }
 
   aBuilder->MarkFramesForDisplayList(this, mFloats, aDirtyRect);
 
   // Prepare for text-overflow processing.
   nsAutoPtr<TextOverflow> textOverflow(
     TextOverflow::WillProcessLines(aBuilder, aLists, this));
 
+  // We'll collect our lines' display items here, & then append this to aLists.
+  nsDisplayListCollection linesDisplayListCollection;
+
   // Don't use the line cursor if we might have a descendant placeholder ...
   // it might skip lines that contain placeholders but don't themselves
   // intersect with the dirty area.
   // In particular, we really want to check ShouldDescendIntoFrame()
   // on all our child frames, but that might be expensive.  So we
   // approximate it by checking it on |this|; if it's true for any
   // frame in our child list, it's also true for |this|.
   nsLineBox* cursor = aBuilder->ShouldDescendIntoFrame(this) ?
@@ -6288,32 +6291,32 @@ nsBlockFrame::BuildDisplayList(nsDisplay
       nsRect lineArea = line->GetVisualOverflowArea();
       if (!lineArea.IsEmpty()) {
         // Because we have a cursor, the combinedArea.ys are non-decreasing.
         // Once we've passed aDirtyRect.YMost(), we can never see it again.
         if (lineArea.y >= aDirtyRect.YMost()) {
           break;
         }
         rv = DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines,
-                         aLists, this, textOverflow);
+                         linesDisplayListCollection, this, textOverflow);
         if (NS_FAILED(rv))
           break;
       }
     }
   } else {
     bool nonDecreasingYs = true;
     PRInt32 lineCount = 0;
     nscoord lastY = PR_INT32_MIN;
     nscoord lastYMost = PR_INT32_MIN;
     for (line_iterator line = begin_lines();
          line != line_end;
          ++line) {
       nsRect lineArea = line->GetVisualOverflowArea();
       rv = DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines,
-                       aLists, this, textOverflow);
+                       linesDisplayListCollection, this, textOverflow);
       if (NS_FAILED(rv))
         break;
       if (!lineArea.IsEmpty()) {
         if (lineArea.y < lastY
             || lineArea.YMost() < lastYMost) {
           nonDecreasingYs = false;
         }
         lastY = lineArea.y;
@@ -6322,16 +6325,25 @@ nsBlockFrame::BuildDisplayList(nsDisplay
       lineCount++;
     }
 
     if (NS_SUCCEEDED(rv) && nonDecreasingYs && lineCount >= MIN_LINES_NEEDING_CURSOR) {
       SetupLineCursor();
     }
   }
 
+  // Pick up the resulting text-overflow markers.  We append them to
+  // PositionedDescendants just before we append the lines' display items,
+  // so that our text-overflow markers will appear on top of this block's
+  // normal content but below any of its its' positioned children.
+  if (textOverflow) {
+    aLists.PositionedDescendants()->AppendToTop(&textOverflow->GetMarkers());
+  }
+  linesDisplayListCollection.MoveTo(aLists);
+
   if (NS_SUCCEEDED(rv) && HasOutsideBullet()) {
     // Display outside bullets manually
     nsIFrame* bullet = GetOutsideBullet();
     rv = BuildDisplayListForChild(aBuilder, bullet, aDirtyRect, aLists);
   }
 
 #ifdef DEBUG
   if (gLamePaintMetrics) {