LCOV - code coverage report
Current view: top level - layout/tables - nsTableCellFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 539 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 67 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsTableCellFrame.h"
       7             : 
       8             : #include "gfxContext.h"
       9             : #include "gfxUtils.h"
      10             : #include "mozilla/gfx/2D.h"
      11             : #include "mozilla/gfx/Helpers.h"
      12             : #include "nsTableFrame.h"
      13             : #include "nsTableColFrame.h"
      14             : #include "nsTableRowFrame.h"
      15             : #include "nsTableRowGroupFrame.h"
      16             : #include "nsStyleContext.h"
      17             : #include "nsStyleConsts.h"
      18             : #include "nsPresContext.h"
      19             : #include "nsCSSRendering.h"
      20             : #include "nsIContent.h"
      21             : #include "nsGenericHTMLElement.h"
      22             : #include "nsAttrValueInlines.h"
      23             : #include "nsHTMLParts.h"
      24             : #include "nsGkAtoms.h"
      25             : #include "nsIPresShell.h"
      26             : #include "nsCOMPtr.h"
      27             : #include "nsIServiceManager.h"
      28             : #include "nsIDOMNode.h"
      29             : #include "nsNameSpaceManager.h"
      30             : #include "nsDisplayList.h"
      31             : #include "nsLayoutUtils.h"
      32             : #include "nsTextFrame.h"
      33             : #include "FrameLayerBuilder.h"
      34             : #include <algorithm>
      35             : 
      36             : //TABLECELL SELECTION
      37             : #include "nsFrameSelection.h"
      38             : #include "mozilla/LookAndFeel.h"
      39             : 
      40             : using namespace mozilla;
      41             : using namespace mozilla::gfx;
      42             : using namespace mozilla::image;
      43             : 
      44           0 : nsTableCellFrame::nsTableCellFrame(nsStyleContext* aContext,
      45             :                                    nsTableFrame* aTableFrame,
      46           0 :                                    ClassID aID)
      47             :   : nsContainerFrame(aContext, aID)
      48           0 :   , mDesiredSize(aTableFrame->GetWritingMode())
      49             : {
      50           0 :   mColIndex = 0;
      51           0 :   mPriorAvailISize = 0;
      52             : 
      53           0 :   SetContentEmpty(false);
      54           0 :   SetHasPctOverBSize(false);
      55           0 : }
      56             : 
      57           0 : nsTableCellFrame::~nsTableCellFrame()
      58             : {
      59           0 : }
      60             : 
      61           0 : NS_IMPL_FRAMEARENA_HELPERS(nsTableCellFrame)
      62             : 
      63             : nsTableCellFrame*
      64           0 : nsTableCellFrame::GetNextCell() const
      65             : {
      66           0 :   nsIFrame* childFrame = GetNextSibling();
      67           0 :   while (childFrame) {
      68           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
      69           0 :     if (cellFrame) {
      70           0 :       return cellFrame;
      71             :     }
      72           0 :     childFrame = childFrame->GetNextSibling();
      73             :   }
      74           0 :   return nullptr;
      75             : }
      76             : 
      77             : void
      78           0 : nsTableCellFrame::Init(nsIContent*       aContent,
      79             :                        nsContainerFrame* aParent,
      80             :                        nsIFrame*         aPrevInFlow)
      81             : {
      82             :   // Let the base class do its initialization
      83           0 :   nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
      84             : 
      85           0 :   if (HasAnyStateBits(NS_FRAME_FONT_INFLATION_CONTAINER)) {
      86           0 :     AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
      87             :   }
      88             : 
      89           0 :   if (aPrevInFlow) {
      90             :     // Set the column index
      91           0 :     nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
      92             :     int32_t           colIndex;
      93           0 :     cellFrame->GetColIndex(colIndex);
      94           0 :     SetColIndex(colIndex);
      95             :   } else {
      96             :     // Although the spec doesn't say that writing-mode is not applied to
      97             :     // table-cells, we still override style value here because we want to
      98             :     // make effective writing mode of table structure frames consistent
      99             :     // within a table. The content inside table cells is reflowed by an
     100             :     // anonymous block, hence their writing mode is not affected.
     101           0 :     mWritingMode = GetTableFrame()->GetWritingMode();
     102             :   }
     103           0 : }
     104             : 
     105             : void
     106           0 : nsTableCellFrame::DestroyFrom(nsIFrame* aDestructRoot)
     107             : {
     108           0 :   if (HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
     109           0 :     nsTableFrame::UnregisterPositionedTablePart(this, aDestructRoot);
     110             :   }
     111             : 
     112           0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     113           0 : }
     114             : 
     115             : // nsIPercentBSizeObserver methods
     116             : 
     117             : void
     118           0 : nsTableCellFrame::NotifyPercentBSize(const ReflowInput& aReflowInput)
     119             : {
     120             :   // ReflowInput ensures the mCBReflowInput of blocks inside a
     121             :   // cell is the cell frame, not the inner-cell block, and that the
     122             :   // containing block of an inner table is the containing block of its
     123             :   // table wrapper.
     124             :   // XXXldb Given the now-stricter |NeedsToObserve|, many if not all of
     125             :   // these tests are probably unnecessary.
     126             : 
     127             :   // Maybe the cell reflow state; we sure if we're inside the |if|.
     128           0 :   const ReflowInput *cellRI = aReflowInput.mCBReflowInput;
     129             : 
     130           0 :   if (cellRI && cellRI->mFrame == this &&
     131           0 :       (cellRI->ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
     132           0 :        cellRI->ComputedBSize() == 0)) { // XXXldb Why 0?
     133             :     // This is a percentage bsize on a frame whose percentage bsizes
     134             :     // are based on the bsize of the cell, since its containing block
     135             :     // is the inner cell frame.
     136             : 
     137             :     // We'll only honor the percent bsize if sibling-cells/ancestors
     138             :     // have specified/pct bsize. (Also, siblings only count for this if
     139             :     // both this cell and the sibling cell span exactly 1 row.)
     140             : 
     141           0 :     if (nsTableFrame::AncestorsHaveStyleBSize(*cellRI) ||
     142           0 :         (GetTableFrame()->GetEffectiveRowSpan(*this) == 1 &&
     143           0 :          cellRI->mParentReflowInput->mFrame->
     144           0 :            HasAnyStateBits(NS_ROW_HAS_CELL_WITH_STYLE_BSIZE))) {
     145             : 
     146           0 :       for (const ReflowInput *rs = aReflowInput.mParentReflowInput;
     147           0 :            rs != cellRI;
     148           0 :            rs = rs->mParentReflowInput) {
     149           0 :         rs->mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
     150             :       }
     151             : 
     152           0 :       nsTableFrame::RequestSpecialBSizeReflow(*cellRI);
     153             :     }
     154             :   }
     155           0 : }
     156             : 
     157             : // The cell needs to observe its block and things inside its block but nothing below that
     158             : bool
     159           0 : nsTableCellFrame::NeedsToObserve(const ReflowInput& aReflowInput)
     160             : {
     161           0 :   const ReflowInput *rs = aReflowInput.mParentReflowInput;
     162           0 :   if (!rs)
     163           0 :     return false;
     164           0 :   if (rs->mFrame == this) {
     165             :     // We always observe the child block.  It will never send any
     166             :     // notifications, but we need this so that the observer gets
     167             :     // propagated to its kids.
     168           0 :     return true;
     169             :   }
     170           0 :   rs = rs->mParentReflowInput;
     171           0 :   if (!rs) {
     172           0 :     return false;
     173             :   }
     174             : 
     175             :   // We always need to let the percent bsize observer be propagated
     176             :   // from a table wrapper frame to an inner table frame.
     177           0 :   LayoutFrameType fType = aReflowInput.mFrame->Type();
     178           0 :   if (fType == LayoutFrameType::Table) {
     179           0 :     return true;
     180             :   }
     181             : 
     182             :   // We need the observer to be propagated to all children of the cell
     183             :   // (i.e., children of the child block) in quirks mode, but only to
     184             :   // tables in standards mode.
     185             :   // XXX This may not be true in the case of orthogonal flows within
     186             :   // the cell (bug 1174711 comment 8); we may need to observe isizes
     187             :   // instead of bsizes for orthogonal children.
     188           0 :   return rs->mFrame == this &&
     189           0 :          (PresContext()->CompatibilityMode() == eCompatibility_NavQuirks ||
     190           0 :           fType == LayoutFrameType::TableWrapper);
     191             : }
     192             : 
     193             : nsresult
     194           0 : nsTableCellFrame::GetRowIndex(int32_t &aRowIndex) const
     195             : {
     196             :   nsresult result;
     197           0 :   nsTableRowFrame* row = static_cast<nsTableRowFrame*>(GetParent());
     198           0 :   if (row) {
     199           0 :     aRowIndex = row->GetRowIndex();
     200           0 :     result = NS_OK;
     201             :   }
     202             :   else {
     203           0 :     aRowIndex = 0;
     204           0 :     result = NS_ERROR_NOT_INITIALIZED;
     205             :   }
     206           0 :   return result;
     207             : }
     208             : 
     209             : nsresult
     210           0 : nsTableCellFrame::GetColIndex(int32_t &aColIndex) const
     211             : {
     212           0 :   if (GetPrevInFlow()) {
     213           0 :     return static_cast<nsTableCellFrame*>(FirstInFlow())->GetColIndex(aColIndex);
     214             :   }
     215             :   else {
     216           0 :     aColIndex = mColIndex;
     217           0 :     return  NS_OK;
     218             :   }
     219             : }
     220             : 
     221             : nsresult
     222           0 : nsTableCellFrame::AttributeChanged(int32_t         aNameSpaceID,
     223             :                                    nsIAtom*        aAttribute,
     224             :                                    int32_t         aModType)
     225             : {
     226             :   // We need to recalculate in this case because of the nowrap quirk in
     227             :   // BasicTableLayoutStrategy
     228           0 :   if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::nowrap &&
     229           0 :       PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) {
     230           0 :     PresContext()->PresShell()->
     231           0 :       FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
     232             :   }
     233             :   // let the table frame decide what to do
     234           0 :   GetTableFrame()->AttributeChangedFor(this, mContent, aAttribute);
     235           0 :   return NS_OK;
     236             : }
     237             : 
     238             : /* virtual */ void
     239           0 : nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     240             : {
     241           0 :   nsContainerFrame::DidSetStyleContext(aOldStyleContext);
     242             : 
     243           0 :   if (!aOldStyleContext) //avoid this on init
     244           0 :     return;
     245             : 
     246           0 :   nsTableFrame* tableFrame = GetTableFrame();
     247           0 :   if (tableFrame->IsBorderCollapse() &&
     248           0 :       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
     249             :     int32_t colIndex, rowIndex;
     250           0 :     GetColIndex(colIndex);
     251           0 :     GetRowIndex(rowIndex);
     252             :     // row span needs to be clamped as we do not create rows in the cellmap
     253             :     // which do not have cells originating in them
     254             :     TableArea damageArea(colIndex, rowIndex, GetColSpan(),
     255           0 :       std::min(GetRowSpan(), tableFrame->GetRowCount() - rowIndex));
     256           0 :     tableFrame->AddBCDamageArea(damageArea);
     257             :   }
     258             : }
     259             : 
     260             : #ifdef DEBUG
     261             : void
     262           0 : nsTableCellFrame::AppendFrames(ChildListID     aListID,
     263             :                                nsFrameList&    aFrameList)
     264             : {
     265           0 :   MOZ_CRASH("unsupported operation");
     266             : }
     267             : 
     268             : void
     269           0 : nsTableCellFrame::InsertFrames(ChildListID     aListID,
     270             :                                nsIFrame*       aPrevFrame,
     271             :                                nsFrameList&    aFrameList)
     272             : {
     273           0 :   MOZ_CRASH("unsupported operation");
     274             : }
     275             : 
     276             : void
     277           0 : nsTableCellFrame::RemoveFrame(ChildListID     aListID,
     278             :                               nsIFrame*       aOldFrame)
     279             : {
     280           0 :   MOZ_CRASH("unsupported operation");
     281             : }
     282             : #endif
     283             : 
     284           0 : void nsTableCellFrame::SetColIndex(int32_t aColIndex)
     285             : {
     286           0 :   mColIndex = aColIndex;
     287           0 : }
     288             : 
     289             : /* virtual */ nsMargin
     290           0 : nsTableCellFrame::GetUsedMargin() const
     291             : {
     292           0 :   return nsMargin(0,0,0,0);
     293             : }
     294             : 
     295             : //ASSURE DIFFERENT COLORS for selection
     296           0 : inline nscolor EnsureDifferentColors(nscolor colorA, nscolor colorB)
     297             : {
     298           0 :     if (colorA == colorB)
     299             :     {
     300             :       nscolor res;
     301           0 :       res = NS_RGB(NS_GET_R(colorA) ^ 0xff,
     302             :                    NS_GET_G(colorA) ^ 0xff,
     303             :                    NS_GET_B(colorA) ^ 0xff);
     304           0 :       return res;
     305             :     }
     306           0 :     return colorA;
     307             : }
     308             : 
     309             : void
     310           0 : nsTableCellFrame::DecorateForSelection(DrawTarget* aDrawTarget, nsPoint aPt)
     311             : {
     312           0 :   NS_ASSERTION(IsSelected(), "Should only be called for selected cells");
     313             :   int16_t displaySelection;
     314           0 :   nsPresContext* presContext = PresContext();
     315           0 :   displaySelection = DisplaySelection(presContext);
     316           0 :   if (displaySelection) {
     317             :     RefPtr<nsFrameSelection> frameSelection =
     318           0 :       presContext->PresShell()->FrameSelection();
     319             : 
     320           0 :     if (frameSelection->GetTableCellSelection()) {
     321             :       nscolor       bordercolor;
     322           0 :       if (displaySelection == nsISelectionController::SELECTION_DISABLED) {
     323           0 :         bordercolor = NS_RGB(176,176,176);// disabled color
     324             :       }
     325             :       else {
     326             :         bordercolor =
     327           0 :           LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectBackground);
     328             :       }
     329           0 :       nscoord threePx = nsPresContext::CSSPixelsToAppUnits(3);
     330           0 :       if ((mRect.width > threePx) && (mRect.height > threePx)) {
     331             :         //compare bordercolor to background-color
     332           0 :         bordercolor = EnsureDifferentColors(
     333           0 :           bordercolor, StyleBackground()->BackgroundColor(this));
     334             : 
     335           0 :         int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
     336           0 :         Point devPixelOffset = NSPointToPoint(aPt, appUnitsPerDevPixel);
     337             : 
     338           0 :         AutoRestoreTransform autoRestoreTransform(aDrawTarget);
     339             :         aDrawTarget->SetTransform(
     340           0 :           aDrawTarget->GetTransform().PreTranslate(devPixelOffset));
     341             : 
     342           0 :         ColorPattern color(ToDeviceColor(bordercolor));
     343             : 
     344           0 :         nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
     345             : 
     346           0 :         StrokeLineWithSnapping(nsPoint(onePixel, 0), nsPoint(mRect.width, 0),
     347           0 :                                appUnitsPerDevPixel, *aDrawTarget, color);
     348           0 :         StrokeLineWithSnapping(nsPoint(0, onePixel), nsPoint(0, mRect.height),
     349           0 :                                appUnitsPerDevPixel, *aDrawTarget, color);
     350           0 :         StrokeLineWithSnapping(nsPoint(onePixel, mRect.height),
     351           0 :                                nsPoint(mRect.width, mRect.height),
     352           0 :                                appUnitsPerDevPixel, *aDrawTarget, color);
     353           0 :         StrokeLineWithSnapping(nsPoint(mRect.width, onePixel),
     354           0 :                                nsPoint(mRect.width, mRect.height),
     355           0 :                                appUnitsPerDevPixel, *aDrawTarget, color);
     356             :         //middle
     357             :         nsRect r(onePixel, onePixel,
     358           0 :                  mRect.width - onePixel, mRect.height - onePixel);
     359             :         Rect devPixelRect =
     360           0 :           NSRectToSnappedRect(r, appUnitsPerDevPixel, *aDrawTarget);
     361           0 :         aDrawTarget->StrokeRect(devPixelRect, color);
     362             :         //shading
     363           0 :         StrokeLineWithSnapping(nsPoint(2*onePixel, mRect.height-2*onePixel),
     364           0 :                                nsPoint(mRect.width-onePixel, mRect.height- (2*onePixel)),
     365           0 :                                appUnitsPerDevPixel, *aDrawTarget, color);
     366           0 :         StrokeLineWithSnapping(nsPoint(mRect.width - (2*onePixel), 2*onePixel),
     367           0 :                                nsPoint(mRect.width - (2*onePixel), mRect.height-onePixel),
     368           0 :                                appUnitsPerDevPixel, *aDrawTarget, color);
     369             :       }
     370             :     }
     371             :   }
     372           0 : }
     373             : 
     374             : DrawResult
     375           0 : nsTableCellFrame::PaintBackground(gfxContext&          aRenderingContext,
     376             :                                   const nsRect&        aDirtyRect,
     377             :                                   nsPoint              aPt,
     378             :                                   uint32_t             aFlags)
     379             : {
     380           0 :   nsRect rect(aPt, GetSize());
     381             :   nsCSSRendering::PaintBGParams params =
     382           0 :     nsCSSRendering::PaintBGParams::ForAllLayers(*PresContext(),
     383             :                                                 aDirtyRect, rect,
     384           0 :                                                 this, aFlags);
     385           0 :   return nsCSSRendering::PaintStyleImageLayer(params, aRenderingContext);
     386             : }
     387             : 
     388             : nsresult
     389           0 : nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame,
     390             :                                  nsDisplayListBuilder* aBuilder,
     391             :                                  const nsDisplayListSet& aLists)
     392             : {
     393           0 :   const nsStyleBorder* borderStyle = StyleBorder();
     394           0 :   if (aFrame->IsBorderCollapse() || !borderStyle->HasBorder())
     395           0 :     return NS_OK;
     396             : 
     397           0 :   if (!GetContentEmpty() ||
     398           0 :       StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW) {
     399           0 :     aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     400           0 :                                               nsDisplayBorder(aBuilder, this));
     401             :   }
     402             : 
     403           0 :   return NS_OK;
     404             : }
     405             : 
     406             : class nsDisplayTableCellBackground : public nsDisplayTableItem {
     407             : public:
     408             :   nsDisplayTableCellBackground(nsDisplayListBuilder* aBuilder,
     409             :                                nsTableCellFrame* aFrame) :
     410             :     nsDisplayTableItem(aBuilder, aFrame) {
     411             :     MOZ_COUNT_CTOR(nsDisplayTableCellBackground);
     412             :   }
     413             : #ifdef NS_BUILD_REFCNT_LOGGING
     414           0 :   virtual ~nsDisplayTableCellBackground() {
     415           0 :     MOZ_COUNT_DTOR(nsDisplayTableCellBackground);
     416           0 :   }
     417             : #endif
     418             : 
     419           0 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
     420             :                        HitTestState* aState,
     421             :                        nsTArray<nsIFrame*> *aOutFrames) override {
     422           0 :     aOutFrames->AppendElement(mFrame);
     423           0 :   }
     424             :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     425             :                      gfxContext* aCtx) override;
     426             :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
     427             :                            bool* aSnap) override;
     428           0 :   NS_DISPLAY_DECL_NAME("TableCellBackground", TYPE_TABLE_CELL_BACKGROUND)
     429             : };
     430             : 
     431           0 : void nsDisplayTableCellBackground::Paint(nsDisplayListBuilder* aBuilder,
     432             :                                          gfxContext* aCtx)
     433             : {
     434           0 :   DrawResult result = static_cast<nsTableCellFrame*>(mFrame)->
     435           0 :     PaintBackground(*aCtx, mVisibleRect, ToReferenceFrame(),
     436           0 :                     aBuilder->GetBackgroundPaintFlags());
     437             : 
     438           0 :   nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
     439           0 : }
     440             : 
     441             : nsRect
     442           0 : nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder,
     443             :                                         bool* aSnap)
     444             : {
     445             :   // revert from nsDisplayTableItem's implementation ... cell backgrounds
     446             :   // don't overflow the cell
     447           0 :   return nsDisplayItem::GetBounds(aBuilder, aSnap);
     448             : }
     449             : 
     450           0 : void nsTableCellFrame::InvalidateFrame(uint32_t aDisplayItemKey)
     451             : {
     452           0 :   nsIFrame::InvalidateFrame(aDisplayItemKey);
     453           0 :   GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
     454           0 : }
     455             : 
     456           0 : void nsTableCellFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
     457             : {
     458           0 :   nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
     459             :   // If we have filters applied that would affects our bounds, then
     460             :   // we get an inactive layer created and this is computed
     461             :   // within FrameLayerBuilder
     462           0 :   GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
     463           0 : }
     464             : 
     465             : static void
     466           0 : PaintTableCellSelection(nsIFrame* aFrame, DrawTarget* aDrawTarget,
     467             :                         const nsRect& aRect, nsPoint aPt)
     468             : {
     469           0 :   static_cast<nsTableCellFrame*>(aFrame)->DecorateForSelection(aDrawTarget,
     470           0 :                                                                aPt);
     471           0 : }
     472             : 
     473             : void
     474           0 : nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     475             :                                    const nsRect&           aDirtyRect,
     476             :                                    const nsDisplayListSet& aLists)
     477             : {
     478           0 :   DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
     479           0 :   nsTableFrame* tableFrame = GetTableFrame();
     480           0 :   int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
     481           0 :                               StyleTableBorder()->mEmptyCells
     482           0 :                               : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
     483             :   // take account of 'empty-cells'
     484           0 :   if (StyleVisibility()->IsVisible() &&
     485             :       (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
     486             :     // display outset box-shadows if we need to.
     487           0 :     bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
     488           0 :     if (hasBoxShadow) {
     489           0 :       aLists.BorderBackground()->AppendNewToTop(
     490           0 :         new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
     491             :     }
     492             : 
     493             :     // display background if we need to.
     494           0 :     if (aBuilder->IsForEventDelivery() ||
     495           0 :         !StyleBackground()->IsTransparent(this) ||
     496           0 :         StyleDisplay()->mAppearance) {
     497           0 :       nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
     498             :           this,
     499           0 :           GetRectRelativeToSelf(),
     500           0 :           aLists.BorderBackground());
     501             :     }
     502             : 
     503             :     // display inset box-shadows if we need to.
     504           0 :     if (hasBoxShadow) {
     505           0 :       aLists.BorderBackground()->AppendNewToTop(
     506           0 :         new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
     507             :     }
     508             : 
     509             :     // display borders if we need to
     510           0 :     ProcessBorders(tableFrame, aBuilder, aLists);
     511             : 
     512             :     // and display the selection border if we need to
     513           0 :     if (IsSelected()) {
     514           0 :       aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     515             :         nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
     516             :                          "TableCellSelection",
     517           0 :                          nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
     518             :     }
     519             :   }
     520             : 
     521             :   // the 'empty-cells' property has no effect on 'outline'
     522           0 :   DisplayOutline(aBuilder, aLists);
     523             : 
     524             :   // Push a null 'current table item' so that descendant tables can't
     525             :   // accidentally mess with our table
     526           0 :   nsAutoPushCurrentTableItem pushTableItem;
     527           0 :   pushTableItem.Push(aBuilder, nullptr);
     528             : 
     529           0 :   nsIFrame* kid = mFrames.FirstChild();
     530           0 :   NS_ASSERTION(kid && !kid->GetNextSibling(), "Table cells should have just one child");
     531             :   // The child's background will go in our BorderBackground() list.
     532             :   // This isn't a problem since it won't have a real background except for
     533             :   // event handling. We do not call BuildDisplayListForNonBlockChildren
     534             :   // because that/ would put the child's background in the Content() list
     535             :   // which isn't right (e.g., would end up on top of our child floats for
     536             :   // event handling).
     537           0 :   BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
     538           0 : }
     539             : 
     540             : nsIFrame::LogicalSides
     541           0 : nsTableCellFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
     542             : {
     543           0 :   if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
     544             :                      StyleBoxDecorationBreak::Clone)) {
     545           0 :     return LogicalSides();
     546             :   }
     547             : 
     548           0 :   LogicalSides skip;
     549           0 :   if (nullptr != GetPrevInFlow()) {
     550           0 :     skip |= eLogicalSideBitsBStart;
     551             :   }
     552           0 :   if (nullptr != GetNextInFlow()) {
     553           0 :     skip |= eLogicalSideBitsBEnd;
     554             :   }
     555           0 :   return skip;
     556             : }
     557             : 
     558             : /* virtual */ nsMargin
     559           0 : nsTableCellFrame::GetBorderOverflow()
     560             : {
     561           0 :   return nsMargin(0, 0, 0, 0);
     562             : }
     563             : 
     564             : // Align the cell's child frame within the cell
     565             : 
     566           0 : void nsTableCellFrame::BlockDirAlignChild(WritingMode aWM, nscoord aMaxAscent)
     567             : {
     568             :   /* It's the 'border-collapse' on the table that matters */
     569           0 :   LogicalMargin borderPadding = GetLogicalUsedBorderAndPadding(aWM);
     570             : 
     571           0 :   nscoord bStartInset = borderPadding.BStart(aWM);
     572           0 :   nscoord bEndInset = borderPadding.BEnd(aWM);
     573             : 
     574           0 :   uint8_t verticalAlignFlags = GetVerticalAlign();
     575             : 
     576           0 :   nscoord bSize = BSize(aWM);
     577           0 :   nsIFrame* firstKid = mFrames.FirstChild();
     578           0 :   nsSize containerSize = mRect.Size();
     579           0 :   NS_ASSERTION(firstKid, "Frame construction error, a table cell always has "
     580             :                          "an inner cell frame");
     581           0 :   LogicalRect kidRect = firstKid->GetLogicalRect(aWM, containerSize);
     582           0 :   nscoord childBSize = kidRect.BSize(aWM);
     583             : 
     584             :   // Vertically align the child
     585           0 :   nscoord kidBStart = 0;
     586           0 :   switch (verticalAlignFlags)
     587             :   {
     588             :     case NS_STYLE_VERTICAL_ALIGN_BASELINE:
     589             :       // Align the baselines of the child frame with the baselines of
     590             :       // other children in the same row which have 'vertical-align: baseline'
     591           0 :       kidBStart = bStartInset + aMaxAscent - GetCellBaseline();
     592           0 :     break;
     593             : 
     594             :     case NS_STYLE_VERTICAL_ALIGN_TOP:
     595             :       // Align the top of the child frame with the top of the content area,
     596           0 :       kidBStart = bStartInset;
     597           0 :     break;
     598             : 
     599             :     case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
     600             :       // Align the bottom of the child frame with the bottom of the content area,
     601           0 :       kidBStart = bSize - childBSize - bEndInset;
     602           0 :     break;
     603             : 
     604             :     default:
     605             :     case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
     606             :       // Align the middle of the child frame with the middle of the content area,
     607           0 :       kidBStart = (bSize - childBSize - bEndInset + bStartInset) / 2;
     608             :   }
     609             :   // If the content is larger than the cell bsize, align from bStartInset
     610             :   // (cell's content-box bstart edge).
     611           0 :   kidBStart = std::max(bStartInset, kidBStart);
     612             : 
     613           0 :   if (kidBStart != kidRect.BStart(aWM)) {
     614             :     // Invalidate at the old position first
     615           0 :     firstKid->InvalidateFrameSubtree();
     616             :   }
     617             : 
     618           0 :   firstKid->SetPosition(aWM, LogicalPoint(aWM, kidRect.IStart(aWM),
     619           0 :                                           kidBStart), containerSize);
     620           0 :   ReflowOutput desiredSize(aWM);
     621           0 :   desiredSize.SetSize(aWM, GetLogicalSize(aWM));
     622             : 
     623           0 :   nsRect overflow(nsPoint(0,0), GetSize());
     624           0 :   overflow.Inflate(GetBorderOverflow());
     625           0 :   desiredSize.mOverflowAreas.SetAllTo(overflow);
     626           0 :   ConsiderChildOverflow(desiredSize.mOverflowAreas, firstKid);
     627           0 :   FinishAndStoreOverflow(&desiredSize);
     628           0 :   if (kidBStart != kidRect.BStart(aWM)) {
     629             :     // Make sure any child views are correctly positioned. We know the inner table
     630             :     // cell won't have a view
     631           0 :     nsContainerFrame::PositionChildViews(firstKid);
     632             : 
     633             :     // Invalidate new overflow rect
     634           0 :     firstKid->InvalidateFrameSubtree();
     635             :   }
     636           0 :   if (HasView()) {
     637           0 :     nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this,
     638             :                                                GetView(),
     639           0 :                                                desiredSize.VisualOverflow(), 0);
     640             :   }
     641           0 : }
     642             : 
     643             : bool
     644           0 : nsTableCellFrame::ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas)
     645             : {
     646           0 :   nsRect bounds(nsPoint(0,0), GetSize());
     647           0 :   bounds.Inflate(GetBorderOverflow());
     648             : 
     649           0 :   aOverflowAreas.UnionAllWith(bounds);
     650           0 :   return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
     651             : }
     652             : 
     653             : // Per CSS 2.1, we map 'sub', 'super', 'text-top', 'text-bottom',
     654             : // length, percentage, and calc() values to 'baseline'.
     655             : uint8_t
     656           0 : nsTableCellFrame::GetVerticalAlign() const
     657             : {
     658           0 :   const nsStyleCoord& verticalAlign = StyleDisplay()->mVerticalAlign;
     659           0 :   if (verticalAlign.GetUnit() == eStyleUnit_Enumerated) {
     660           0 :     uint8_t value = verticalAlign.GetIntValue();
     661           0 :     if (value == NS_STYLE_VERTICAL_ALIGN_TOP ||
     662           0 :         value == NS_STYLE_VERTICAL_ALIGN_MIDDLE ||
     663             :         value == NS_STYLE_VERTICAL_ALIGN_BOTTOM) {
     664           0 :       return value;
     665             :     }
     666             :   }
     667           0 :   return NS_STYLE_VERTICAL_ALIGN_BASELINE;
     668             : }
     669             : 
     670             : bool
     671           0 : nsTableCellFrame::CellHasVisibleContent(nscoord       height,
     672             :                                         nsTableFrame* tableFrame,
     673             :                                         nsIFrame*     kidFrame)
     674             : {
     675             :   // see  http://www.w3.org/TR/CSS21/tables.html#empty-cells
     676           0 :   if (height > 0)
     677           0 :     return true;
     678           0 :   if (tableFrame->IsBorderCollapse())
     679           0 :     return true;
     680           0 :   for (nsIFrame* innerFrame : kidFrame->PrincipalChildList()) {
     681           0 :     LayoutFrameType frameType = innerFrame->Type();
     682           0 :     if (LayoutFrameType::Text == frameType) {
     683           0 :       nsTextFrame* textFrame = static_cast<nsTextFrame*>(innerFrame);
     684           0 :       if (textFrame->HasNoncollapsedCharacters())
     685           0 :         return true;
     686           0 :     } else if (LayoutFrameType::Placeholder != frameType) {
     687           0 :       return true;
     688             :     }
     689             :     else {
     690           0 :       nsIFrame *floatFrame = nsLayoutUtils::GetFloatFromPlaceholder(innerFrame);
     691           0 :       if (floatFrame)
     692           0 :         return true;
     693             :     }
     694             :   }
     695           0 :   return false;
     696             : }
     697             : 
     698             : nscoord
     699           0 : nsTableCellFrame::GetCellBaseline() const
     700             : {
     701             :   // Ignore the position of the inner frame relative to the cell frame
     702             :   // since we want the position as though the inner were top-aligned.
     703           0 :   nsIFrame *inner = mFrames.FirstChild();
     704           0 :   nscoord borderPadding = GetUsedBorderAndPadding().top;
     705             :   nscoord result;
     706           0 :   if (nsLayoutUtils::GetFirstLineBaseline(GetWritingMode(), inner, &result))
     707           0 :     return result + borderPadding;
     708           0 :   return inner->GetContentRectRelativeToSelf().YMost() +
     709           0 :          borderPadding;
     710             : }
     711             : 
     712             : int32_t
     713           0 : nsTableCellFrame::GetRowSpan()
     714             : {
     715           0 :   int32_t rowSpan=1;
     716             : 
     717             :   // Don't look at the content's rowspan if we're a pseudo cell
     718           0 :   if (!StyleContext()->GetPseudo()) {
     719           0 :     dom::Element* elem = mContent->AsElement();
     720           0 :     const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::rowspan);
     721             :     // Note that we don't need to check the tag name, because only table cells
     722             :     // (including MathML <mtd>) and table headers parse the "rowspan" attribute
     723             :     // into an integer.
     724           0 :     if (attr && attr->Type() == nsAttrValue::eInteger) {
     725           0 :        rowSpan = attr->GetIntegerValue();
     726             :     }
     727             :   }
     728           0 :   return rowSpan;
     729             : }
     730             : 
     731             : int32_t
     732           0 : nsTableCellFrame::GetColSpan()
     733             : {
     734           0 :   int32_t colSpan=1;
     735             : 
     736             :   // Don't look at the content's colspan if we're a pseudo cell
     737           0 :   if (!StyleContext()->GetPseudo()) {
     738           0 :     dom::Element* elem = mContent->AsElement();
     739           0 :     const nsAttrValue* attr = elem->GetParsedAttr(
     740           0 :       MOZ_UNLIKELY(elem->IsMathMLElement()) ? nsGkAtoms::columnspan_
     741           0 :                                             : nsGkAtoms::colspan);
     742             :     // Note that we don't need to check the tag name, because only table cells
     743             :     // (including MathML <mtd>) and table headers parse the "colspan" attribute
     744             :     // into an integer.
     745           0 :     if (attr && attr->Type() == nsAttrValue::eInteger) {
     746           0 :        colSpan = attr->GetIntegerValue();
     747             :     }
     748             :   }
     749           0 :   return colSpan;
     750             : }
     751             : 
     752             : /* virtual */ nscoord
     753           0 : nsTableCellFrame::GetMinISize(gfxContext *aRenderingContext)
     754             : {
     755           0 :   nscoord result = 0;
     756           0 :   DISPLAY_MIN_WIDTH(this, result);
     757             : 
     758           0 :   nsIFrame *inner = mFrames.FirstChild();
     759           0 :   result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner,
     760             :                                                     nsLayoutUtils::MIN_ISIZE);
     761           0 :   return result;
     762             : }
     763             : 
     764             : /* virtual */ nscoord
     765           0 : nsTableCellFrame::GetPrefISize(gfxContext *aRenderingContext)
     766             : {
     767           0 :   nscoord result = 0;
     768           0 :   DISPLAY_PREF_WIDTH(this, result);
     769             : 
     770           0 :   nsIFrame *inner = mFrames.FirstChild();
     771           0 :   result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner,
     772             :                                                 nsLayoutUtils::PREF_ISIZE);
     773           0 :   return result;
     774             : }
     775             : 
     776             : /* virtual */ nsIFrame::IntrinsicISizeOffsetData
     777           0 : nsTableCellFrame::IntrinsicISizeOffsets()
     778             : {
     779           0 :   IntrinsicISizeOffsetData result = nsContainerFrame::IntrinsicISizeOffsets();
     780             : 
     781           0 :   result.hMargin = 0;
     782           0 :   result.hPctMargin = 0;
     783             : 
     784           0 :   WritingMode wm = GetWritingMode();
     785           0 :   result.hBorder = GetBorderWidth(wm).IStartEnd(wm);
     786             : 
     787           0 :   return result;
     788             : }
     789             : 
     790             : #ifdef DEBUG
     791             : #define PROBABLY_TOO_LARGE 1000000
     792             : static
     793           0 : void DebugCheckChildSize(nsIFrame*            aChild,
     794             :                          ReflowOutput& aMet)
     795             : {
     796           0 :   WritingMode wm = aMet.GetWritingMode();
     797           0 :   if ((aMet.ISize(wm) < 0) || (aMet.ISize(wm) > PROBABLY_TOO_LARGE)) {
     798           0 :     printf("WARNING: cell content %p has large inline size %d \n",
     799           0 :            static_cast<void*>(aChild), int32_t(aMet.ISize(wm)));
     800             :   }
     801           0 : }
     802             : #endif
     803             : 
     804             : // the computed bsize for the cell, which descendants use for percent bsize calculations
     805             : // it is the bsize (minus border, padding) of the cell's first in flow during its final
     806             : // reflow without an unconstrained bsize.
     807             : static nscoord
     808           0 : CalcUnpaginatedBSize(nsTableCellFrame& aCellFrame,
     809             :                      nsTableFrame&     aTableFrame,
     810             :                      nscoord           aBlockDirBorderPadding)
     811             : {
     812             :   const nsTableCellFrame* firstCellInFlow =
     813           0 :     static_cast<nsTableCellFrame*>(aCellFrame.FirstInFlow());
     814             :   nsTableFrame* firstTableInFlow  =
     815           0 :     static_cast<nsTableFrame*>(aTableFrame.FirstInFlow());
     816             :   nsTableRowFrame* row =
     817           0 :     static_cast<nsTableRowFrame*>(firstCellInFlow->GetParent());
     818             :   nsTableRowGroupFrame* firstRGInFlow =
     819           0 :     static_cast<nsTableRowGroupFrame*>(row->GetParent());
     820             : 
     821             :   int32_t rowIndex;
     822           0 :   firstCellInFlow->GetRowIndex(rowIndex);
     823           0 :   int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(*firstCellInFlow);
     824             : 
     825           0 :   nscoord computedBSize = firstTableInFlow->GetRowSpacing(rowIndex,
     826           0 :                                                           rowIndex + rowSpan - 1);
     827           0 :   computedBSize -= aBlockDirBorderPadding;
     828             :   int32_t rowX;
     829           0 :   for (row = firstRGInFlow->GetFirstRow(), rowX = 0; row; row = row->GetNextRow(), rowX++) {
     830           0 :     if (rowX > rowIndex + rowSpan - 1) {
     831           0 :       break;
     832             :     }
     833           0 :     else if (rowX >= rowIndex) {
     834           0 :       computedBSize += row->GetUnpaginatedBSize();
     835             :     }
     836             :   }
     837           0 :   return computedBSize;
     838             : }
     839             : 
     840             : void
     841           0 : nsTableCellFrame::Reflow(nsPresContext*           aPresContext,
     842             :                          ReflowOutput&     aDesiredSize,
     843             :                          const ReflowInput& aReflowInput,
     844             :                          nsReflowStatus&          aStatus)
     845             : {
     846           0 :   MarkInReflow();
     847           0 :   DO_GLOBAL_REFLOW_COUNT("nsTableCellFrame");
     848           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     849             : 
     850           0 :   if (aReflowInput.mFlags.mSpecialBSizeReflow) {
     851           0 :     FirstInFlow()->AddStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW);
     852             :   }
     853             : 
     854             :   // see if a special bsize reflow needs to occur due to having a pct height
     855           0 :   nsTableFrame::CheckRequestSpecialBSizeReflow(aReflowInput);
     856             : 
     857           0 :   aStatus.Reset();
     858           0 :   WritingMode wm = aReflowInput.GetWritingMode();
     859             :   LogicalSize availSize(wm, aReflowInput.AvailableISize(),
     860           0 :                             aReflowInput.AvailableBSize());
     861             : 
     862           0 :   LogicalMargin borderPadding = aReflowInput.ComputedLogicalPadding();
     863           0 :   LogicalMargin border = GetBorderWidth(wm);
     864           0 :   borderPadding += border;
     865             : 
     866             :   // reduce available space by insets, if we're in a constrained situation
     867           0 :   availSize.ISize(wm) -= borderPadding.IStartEnd(wm);
     868           0 :   if (NS_UNCONSTRAINEDSIZE != availSize.BSize(wm)) {
     869           0 :     availSize.BSize(wm) -= borderPadding.BStartEnd(wm);
     870             :   }
     871             : 
     872             :   // Try to reflow the child into the available space. It might not
     873             :   // fit or might need continuing.
     874           0 :   if (availSize.BSize(wm) < 0) {
     875           0 :     availSize.BSize(wm) = 1;
     876             :   }
     877             : 
     878           0 :   ReflowOutput kidSize(wm, aDesiredSize.mFlags);
     879           0 :   kidSize.ClearSize();
     880           0 :   SetPriorAvailISize(aReflowInput.AvailableISize());
     881           0 :   nsIFrame* firstKid = mFrames.FirstChild();
     882           0 :   NS_ASSERTION(firstKid, "Frame construction error, a table cell always has an inner cell frame");
     883           0 :   nsTableFrame* tableFrame = GetTableFrame();
     884             : 
     885           0 :   if (aReflowInput.mFlags.mSpecialBSizeReflow) {
     886             :     const_cast<ReflowInput&>(aReflowInput).
     887           0 :       SetComputedBSize(BSize(wm) - borderPadding.BStartEnd(wm));
     888           0 :     DISPLAY_REFLOW_CHANGE();
     889             :   }
     890           0 :   else if (aPresContext->IsPaginated()) {
     891             :     nscoord computedUnpaginatedBSize =
     892           0 :       CalcUnpaginatedBSize((nsTableCellFrame&)*this,
     893           0 :                            *tableFrame, borderPadding.BStartEnd(wm));
     894           0 :     if (computedUnpaginatedBSize > 0) {
     895           0 :       const_cast<ReflowInput&>(aReflowInput).SetComputedBSize(computedUnpaginatedBSize);
     896           0 :       DISPLAY_REFLOW_CHANGE();
     897             :     }
     898             :   }
     899             :   else {
     900           0 :     SetHasPctOverBSize(false);
     901             :   }
     902             : 
     903           0 :   WritingMode kidWM = firstKid->GetWritingMode();
     904             :   ReflowInput kidReflowInput(aPresContext, aReflowInput, firstKid,
     905           0 :                                    availSize.ConvertTo(kidWM, wm));
     906             : 
     907             :   // Don't be a percent height observer if we're in the middle of
     908             :   // special-bsize reflow, in case we get an accidental NotifyPercentBSize()
     909             :   // call (which we shouldn't honor during special-bsize reflow)
     910           0 :   if (!aReflowInput.mFlags.mSpecialBSizeReflow) {
     911             :     // mPercentBSizeObserver is for children of cells in quirks mode,
     912             :     // but only those than are tables in standards mode.  NeedsToObserve
     913             :     // will determine how far this is propagated to descendants.
     914           0 :     kidReflowInput.mPercentBSizeObserver = this;
     915             :   }
     916             :   // Don't propagate special bsize reflow state to our kids
     917           0 :   kidReflowInput.mFlags.mSpecialBSizeReflow = false;
     918             : 
     919           0 :   if (aReflowInput.mFlags.mSpecialBSizeReflow ||
     920           0 :       FirstInFlow()->HasAnyStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) {
     921             :     // We need to force the kid to have mBResize set if we've had a
     922             :     // special reflow in the past, since the non-special reflow needs to
     923             :     // resize back to what it was without the special bsize reflow.
     924           0 :     kidReflowInput.SetBResize(true);
     925             :   }
     926             : 
     927             :   nsSize containerSize =
     928           0 :     aReflowInput.ComputedSizeAsContainerIfConstrained();
     929             : 
     930           0 :   LogicalPoint kidOrigin(wm, borderPadding.IStart(wm),
     931           0 :                          borderPadding.BStart(wm));
     932           0 :   nsRect origRect = firstKid->GetRect();
     933           0 :   nsRect origVisualOverflow = firstKid->GetVisualOverflowRect();
     934           0 :   bool firstReflow = firstKid->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
     935             : 
     936           0 :   ReflowChild(firstKid, aPresContext, kidSize, kidReflowInput,
     937           0 :               wm, kidOrigin, containerSize, 0, aStatus);
     938           0 :   if (aStatus.IsOverflowIncomplete()) {
     939             :     // Don't pass OVERFLOW_INCOMPLETE through tables until they can actually handle it
     940             :     //XXX should paginate overflow as overflow, but not in this patch (bug 379349)
     941           0 :     aStatus.SetIncomplete();
     942           0 :     printf("Set table cell incomplete %p\n", static_cast<void*>(this));
     943             :   }
     944             : 
     945             :   // XXXbz is this invalidate actually needed, really?
     946           0 :   if (HasAnyStateBits(NS_FRAME_IS_DIRTY)) {
     947           0 :     InvalidateFrameSubtree();
     948             :   }
     949             : 
     950             : #ifdef DEBUG
     951           0 :   DebugCheckChildSize(firstKid, kidSize);
     952             : #endif
     953             : 
     954             :   // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode
     955             :   // see testcase "emptyCells.html"
     956           0 :   nsIFrame* prevInFlow = GetPrevInFlow();
     957             :   bool isEmpty;
     958           0 :   if (prevInFlow) {
     959           0 :     isEmpty = static_cast<nsTableCellFrame*>(prevInFlow)->GetContentEmpty();
     960             :   } else {
     961           0 :     isEmpty = !CellHasVisibleContent(kidSize.Height(), tableFrame, firstKid);
     962             :   }
     963           0 :   SetContentEmpty(isEmpty);
     964             : 
     965             :   // Place the child
     966             :   FinishReflowChild(firstKid, aPresContext, kidSize, &kidReflowInput,
     967           0 :                     wm, kidOrigin, containerSize, 0);
     968             : 
     969           0 :   if (tableFrame->IsBorderCollapse()) {
     970           0 :     nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow,
     971           0 :                                        firstReflow);
     972             :   }
     973             :   // first, compute the bsize which can be set w/o being restricted by
     974             :   // available bsize
     975           0 :   LogicalSize cellSize(wm);
     976           0 :   cellSize.BSize(wm) = kidSize.BSize(wm);
     977             : 
     978           0 :   if (NS_UNCONSTRAINEDSIZE != cellSize.BSize(wm)) {
     979           0 :     cellSize.BSize(wm) += borderPadding.BStartEnd(wm);
     980             :   }
     981             : 
     982             :   // next determine the cell's isize
     983           0 :   cellSize.ISize(wm) = kidSize.ISize(wm);      // at this point, we've factored in the cell's style attributes
     984             : 
     985             :   // factor in border and padding
     986           0 :   if (NS_UNCONSTRAINEDSIZE != cellSize.ISize(wm)) {
     987           0 :     cellSize.ISize(wm) += borderPadding.IStartEnd(wm);
     988             :   }
     989             : 
     990             :   // set the cell's desired size and max element size
     991           0 :   aDesiredSize.SetSize(wm, cellSize);
     992             : 
     993             :   // the overflow area will be computed when BlockDirAlignChild() gets called
     994             : 
     995           0 :   if (aReflowInput.mFlags.mSpecialBSizeReflow) {
     996           0 :     if (aDesiredSize.BSize(wm) > BSize(wm)) {
     997             :       // set a bit indicating that the pct bsize contents exceeded
     998             :       // the height that they could honor in the pass 2 reflow
     999           0 :       SetHasPctOverBSize(true);
    1000             :     }
    1001           0 :     if (NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) {
    1002           0 :       aDesiredSize.BSize(wm) = BSize(wm);
    1003             :     }
    1004             :   }
    1005             : 
    1006             :   // If our parent is in initial reflow, it'll handle invalidating our
    1007             :   // entire overflow rect.
    1008           0 :   if (!GetParent()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW) &&
    1009           0 :       nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
    1010           0 :     InvalidateFrame();
    1011             :   }
    1012             : 
    1013             :   // remember the desired size for this reflow
    1014           0 :   SetDesiredSize(aDesiredSize);
    1015             : 
    1016             :   // Any absolutely-positioned children will get reflowed in
    1017             :   // nsFrame::FixupPositionedTableParts in another pass, so propagate our
    1018             :   // dirtiness to them before our parent clears our dirty bits.
    1019           0 :   PushDirtyBitToAbsoluteFrames();
    1020             : 
    1021           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
    1022           0 : }
    1023             : 
    1024             : /* ----- global methods ----- */
    1025             : 
    1026           0 : NS_QUERYFRAME_HEAD(nsTableCellFrame)
    1027           0 :   NS_QUERYFRAME_ENTRY(nsTableCellFrame)
    1028           0 :   NS_QUERYFRAME_ENTRY(nsITableCellLayout)
    1029           0 :   NS_QUERYFRAME_ENTRY(nsIPercentBSizeObserver)
    1030           0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
    1031             : 
    1032             : #ifdef ACCESSIBILITY
    1033             : a11y::AccType
    1034           0 : nsTableCellFrame::AccessibleType()
    1035             : {
    1036           0 :   return a11y::eHTMLTableCellType;
    1037             : }
    1038             : #endif
    1039             : 
    1040             : /* This is primarily for editor access via nsITableLayout */
    1041             : NS_IMETHODIMP
    1042           0 : nsTableCellFrame::GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)
    1043             : {
    1044           0 :   nsresult res = GetRowIndex(aRowIndex);
    1045           0 :   if (NS_FAILED(res))
    1046             :   {
    1047           0 :     aColIndex = 0;
    1048           0 :     return res;
    1049             :   }
    1050           0 :   aColIndex = mColIndex;
    1051           0 :   return  NS_OK;
    1052             : }
    1053             : 
    1054             : nsTableCellFrame*
    1055           0 : NS_NewTableCellFrame(nsIPresShell*   aPresShell,
    1056             :                      nsStyleContext* aContext,
    1057             :                      nsTableFrame* aTableFrame)
    1058             : {
    1059           0 :   if (aTableFrame->IsBorderCollapse())
    1060           0 :     return new (aPresShell) nsBCTableCellFrame(aContext, aTableFrame);
    1061             :   else
    1062           0 :     return new (aPresShell) nsTableCellFrame(aContext, aTableFrame);
    1063             : }
    1064             : 
    1065           0 : NS_IMPL_FRAMEARENA_HELPERS(nsBCTableCellFrame)
    1066             : 
    1067             : LogicalMargin
    1068           0 : nsTableCellFrame::GetBorderWidth(WritingMode aWM) const
    1069             : {
    1070           0 :   return LogicalMargin(aWM, StyleBorder()->GetComputedBorder());
    1071             : }
    1072             : 
    1073             : void
    1074           0 : nsTableCellFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
    1075             : {
    1076           0 :   nsIFrame* kid = mFrames.FirstChild();
    1077           0 :   MOZ_ASSERT(kid && !kid->GetNextSibling(),
    1078             :              "Table cells should have just one child");
    1079           0 :   aResult.AppendElement(OwnedAnonBox(kid));
    1080           0 : }
    1081             : 
    1082             : #ifdef DEBUG_FRAME_DUMP
    1083             : nsresult
    1084           0 : nsTableCellFrame::GetFrameName(nsAString& aResult) const
    1085             : {
    1086           0 :   return MakeFrameName(NS_LITERAL_STRING("TableCell"), aResult);
    1087             : }
    1088             : #endif
    1089             : 
    1090             : // nsBCTableCellFrame
    1091             : 
    1092           0 : nsBCTableCellFrame::nsBCTableCellFrame(nsStyleContext* aContext,
    1093           0 :                                        nsTableFrame* aTableFrame)
    1094           0 :   : nsTableCellFrame(aContext, aTableFrame, kClassID)
    1095             : {
    1096           0 :   mBStartBorder = mIEndBorder = mBEndBorder = mIStartBorder = 0;
    1097           0 : }
    1098             : 
    1099           0 : nsBCTableCellFrame::~nsBCTableCellFrame()
    1100             : {
    1101           0 : }
    1102             : 
    1103             : /* virtual */ nsMargin
    1104           0 : nsBCTableCellFrame::GetUsedBorder() const
    1105             : {
    1106           0 :   WritingMode wm = GetWritingMode();
    1107           0 :   return GetBorderWidth(wm).GetPhysicalMargin(wm);
    1108             : }
    1109             : 
    1110             : /* virtual */ bool
    1111           0 : nsBCTableCellFrame::GetBorderRadii(const nsSize& aFrameSize,
    1112             :                                    const nsSize& aBorderArea,
    1113             :                                    Sides aSkipSides,
    1114             :                                    nscoord aRadii[8]) const
    1115             : {
    1116           0 :   NS_FOR_CSS_HALF_CORNERS(corner) {
    1117           0 :     aRadii[corner] = 0;
    1118             :   }
    1119           0 :   return false;
    1120             : }
    1121             : 
    1122             : #ifdef DEBUG_FRAME_DUMP
    1123             : nsresult
    1124           0 : nsBCTableCellFrame::GetFrameName(nsAString& aResult) const
    1125             : {
    1126           0 :   return MakeFrameName(NS_LITERAL_STRING("BCTableCell"), aResult);
    1127             : }
    1128             : #endif
    1129             : 
    1130             : LogicalMargin
    1131           0 : nsBCTableCellFrame::GetBorderWidth(WritingMode aWM) const
    1132             : {
    1133           0 :   int32_t pixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
    1134             :   return LogicalMargin(aWM,
    1135           0 :                        BC_BORDER_END_HALF_COORD(pixelsToTwips, mBStartBorder),
    1136           0 :                        BC_BORDER_START_HALF_COORD(pixelsToTwips, mIEndBorder),
    1137           0 :                        BC_BORDER_START_HALF_COORD(pixelsToTwips, mBEndBorder),
    1138           0 :                        BC_BORDER_END_HALF_COORD(pixelsToTwips, mIStartBorder));
    1139             : }
    1140             : 
    1141             : BCPixelSize
    1142           0 : nsBCTableCellFrame::GetBorderWidth(LogicalSide aSide) const
    1143             : {
    1144           0 :   switch(aSide) {
    1145             :   case eLogicalSideBStart:
    1146           0 :     return BC_BORDER_END_HALF(mBStartBorder);
    1147             :   case eLogicalSideIEnd:
    1148           0 :     return BC_BORDER_START_HALF(mIEndBorder);
    1149             :   case eLogicalSideBEnd:
    1150           0 :     return BC_BORDER_START_HALF(mBEndBorder);
    1151             :   default:
    1152           0 :     return BC_BORDER_END_HALF(mIStartBorder);
    1153             :   }
    1154             : }
    1155             : 
    1156             : void
    1157           0 : nsBCTableCellFrame::SetBorderWidth(LogicalSide aSide, BCPixelSize aValue)
    1158             : {
    1159           0 :   switch(aSide) {
    1160             :   case eLogicalSideBStart:
    1161           0 :     mBStartBorder = aValue;
    1162           0 :     break;
    1163             :   case eLogicalSideIEnd:
    1164           0 :     mIEndBorder = aValue;
    1165           0 :     break;
    1166             :   case eLogicalSideBEnd:
    1167           0 :     mBEndBorder = aValue;
    1168           0 :     break;
    1169             :   default:
    1170           0 :     mIStartBorder = aValue;
    1171             :   }
    1172           0 : }
    1173             : 
    1174             : /* virtual */ nsMargin
    1175           0 : nsBCTableCellFrame::GetBorderOverflow()
    1176             : {
    1177           0 :   WritingMode wm = GetWritingMode();
    1178           0 :   int32_t p2t = nsPresContext::AppUnitsPerCSSPixel();
    1179             :   LogicalMargin halfBorder(wm,
    1180           0 :                            BC_BORDER_START_HALF_COORD(p2t, mBStartBorder),
    1181           0 :                            BC_BORDER_END_HALF_COORD(p2t, mIEndBorder),
    1182           0 :                            BC_BORDER_END_HALF_COORD(p2t, mBEndBorder),
    1183           0 :                            BC_BORDER_START_HALF_COORD(p2t, mIStartBorder));
    1184           0 :   return halfBorder.GetPhysicalMargin(wm);
    1185             : }
    1186             : 
    1187             : DrawResult
    1188           0 : nsBCTableCellFrame::PaintBackground(gfxContext&          aRenderingContext,
    1189             :                                     const nsRect&        aDirtyRect,
    1190             :                                     nsPoint              aPt,
    1191             :                                     uint32_t             aFlags)
    1192             : {
    1193             :   // make border-width reflect the half of the border-collapse
    1194             :   // assigned border that's inside the cell
    1195           0 :   WritingMode wm = GetWritingMode();
    1196           0 :   nsMargin borderWidth = GetBorderWidth(wm).GetPhysicalMargin(wm);
    1197             : 
    1198           0 :   nsStyleBorder myBorder(*StyleBorder());
    1199             : 
    1200           0 :   NS_FOR_CSS_SIDES(side) {
    1201           0 :     myBorder.SetBorderWidth(side, borderWidth.Side(side));
    1202             :   }
    1203             : 
    1204             :   // bypassing nsCSSRendering::PaintBackground is safe because this kind
    1205             :   // of frame cannot be used for the root element
    1206           0 :   nsRect rect(aPt, GetSize());
    1207             :   nsCSSRendering::PaintBGParams params =
    1208           0 :     nsCSSRendering::PaintBGParams::ForAllLayers(*PresContext(),
    1209             :                                                 aDirtyRect,
    1210             :                                                 rect, this,
    1211           0 :                                                 aFlags);
    1212           0 :   return nsCSSRendering::PaintStyleImageLayerWithSC(params, aRenderingContext, StyleContext(),
    1213           0 :                                                     myBorder);
    1214             : }

Generated by: LCOV version 1.13