Bug 539356. Make PruneDisplayListForExtraPage prune print preview properly. r=mattwoodrow
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 28 Sep 2012 23:19:39 +1200
changeset 108581 23f1b8c7d17e912c28c35987c3b321641bcb5c8d
parent 108580 96752e66aaabd64af097b292b486980a3c7c5c91
child 108582 6b58397ad7354883d26b50622d89a29804b4f425
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersmattwoodrow
bugs539356
milestone18.0a1
Bug 539356. Make PruneDisplayListForExtraPage prune print preview properly. r=mattwoodrow PruneDisplayListForExtraPage wasn't pruning properly in print preview. It was pruning to the RootReferenceFrame, which is per-page when printing normally, but is the ancestor of all pages in print preview, so it wasn't doing anything in print preview. So, pass in the nsPageFrame we want to prune to. This prevents bogus entirely-clipped-out display items appearing in the display list for the page.
layout/generic/nsPageFrame.cpp
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -358,87 +358,89 @@ nsPageFrame::DrawHeaderFooter(nsRenderin
     aRenderingContext.PopState();
   }
 }
 
 /**
  * Remove all leaf display items that are not for descendants of
  * aBuilder->GetReferenceFrame() from aList, and move all nsDisplayClip
  * wrappers to their correct locations.
+ * @param aPage the page we're constructing the display list for
  * @param aExtraPage the page we constructed aList for
  * @param aY the Y-coordinate where aPage would be positioned relative
  * to the main page (aBuilder->GetReferenceFrame()), considering only
  * the content and ignoring page margins and dead space
  * @param aList the list that is modified in-place
  */
 static void
 PruneDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
-        nsIFrame* aExtraPage, nscoord aY, nsDisplayList* aList)
+                             nsPageFrame* aPage, nsIFrame* aExtraPage,
+                             nscoord aY, nsDisplayList* aList)
 {
   nsDisplayList newList;
-  // The page which we're really constructing a display list for
-  nsIFrame* mainPage = aBuilder->RootReferenceFrame();
 
   while (true) {
     nsDisplayItem* i = aList->RemoveBottom();
     if (!i)
       break;
     nsDisplayList* subList = i->GetList();
     if (subList) {
-      PruneDisplayListForExtraPage(aBuilder, aExtraPage, aY, subList);
+      PruneDisplayListForExtraPage(aBuilder, aPage, aExtraPage, aY, subList);
       nsDisplayItem::Type type = i->GetType();
       if (type == nsDisplayItem::TYPE_CLIP ||
           type == nsDisplayItem::TYPE_CLIP_ROUNDED_RECT) {
         // This might clip an element which should appear on the first
         // page, and that element might be visible if this uses a 'clip'
         // property with a negative top.
         // The clip area needs to be moved because the frame geometry doesn't
         // put page content frames for adjacent pages vertically adjacent,
         // there are page margins and dead space between them in print
         // preview, and in printing all pages are at (0,0)...
         // XXX we have no way to test this right now that I know of;
         // the 'clip' property requires an abs-pos element and we never
         // paint abs-pos elements that start after the main page
         // (bug 426909).
         nsDisplayClip* clip = static_cast<nsDisplayClip*>(i);
         clip->SetClipRect(clip->GetClipRect() + nsPoint(0, aY) -
-                aExtraPage->GetOffsetTo(mainPage));
+                aExtraPage->GetOffsetTo(aBuilder->FindReferenceFrameFor(aPage)));
       }
       newList.AppendToTop(i);
     } else {
       nsIFrame* f = i->GetUnderlyingFrame();
-      if (f && nsLayoutUtils::IsProperAncestorFrameCrossDoc(mainPage, f)) {
+      if (f && nsLayoutUtils::IsProperAncestorFrameCrossDoc(aPage, f)) {
         // This one is in the page we care about, keep it
         newList.AppendToTop(i);
       } else {
         // We're throwing this away so call its destructor now. The memory
         // is owned by aBuilder which destroys all items at once.
         i->~nsDisplayItem();
       }
     }
   }
   aList->AppendToTop(&newList);
 }
 
 
 static nsresult
 BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
-        nsIFrame* aPage, nscoord aY, nsDisplayList* aList)
+                             nsPageFrame* aPage, nsIFrame* aExtraPage,
+                             nscoord aY, nsDisplayList* aList)
 {
   nsDisplayList list;
   // Pass an empty dirty rect since we're only interested in finding
   // placeholders whose out-of-flows are in the page
   // aBuilder->GetReferenceFrame(), and the paths to those placeholders
   // have already been marked as NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO.
   // Note that we should still do a prune step since we don't want to
   // rely on dirty-rect checking for correctness.
-  nsresult rv = aPage->BuildDisplayListForStackingContext(aBuilder, nsRect(), &list);
+  nsresult rv =
+    aExtraPage->BuildDisplayListForStackingContext(aBuilder, nsRect(), &list);
   if (NS_FAILED(rv))
     return rv;
-  PruneDisplayListForExtraPage(aBuilder, aPage, aY, &list);
+  PruneDisplayListForExtraPage(aBuilder, aPage, aExtraPage, aY, &list);
   aList->AppendToTop(&list);
   return NS_OK;
 }
 
 static nsIFrame*
 GetNextPage(nsIFrame* aPageContentFrame)
 {
   // XXX ugh
@@ -493,17 +495,17 @@ nsPageFrame::BuildDisplayList(nsDisplayL
   // out-of-flow frames can't be placed after their placeholders so
   // we don't have to process earlier pages. The display lists for
   // these extra pages are pruned so that only display items for the
   // page we currently care about (which we would have reached by
   // following placeholders to their out-of-flows) end up on the list.
   nsIFrame* page = child;
   nscoord y = child->GetSize().height;
   while ((page = GetNextPage(page)) != nullptr) {
-    rv = BuildDisplayListForExtraPage(aBuilder, page, y, &content);
+    rv = BuildDisplayListForExtraPage(aBuilder, this, page, y, &content);
     if (NS_FAILED(rv))
       break;
     y += page->GetSize().height;
   }
 
   float scale = PresContext()->GetPageScale();
   nsRect clipRect(nsPoint(0, 0), child->GetSize());
   // Note: this computation matches how we compute maxSize.height