Bug 736915 - Print Selection prints a blank page when the selection is inside a table. r=bz, a=lsblakk
authorMats Palmgren <matspal@gmail.com>
Tue, 03 Apr 2012 02:30:45 +0200
changeset 92013 d4c63d6b84db2e7f1c51cbd204857fc478820dd0
parent 92012 a923cadf7b8d6bbefd7a9dd12003d7357c226f96
child 92014 ac43257b27fef4699eb9fecfd201cfea2690838e
push idunknown
push userunknown
push dateunknown
reviewersbz, lsblakk
bugs736915
milestone13.0a2
Bug 736915 - Print Selection prints a blank page when the selection is inside a table. r=bz, a=lsblakk 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;