Bug 736915 - Print Selection prints a blank page when the selection is inside a table. r=bz
authorMats Palmgren <matspal@gmail.com>
Tue, 03 Apr 2012 02:30:45 +0200
changeset 94193 6642b531a08a0fe1be118b316c22aadf475452ce
parent 94192 b66d04ae6ae0f9684b15bb2eeed2c472f15417d8
child 94194 5f02ed27742455fc7e06c6d63ea3939e6446c718
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs736915
milestone14.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 736915 - Print Selection prints a blank page when the selection is inside a table. r=bz When rendering just the current Selection (Print - Selection) then don't create display items for table-related frames unless the frame itself is part of the selection, and always ask descendant frames to build display lists [in case they are selected].
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowGroupFrame.cpp
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -429,88 +429,87 @@ PaintTableCellSelection(nsIFrame* aFrame
   static_cast<nsTableCellFrame*>(aFrame)->DecorateForSelection(*aCtx, aPt);
 }
 
 NS_IMETHODIMP
 nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                    const nsRect&           aDirtyRect,
                                    const nsDisplayListSet& aLists)
 {
-  if (!IsVisibleInSelection(aBuilder))
-    return NS_OK;
-
   DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
-  nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
-  PRInt32 emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
-                              GetStyleTableBorder()->mEmptyCells
-                              : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
-  // take account of 'empty-cells'
-  if (GetStyleVisibility()->IsVisible() &&
-      (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
-
-
-    bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
-    if (!isRoot) {
-      nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
-      if (currentItem) {
-        currentItem->UpdateForFrameBackground(this);
+  if (IsVisibleInSelection(aBuilder)) {
+    nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
+    PRInt32 emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
+                                GetStyleTableBorder()->mEmptyCells
+                                : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
+    // take account of 'empty-cells'
+    if (GetStyleVisibility()->IsVisible() &&
+        (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
+    
+    
+      bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
+      if (!isRoot) {
+        nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
+        if (currentItem) {
+          currentItem->UpdateForFrameBackground(this);
+        }
+      }
+    
+      // display outset box-shadows if we need to.
+      bool hasBoxShadow = !!(GetStyleBorder()->mBoxShadow);
+      if (hasBoxShadow) {
+        nsresult rv = aLists.BorderBackground()->AppendNewToTop(
+            new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    
+      // display background if we need to.
+      if (aBuilder->IsForEventDelivery() ||
+          (((!tableFrame->IsBorderCollapse() || isRoot) &&
+          (!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance)))) {
+        // The cell background was not painted by the nsTablePainter,
+        // so we need to do it. We have special background processing here
+        // so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline
+        nsDisplayTableItem* item =
+          new (aBuilder) nsDisplayTableCellBackground(aBuilder, this);
+        nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
+        NS_ENSURE_SUCCESS(rv, rv);
+        item->UpdateForFrameBackground(this);
+      }
+    
+      // display inset box-shadows if we need to.
+      if (hasBoxShadow) {
+        nsresult rv = aLists.BorderBackground()->AppendNewToTop(
+            new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    
+      // display borders if we need to
+      if (!tableFrame->IsBorderCollapse() && HasBorder() &&
+          emptyCellStyle == NS_STYLE_TABLE_EMPTY_CELLS_SHOW) {
+        nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
+            nsDisplayBorder(aBuilder, this));
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    
+      // and display the selection border if we need to
+      if (IsSelected()) {
+        nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
+            nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
+                             "TableCellSelection",
+                             nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
+        NS_ENSURE_SUCCESS(rv, rv);
       }
     }
-
-    // display outset box-shadows if we need to.
-    bool hasBoxShadow = !!(GetStyleBorder()->mBoxShadow);
-    if (hasBoxShadow) {
-      nsresult rv = aLists.BorderBackground()->AppendNewToTop(
-          new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    // display background if we need to.
-    if (aBuilder->IsForEventDelivery() ||
-        (((!tableFrame->IsBorderCollapse() || isRoot) &&
-        (!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance)))) {
-      // The cell background was not painted by the nsTablePainter,
-      // so we need to do it. We have special background processing here
-      // so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline
-      nsDisplayTableItem* item =
-        new (aBuilder) nsDisplayTableCellBackground(aBuilder, this);
-      nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
-      NS_ENSURE_SUCCESS(rv, rv);
-      item->UpdateForFrameBackground(this);
-    }
-
-    // display inset box-shadows if we need to.
-    if (hasBoxShadow) {
-      nsresult rv = aLists.BorderBackground()->AppendNewToTop(
-          new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    // display borders if we need to
-    if (!tableFrame->IsBorderCollapse() && HasBorder() &&
-        emptyCellStyle == NS_STYLE_TABLE_EMPTY_CELLS_SHOW) {
-      nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
-          nsDisplayBorder(aBuilder, this));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    // and display the selection border if we need to
-    if (IsSelected()) {
-      nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
-          nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
-                           "TableCellSelection",
-                           nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
+    
+    // the 'empty-cells' property has no effect on 'outline'
+    nsresult rv = DisplayOutline(aBuilder, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // the 'empty-cells' property has no effect on 'outline'
-  nsresult rv = DisplayOutline(aBuilder, aLists);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Push a null 'current table item' so that descendant tables can't
   // accidentally mess with our table
   nsAutoPushCurrentTableItem pushTableItem;
   pushTableItem.Push(aBuilder, nsnull);
 
   nsIFrame* kid = mFrames.FirstChild();
   NS_ASSERTION(kid && !kid->GetNextSibling(), "Table cells should have just one child");
   // The child's background will go in our BorderBackground() list.
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1265,46 +1265,44 @@ AnyTablePartHasBorderOrBackground(nsIFra
 
 // table paint code is concerned primarily with borders and bg color
 // SEC: TODO: adjust the rect for captions
 NS_IMETHODIMP
 nsTableFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                const nsRect&           aDirtyRect,
                                const nsDisplayListSet& aLists)
 {
-  if (!IsVisibleInSelection(aBuilder))
-    return NS_OK;
-
   DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
 
-  if (GetStyleVisibility()->IsVisible()) {
-    nsMargin deflate = GetDeflationForBackground(PresContext());
-    // If 'deflate' is (0,0,0,0) then we can paint the table background
-    // in its own display item, so do that to take advantage of
-    // opacity and visibility optimizations
-    if (deflate == nsMargin(0, 0, 0, 0)) {
-      nsresult rv = DisplayBackgroundUnconditional(aBuilder, aLists, false);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-
   nsDisplayTableItem* item = nsnull;
-  // This background is created if any of the table parts are visible,
-  // or if we're doing event handling (since DisplayGenericTablePart
-  // needs the item for the |sortEventBackgrounds|-dependent code).
-  // Specific visibility decisions are delegated to the table background
-  // painter, which handles borders and backgrounds for the table.
-  if (aBuilder->IsForEventDelivery() ||
-      AnyTablePartHasBorderOrBackground(this, GetNextSibling()) ||
-      AnyTablePartHasBorderOrBackground(mColGroups.FirstChild(), nsnull)) {
-    item = new (aBuilder) nsDisplayTableBorderBackground(aBuilder, this);
-    nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
+  if (IsVisibleInSelection(aBuilder)) {
+    if (GetStyleVisibility()->IsVisible()) {
+      nsMargin deflate = GetDeflationForBackground(PresContext());
+      // If 'deflate' is (0,0,0,0) then we can paint the table background
+      // in its own display item, so do that to take advantage of
+      // opacity and visibility optimizations
+      if (deflate == nsMargin(0, 0, 0, 0)) {
+        nsresult rv = DisplayBackgroundUnconditional(aBuilder, aLists, false);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    }
+    
+    // This background is created if any of the table parts are visible,
+    // or if we're doing event handling (since DisplayGenericTablePart
+    // needs the item for the |sortEventBackgrounds|-dependent code).
+    // Specific visibility decisions are delegated to the table background
+    // painter, which handles borders and backgrounds for the table.
+    if (aBuilder->IsForEventDelivery() ||
+        AnyTablePartHasBorderOrBackground(this, GetNextSibling()) ||
+        AnyTablePartHasBorderOrBackground(mColGroups.FirstChild(), nsnull)) {
+      item = new (aBuilder) nsDisplayTableBorderBackground(aBuilder, this);
+      nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
   return DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
 }
 
 nsMargin
 nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const
 {
   if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode() ||
       !IsBorderCollapse())
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -333,18 +333,16 @@ nsTableOuterFrame::RemoveFrame(ChildList
 
 NS_METHOD 
 nsTableOuterFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
 {
   // No border, background or outline are painted because they all belong
   // to the inner table.
-  if (!IsVisibleInSelection(aBuilder))
-    return NS_OK;
 
   // If there's no caption, take a short cut to avoid having to create
   // the special display list set and then sort it.
   if (mCaptionFrames.IsEmpty())
     return BuildDisplayListForInnerTable(aBuilder, aDirtyRect, aLists);
     
   nsDisplayListCollection set;
   nsresult rv = BuildDisplayListForInnerTable(aBuilder, aDirtyRect, set);
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -584,33 +584,31 @@ nsDisplayTableRowBackground::Paint(nsDis
   painter.PaintRow(static_cast<nsTableRowFrame*>(mFrame));
 }
 
 NS_IMETHODIMP
 nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                   const nsRect&           aDirtyRect,
                                   const nsDisplayListSet& aLists)
 {
-  if (!IsVisibleInSelection(aBuilder))
-    return NS_OK;
-
-  bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
   nsDisplayTableItem* item = nsnull;
-  if (isRoot) {
-    // This background is created regardless of whether this frame is
-    // visible or not. Visibility decisions are delegated to the
-    // table background painter.
-    // We would use nsDisplayGeneric for this rare case except that we
-    // need the background to be larger than the row frame in some
-    // cases.
-    item = new (aBuilder) nsDisplayTableRowBackground(aBuilder, this);
-    nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (IsVisibleInSelection(aBuilder)) {
+    bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
+    if (isRoot) {
+      // This background is created regardless of whether this frame is
+      // visible or not. Visibility decisions are delegated to the
+      // table background painter.
+      // We would use nsDisplayGeneric for this rare case except that we
+      // need the background to be larger than the row frame in some
+      // cases.
+      item = new (aBuilder) nsDisplayTableRowBackground(aBuilder, this);
+      nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
   }
-  
   return nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
 }
 
 PRIntn
 nsTableRowFrame::GetSkipSides() const
 {
   PRIntn skip = 0;
   if (nsnull != GetPrevInFlow()) {
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -243,30 +243,28 @@ DisplayRows(nsDisplayListBuilder* aBuild
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                        const nsRect&           aDirtyRect,
                                        const nsDisplayListSet& aLists)
 {
-  if (!IsVisibleInSelection(aBuilder))
-    return NS_OK;
-
-  bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
   nsDisplayTableItem* item = nsnull;
-  if (isRoot) {
-    // This background is created regardless of whether this frame is
-    // visible or not. Visibility decisions are delegated to the
-    // table background painter.
-    item = new (aBuilder) nsDisplayTableRowGroupBackground(aBuilder, this);
-    nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  
+  if (IsVisibleInSelection(aBuilder)) {
+    bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
+    if (isRoot) {
+      // This background is created regardless of whether this frame is
+      // visible or not. Visibility decisions are delegated to the
+      // table background painter.
+      item = new (aBuilder) nsDisplayTableRowGroupBackground(aBuilder, this);
+      nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }  
   return nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect,
                                                aLists, item, DisplayRows);
 }
 
 PRIntn
 nsTableRowGroupFrame::GetSkipSides() const
 {
   PRIntn skip = 0;