LCOV - code coverage report
Current view: top level - layout/tables - nsTableWrapperFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 515 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 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 "nsTableWrapperFrame.h"
       7             : 
       8             : #include "nsFrameManager.h"
       9             : #include "nsTableFrame.h"
      10             : #include "nsTableCellFrame.h"
      11             : #include "nsStyleContext.h"
      12             : #include "nsStyleConsts.h"
      13             : #include "nsPresContext.h"
      14             : #include "nsCSSRendering.h"
      15             : #include "nsIContent.h"
      16             : #include "prinrval.h"
      17             : #include "nsGkAtoms.h"
      18             : #include "nsHTMLParts.h"
      19             : #include "nsIPresShell.h"
      20             : #include "nsIServiceManager.h"
      21             : #include "nsIDOMNode.h"
      22             : #include "nsDisplayList.h"
      23             : #include "nsLayoutUtils.h"
      24             : #include "nsIFrameInlines.h"
      25             : #include <algorithm>
      26             : 
      27             : using namespace mozilla;
      28             : using namespace mozilla::layout;
      29             : 
      30             : #define NO_SIDE 100
      31             : 
      32             : /* virtual */ nscoord
      33           0 : nsTableWrapperFrame::GetLogicalBaseline(WritingMode aWritingMode) const
      34             : {
      35           0 :   nsIFrame* kid = mFrames.FirstChild();
      36           0 :   if (!kid) {
      37           0 :     NS_NOTREACHED("no inner table");
      38           0 :     return nsContainerFrame::GetLogicalBaseline(aWritingMode);
      39             :   }
      40             : 
      41           0 :   return kid->GetLogicalBaseline(aWritingMode) +
      42           0 :          kid->BStart(aWritingMode, mRect.Size());
      43             : }
      44             : 
      45           0 : nsTableWrapperFrame::nsTableWrapperFrame(nsStyleContext* aContext, ClassID aID)
      46           0 :   : nsContainerFrame(aContext, aID)
      47             : {
      48           0 : }
      49             : 
      50           0 : nsTableWrapperFrame::~nsTableWrapperFrame()
      51             : {
      52           0 : }
      53             : 
      54           0 : NS_QUERYFRAME_HEAD(nsTableWrapperFrame)
      55           0 :   NS_QUERYFRAME_ENTRY(nsTableWrapperFrame)
      56           0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      57             : 
      58             : #ifdef ACCESSIBILITY
      59             : a11y::AccType
      60           0 : nsTableWrapperFrame::AccessibleType()
      61             : {
      62           0 :   return a11y::eHTMLTableType;
      63             : }
      64             : #endif
      65             : 
      66             : void
      67           0 : nsTableWrapperFrame::DestroyFrom(nsIFrame* aDestructRoot)
      68             : {
      69           0 :   DestroyAbsoluteFrames(aDestructRoot);
      70           0 :   mCaptionFrames.DestroyFramesFrom(aDestructRoot);
      71           0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
      72           0 : }
      73             : 
      74             : const nsFrameList&
      75           0 : nsTableWrapperFrame::GetChildList(ChildListID aListID) const
      76             : {
      77           0 :   if (aListID == kCaptionList) {
      78           0 :     return mCaptionFrames;
      79             :   }
      80             : 
      81           0 :   return nsContainerFrame::GetChildList(aListID);
      82             : }
      83             : 
      84             : void
      85           0 : nsTableWrapperFrame::GetChildLists(nsTArray<ChildList>* aLists) const
      86             : {
      87           0 :   nsContainerFrame::GetChildLists(aLists);
      88           0 :   mCaptionFrames.AppendIfNonempty(aLists, kCaptionList);
      89           0 : }
      90             : 
      91             : void
      92           0 : nsTableWrapperFrame::SetInitialChildList(ChildListID     aListID,
      93             :                                          nsFrameList&    aChildList)
      94             : {
      95           0 :   if (kCaptionList == aListID) {
      96             :     // the frame constructor already checked for table-caption display type
      97           0 :     MOZ_ASSERT(mCaptionFrames.IsEmpty(),
      98             :                "already have child frames in CaptionList");
      99           0 :     mCaptionFrames.SetFrames(aChildList);
     100             :   } else {
     101           0 :     MOZ_ASSERT(kPrincipalList != aListID ||
     102             :                (aChildList.FirstChild() &&
     103             :                 aChildList.FirstChild() == aChildList.LastChild() &&
     104             :                 aChildList.FirstChild()->IsTableFrame()),
     105             :                "expected a single table frame in principal child list");
     106           0 :     nsContainerFrame::SetInitialChildList(aListID, aChildList);
     107             :   }
     108           0 : }
     109             : 
     110             : void
     111           0 : nsTableWrapperFrame::AppendFrames(ChildListID     aListID,
     112             :                                   nsFrameList&    aFrameList)
     113             : {
     114             :   // We only have two child frames: the inner table and a caption frame.
     115             :   // The inner frame is provided when we're initialized, and it cannot change
     116           0 :   MOZ_ASSERT(kCaptionList == aListID, "unexpected child list");
     117           0 :   MOZ_ASSERT(aFrameList.IsEmpty() ||
     118             :              aFrameList.FirstChild()->IsTableCaption(),
     119             :              "appending non-caption frame to captionList");
     120           0 :   mCaptionFrames.AppendFrames(this, aFrameList);
     121             : 
     122             :   // Reflow the new caption frame. It's already marked dirty, so
     123             :   // just tell the pres shell.
     124           0 :   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     125           0 :                                                NS_FRAME_HAS_DIRTY_CHILDREN);
     126           0 : }
     127             : 
     128             : void
     129           0 : nsTableWrapperFrame::InsertFrames(ChildListID     aListID,
     130             :                                   nsIFrame*       aPrevFrame,
     131             :                                   nsFrameList&    aFrameList)
     132             : {
     133           0 :   MOZ_ASSERT(kCaptionList == aListID, "unexpected child list");
     134           0 :   MOZ_ASSERT(aFrameList.IsEmpty() ||
     135             :              aFrameList.FirstChild()->IsTableCaption(),
     136             :              "inserting non-caption frame into captionList");
     137           0 :   MOZ_ASSERT(!aPrevFrame || aPrevFrame->GetParent() == this,
     138             :              "inserting after sibling frame with different parent");
     139           0 :   mCaptionFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
     140             : 
     141             :   // Reflow the new caption frame. It's already marked dirty, so
     142             :   // just tell the pres shell.
     143           0 :   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     144           0 :                                                NS_FRAME_HAS_DIRTY_CHILDREN);
     145           0 : }
     146             : 
     147             : void
     148           0 : nsTableWrapperFrame::RemoveFrame(ChildListID  aListID,
     149             :                                  nsIFrame*    aOldFrame)
     150             : {
     151             :   // We only have two child frames: the inner table and one caption frame.
     152             :   // The inner frame can't be removed so this should be the caption
     153           0 :   NS_PRECONDITION(kCaptionList == aListID, "can't remove inner frame");
     154             : 
     155           0 :   if (HasSideCaption()) {
     156             :     // The old caption isize had an effect on the inner table isize, so
     157             :     // we're going to need to reflow it. Mark it dirty
     158           0 :     InnerTableFrame()->AddStateBits(NS_FRAME_IS_DIRTY);
     159             :   }
     160             : 
     161             :   // Remove the frame and destroy it
     162           0 :   mCaptionFrames.DestroyFrame(aOldFrame);
     163             : 
     164           0 :   PresContext()->PresShell()->
     165           0 :     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     166           0 :                      NS_FRAME_HAS_DIRTY_CHILDREN); // also means child removed
     167           0 : }
     168             : 
     169             : void
     170           0 : nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     171             :                                       const nsRect&           aDirtyRect,
     172             :                                       const nsDisplayListSet& aLists)
     173             : {
     174             :   // No border, background or outline are painted because they all belong
     175             :   // to the inner table.
     176             : 
     177             :   // If there's no caption, take a short cut to avoid having to create
     178             :   // the special display list set and then sort it.
     179           0 :   if (mCaptionFrames.IsEmpty()) {
     180           0 :     BuildDisplayListForInnerTable(aBuilder, aDirtyRect, aLists);
     181           0 :     return;
     182             :   }
     183             : 
     184           0 :   nsDisplayListCollection set;
     185           0 :   BuildDisplayListForInnerTable(aBuilder, aDirtyRect, set);
     186             : 
     187           0 :   nsDisplayListSet captionSet(set, set.BlockBorderBackgrounds());
     188           0 :   BuildDisplayListForChild(aBuilder, mCaptionFrames.FirstChild(),
     189           0 :                            aDirtyRect, captionSet);
     190             : 
     191             :   // Now we have to sort everything by content order, since the caption
     192             :   // may be somewhere inside the table
     193           0 :   set.BlockBorderBackgrounds()->SortByContentOrder(GetContent());
     194           0 :   set.Floats()->SortByContentOrder(GetContent());
     195           0 :   set.Content()->SortByContentOrder(GetContent());
     196           0 :   set.PositionedDescendants()->SortByContentOrder(GetContent());
     197           0 :   set.Outlines()->SortByContentOrder(GetContent());
     198           0 :   set.MoveTo(aLists);
     199             : }
     200             : 
     201             : void
     202           0 : nsTableWrapperFrame::BuildDisplayListForInnerTable(nsDisplayListBuilder*   aBuilder,
     203             :                                                    const nsRect&           aDirtyRect,
     204             :                                                    const nsDisplayListSet& aLists)
     205             : {
     206             :   // Just paint the regular children, but the children's background is our
     207             :   // true background (there should only be one, the real table)
     208           0 :   nsIFrame* kid = mFrames.FirstChild();
     209             :   // The children should be in content order
     210           0 :   while (kid) {
     211           0 :     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
     212           0 :     kid = kid->GetNextSibling();
     213             :   }
     214           0 : }
     215             : 
     216             : nsStyleContext*
     217           0 : nsTableWrapperFrame::GetParentStyleContext(nsIFrame** aProviderFrame) const
     218             : {
     219             :   // The table wrapper frame and the (inner) table frame split the style
     220             :   // data by giving the table frame the style context associated with
     221             :   // the table content node and creating a style context for the wrapper
     222             :   // frame that is a *child* of the table frame's style context,
     223             :   // matching the ::-moz-table-wrapper pseudo-element. html.css has a
     224             :   // rule that causes that pseudo-element (and thus the wrapper table)
     225             :   // to inherit *some* style properties from the table frame.  The
     226             :   // children of the table inherit directly from the inner table, and
     227             :   // the table wrapper's style context is a leaf.
     228             : 
     229           0 :   return (*aProviderFrame = InnerTableFrame())->StyleContext();
     230             : }
     231             : 
     232             : // INCREMENTAL REFLOW HELPER FUNCTIONS
     233             : 
     234             : void
     235           0 : nsTableWrapperFrame::InitChildReflowInput(nsPresContext& aPresContext,
     236             :                                           const ReflowInput& aOuterRI,
     237             :                                           ReflowInput&   aReflowInput)
     238             : {
     239           0 :   nsMargin collapseBorder;
     240           0 :   nsMargin collapsePadding(0,0,0,0);
     241           0 :   nsMargin* pCollapseBorder  = nullptr;
     242           0 :   nsMargin* pCollapsePadding = nullptr;
     243           0 :   Maybe<LogicalSize> cbSize;
     244           0 :   if (aReflowInput.mFrame == InnerTableFrame()) {
     245           0 :     WritingMode wm = aReflowInput.GetWritingMode();
     246           0 :     if (InnerTableFrame()->IsBorderCollapse()) {
     247           0 :       LogicalMargin border = InnerTableFrame()->GetIncludedOuterBCBorder(wm);
     248           0 :       collapseBorder = border.GetPhysicalMargin(wm);
     249           0 :       pCollapseBorder = &collapseBorder;
     250           0 :       pCollapsePadding = &collapsePadding;
     251             :     }
     252             :     // Propagate our stored CB size if present, minus any margins.
     253           0 :     if (!HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
     254           0 :       LogicalSize* cb = GetProperty(GridItemCBSizeProperty());
     255           0 :       if (cb) {
     256           0 :         cbSize.emplace(*cb);
     257           0 :         *cbSize -= aReflowInput.ComputedLogicalMargin().Size(wm);
     258             :       }
     259             :     }
     260           0 :     if (!cbSize) {
     261             :       // For inner table frames, the containing block is the same as for
     262             :       // the outer table frame.
     263           0 :       cbSize.emplace(aOuterRI.mContainingBlockSize);
     264             :     }
     265             :   }
     266           0 :   aReflowInput.Init(&aPresContext, cbSize.ptrOr(nullptr), pCollapseBorder,
     267           0 :                     pCollapsePadding);
     268           0 : }
     269             : 
     270             : // get the margin and padding data. ReflowInput doesn't handle the
     271             : // case of auto margins
     272             : void
     273           0 : nsTableWrapperFrame::GetChildMargin(nsPresContext*           aPresContext,
     274             :                                     const ReflowInput& aOuterRI,
     275             :                                     nsIFrame*                aChildFrame,
     276             :                                     nscoord                  aAvailISize,
     277             :                                     LogicalMargin&           aMargin)
     278             : {
     279           0 :   NS_ASSERTION(!aChildFrame->IsTableCaption(),
     280             :                "didn't expect caption frame; writing-mode may be wrong!");
     281             : 
     282             :   // construct a reflow state to compute margin and padding. Auto margins
     283             :   // will not be computed at this time.
     284             : 
     285             :   // create and init the child reflow state
     286             :   // XXX We really shouldn't construct a reflow state to do this.
     287           0 :   WritingMode wm = aOuterRI.GetWritingMode();
     288           0 :   LogicalSize availSize(wm, aAvailISize, aOuterRI.AvailableSize(wm).BSize(wm));
     289             :   ReflowInput childRI(aPresContext, aOuterRI, aChildFrame, availSize,
     290           0 :                             nullptr, ReflowInput::CALLER_WILL_INIT);
     291           0 :   InitChildReflowInput(*aPresContext, aOuterRI, childRI);
     292             : 
     293           0 :   aMargin = childRI.ComputedLogicalMargin();
     294           0 : }
     295             : 
     296             : static nsSize
     297           0 : GetContainingBlockSize(const ReflowInput& aOuterRI)
     298             : {
     299           0 :   nsSize size(0,0);
     300           0 :   const ReflowInput* containRS = aOuterRI.mCBReflowInput;
     301             : 
     302           0 :   if (containRS) {
     303           0 :     size.width = containRS->ComputedWidth();
     304           0 :     if (NS_UNCONSTRAINEDSIZE == size.width) {
     305           0 :       size.width = 0;
     306             :     }
     307           0 :     size.height = containRS->ComputedHeight();
     308           0 :     if (NS_UNCONSTRAINEDSIZE == size.height) {
     309           0 :       size.height = 0;
     310             :     }
     311             :   }
     312           0 :   return size;
     313             : }
     314             : 
     315             : /* virtual */ nscoord
     316           0 : nsTableWrapperFrame::GetMinISize(gfxContext *aRenderingContext)
     317             : {
     318           0 :   nscoord iSize = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     319           0 :                     InnerTableFrame(), nsLayoutUtils::MIN_ISIZE);
     320           0 :   DISPLAY_MIN_WIDTH(this, iSize);
     321           0 :   if (mCaptionFrames.NotEmpty()) {
     322             :     nscoord capISize =
     323           0 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     324             :                                            mCaptionFrames.FirstChild(),
     325           0 :                                            nsLayoutUtils::MIN_ISIZE);
     326           0 :     if (HasSideCaption()) {
     327           0 :       iSize += capISize;
     328             :     } else {
     329           0 :       if (capISize > iSize) {
     330           0 :         iSize = capISize;
     331             :       }
     332             :     }
     333             :   }
     334           0 :   return iSize;
     335             : }
     336             : 
     337             : /* virtual */ nscoord
     338           0 : nsTableWrapperFrame::GetPrefISize(gfxContext *aRenderingContext)
     339             : {
     340             :   nscoord maxISize;
     341           0 :   DISPLAY_PREF_WIDTH(this, maxISize);
     342             : 
     343           0 :   maxISize = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     344           0 :                InnerTableFrame(), nsLayoutUtils::PREF_ISIZE);
     345           0 :   if (mCaptionFrames.NotEmpty()) {
     346           0 :     uint8_t captionSide = GetCaptionSide();
     347           0 :     switch (captionSide) {
     348             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     349             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     350             :       {
     351             :         nscoord capMin =
     352           0 :           nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     353             :                                                mCaptionFrames.FirstChild(),
     354           0 :                                                nsLayoutUtils::MIN_ISIZE);
     355           0 :         maxISize += capMin;
     356             :       }
     357           0 :       break;
     358             :     default:
     359             :       {
     360             :         nsLayoutUtils::IntrinsicISizeType iwt;
     361           0 :         if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     362             :             captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     363             :           // Don't let the caption's pref isize expand the table's pref
     364             :           // isize.
     365           0 :           iwt = nsLayoutUtils::MIN_ISIZE;
     366             :         } else {
     367           0 :           NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
     368             :                        captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
     369             :                        "unexpected caption side");
     370           0 :           iwt = nsLayoutUtils::PREF_ISIZE;
     371             :         }
     372             :         nscoord capPref =
     373           0 :           nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     374             :                                                mCaptionFrames.FirstChild(),
     375           0 :                                                iwt);
     376           0 :         maxISize = std::max(maxISize, capPref);
     377             :       }
     378           0 :       break;
     379             :     }
     380             :   }
     381           0 :   return maxISize;
     382             : }
     383             : 
     384             : nscoord
     385           0 : nsTableWrapperFrame::ChildShrinkWrapISize(gfxContext*         aRenderingContext,
     386             :                                           nsIFrame*           aChildFrame,
     387             :                                           WritingMode         aWM,
     388             :                                           LogicalSize         aCBSize,
     389             :                                           nscoord             aAvailableISize,
     390             :                                           nscoord*            aMarginResult) const
     391             : {
     392           0 :   AutoMaybeDisableFontInflation an(aChildFrame);
     393             : 
     394             :   // For the caption frame, child's WM may differ from the table's main WM.
     395           0 :   WritingMode childWM = aChildFrame->GetWritingMode();
     396             : 
     397             :   SizeComputationInput offsets(aChildFrame, aRenderingContext, aWM,
     398           0 :                                aCBSize.ISize(aWM));
     399             :   LogicalSize marginSize =
     400           0 :     offsets.ComputedLogicalMargin().Size(childWM).ConvertTo(aWM, childWM);
     401             :   LogicalSize paddingSize =
     402           0 :     offsets.ComputedLogicalPadding().Size(childWM).ConvertTo(aWM, childWM);
     403             :   LogicalSize bpSize =
     404           0 :     offsets.ComputedLogicalBorderPadding().Size(childWM).ConvertTo(aWM, childWM);
     405             : 
     406             :   // Shrink-wrap aChildFrame by default, except if we're a stretched grid item.
     407           0 :   auto flags = ComputeSizeFlags::eShrinkWrap;
     408           0 :   auto parent = GetParent();
     409           0 :   bool isGridItem = parent && parent->IsGridContainerFrame() &&
     410           0 :                     !HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
     411           0 :   if (MOZ_UNLIKELY(isGridItem) &&
     412           0 :       !StyleMargin()->HasInlineAxisAuto(aWM)) {
     413           0 :     auto inlineAxisAlignment = aWM.IsOrthogonalTo(parent->GetWritingMode()) ?
     414           0 :                      StylePosition()->UsedAlignSelf(parent->StyleContext()) :
     415           0 :                      StylePosition()->UsedJustifySelf(parent->StyleContext());
     416           0 :     if (inlineAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
     417             :         inlineAxisAlignment == NS_STYLE_ALIGN_STRETCH) {
     418           0 :       flags = nsIFrame::ComputeSizeFlags::eDefault;
     419             :     }
     420             :   }
     421             : 
     422             :   LogicalSize size =
     423             :     aChildFrame->ComputeSize(aRenderingContext, aWM, aCBSize, aAvailableISize,
     424           0 :                              marginSize, bpSize - paddingSize, paddingSize,
     425           0 :                              flags);
     426           0 :   if (aMarginResult) {
     427           0 :     *aMarginResult = offsets.ComputedLogicalMargin().IStartEnd(aWM);
     428             :   }
     429           0 :   return size.ISize(aWM) + marginSize.ISize(aWM) + bpSize.ISize(aWM);
     430             : }
     431             : 
     432             : /* virtual */
     433             : LogicalSize
     434           0 : nsTableWrapperFrame::ComputeAutoSize(gfxContext*         aRenderingContext,
     435             :                                      WritingMode         aWM,
     436             :                                      const LogicalSize&  aCBSize,
     437             :                                      nscoord             aAvailableISize,
     438             :                                      const LogicalSize&  aMargin,
     439             :                                      const LogicalSize&  aBorder,
     440             :                                      const LogicalSize&  aPadding,
     441             :                                      ComputeSizeFlags    aFlags)
     442             : {
     443           0 :   nscoord kidAvailableISize = aAvailableISize - aMargin.ISize(aWM);
     444           0 :   NS_ASSERTION(aBorder.IsAllZero() && aPadding.IsAllZero(),
     445             :                "Table wrapper frames cannot have borders or paddings");
     446             : 
     447             :   // When we're shrink-wrapping, our auto size needs to wrap around the
     448             :   // actual size of the table, which (if it is specified as a percent)
     449             :   // could be something that is not reflected in our GetMinISize and
     450             :   // GetPrefISize.  See bug 349457 for an example.
     451             : 
     452             :   // Match the availableISize logic in Reflow.
     453           0 :   uint8_t captionSide = GetCaptionSide();
     454             :   nscoord inlineSize;
     455           0 :   if (captionSide == NO_SIDE) {
     456           0 :     inlineSize = ChildShrinkWrapISize(aRenderingContext, InnerTableFrame(), aWM,
     457           0 :                                       aCBSize, kidAvailableISize);
     458           0 :   } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
     459             :              captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
     460           0 :     nscoord capISize = ChildShrinkWrapISize(aRenderingContext,
     461             :                                             mCaptionFrames.FirstChild(), aWM,
     462           0 :                                             aCBSize, kidAvailableISize);
     463           0 :     inlineSize = capISize + ChildShrinkWrapISize(aRenderingContext,
     464           0 :                                                  InnerTableFrame(), aWM,
     465             :                                                  aCBSize,
     466           0 :                                                  kidAvailableISize - capISize);
     467           0 :   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     468             :              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     469             :     nscoord margin;
     470           0 :     inlineSize = ChildShrinkWrapISize(aRenderingContext, InnerTableFrame(), aWM,
     471           0 :                                       aCBSize, kidAvailableISize, &margin);
     472           0 :     nscoord capISize = ChildShrinkWrapISize(aRenderingContext,
     473             :                                             mCaptionFrames.FirstChild(), aWM,
     474           0 :                                             aCBSize, inlineSize - margin);
     475           0 :     if (capISize > inlineSize) {
     476           0 :       inlineSize = capISize;
     477           0 :     }
     478             :   } else {
     479           0 :     NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
     480             :                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
     481             :                  "unexpected caption-side");
     482           0 :     inlineSize = ChildShrinkWrapISize(aRenderingContext, InnerTableFrame(), aWM,
     483           0 :                                       aCBSize, kidAvailableISize);
     484           0 :     nscoord capISize = ChildShrinkWrapISize(aRenderingContext,
     485             :                                             mCaptionFrames.FirstChild(), aWM,
     486           0 :                                             aCBSize, kidAvailableISize);
     487           0 :     if (capISize > inlineSize) {
     488           0 :       inlineSize = capISize;
     489             :     }
     490             :   }
     491             : 
     492           0 :   return LogicalSize(aWM, inlineSize, NS_UNCONSTRAINEDSIZE);
     493             : }
     494             : 
     495             : uint8_t
     496           0 : nsTableWrapperFrame::GetCaptionSide()
     497             : {
     498           0 :   if (mCaptionFrames.NotEmpty()) {
     499           0 :     return mCaptionFrames.FirstChild()->StyleTableBorder()->mCaptionSide;
     500             :   }
     501             :   else {
     502           0 :     return NO_SIDE; // no caption
     503             :   }
     504             : }
     505             : 
     506             : uint8_t
     507           0 : nsTableWrapperFrame::GetCaptionVerticalAlign()
     508             : {
     509             :   const nsStyleCoord& va =
     510           0 :     mCaptionFrames.FirstChild()->StyleDisplay()->mVerticalAlign;
     511             : 
     512           0 :   return (va.GetUnit() == eStyleUnit_Enumerated)
     513           0 :            ? va.GetIntValue()
     514           0 :            : NS_STYLE_VERTICAL_ALIGN_TOP;
     515             : }
     516             : 
     517             : void
     518           0 : nsTableWrapperFrame::SetDesiredSize(uint8_t              aCaptionSide,
     519             :                                     const LogicalSize&   aInnerSize,
     520             :                                     const LogicalSize&   aCaptionSize,
     521             :                                     const LogicalMargin& aInnerMargin,
     522             :                                     const LogicalMargin& aCaptionMargin,
     523             :                                     nscoord&             aISize,
     524             :                                     nscoord&             aBSize,
     525             :                                     WritingMode          aWM)
     526             : {
     527           0 :   aISize = aBSize = 0;
     528             : 
     529             :   // compute the overall inline-size
     530           0 :   switch (aCaptionSide) {
     531             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     532           0 :       aISize =
     533           0 :         std::max(aInnerMargin.LineLeft(aWM),
     534           0 :                  aCaptionMargin.IStartEnd(aWM) + aCaptionSize.ISize(aWM)) +
     535           0 :         aInnerSize.ISize(aWM) + aInnerMargin.LineRight(aWM);
     536           0 :       break;
     537             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     538           0 :       aISize =
     539           0 :         std::max(aInnerMargin.LineRight(aWM),
     540           0 :                  aCaptionMargin.IStartEnd(aWM) + aCaptionSize.ISize(aWM)) +
     541           0 :         aInnerSize.ISize(aWM) + aInnerMargin.LineLeft(aWM);
     542           0 :       break;
     543             :     default:
     544           0 :       aISize =
     545           0 :         std::max(aInnerMargin.IStartEnd(aWM) + aInnerSize.ISize(aWM),
     546           0 :                  aCaptionMargin.IStartEnd(aWM) + aCaptionSize.ISize(aWM));
     547           0 :       break;
     548             :   }
     549             : 
     550             :   // compute the overall block-size
     551           0 :   switch (aCaptionSide) {
     552             :     case NS_STYLE_CAPTION_SIDE_TOP:
     553             :     case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
     554           0 :       aBSize = aInnerSize.BSize(aWM) + aInnerMargin.BEnd(aWM);
     555           0 :       aBSize +=
     556           0 :         std::max(aInnerMargin.BStart(aWM),
     557           0 :                  aCaptionSize.BSize(aWM) + aCaptionMargin.BStartEnd(aWM));
     558           0 :       break;
     559             :     case NS_STYLE_CAPTION_SIDE_BOTTOM:
     560             :     case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE:
     561           0 :       aBSize = aInnerSize.BSize(aWM) + aInnerMargin.BStart(aWM);
     562           0 :       aBSize +=
     563           0 :         std::max(aInnerMargin.BEnd(aWM),
     564           0 :                  aCaptionSize.BSize(aWM) + aCaptionMargin.BStartEnd(aWM));
     565           0 :       break;
     566             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     567             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     568           0 :       aBSize = aInnerMargin.BStart(aWM);
     569           0 :       aBSize +=
     570           0 :         std::max(aInnerSize.BSize(aWM) + aInnerMargin.BEnd(aWM),
     571           0 :                  aCaptionSize.BSize(aWM) + aCaptionMargin.BEnd(aWM));
     572           0 :       break;
     573             :     default:
     574           0 :       NS_ASSERTION(aCaptionSide == NO_SIDE, "unexpected caption side");
     575           0 :       aBSize = aInnerSize.BSize(aWM) + aInnerMargin.BStartEnd(aWM);
     576           0 :       break;
     577             :   }
     578             : 
     579             :   // negative sizes can upset overflow-area code
     580           0 :   aISize = std::max(aISize, 0);
     581           0 :   aBSize = std::max(aBSize, 0);
     582           0 : }
     583             : 
     584             : nsresult
     585           0 : nsTableWrapperFrame::GetCaptionOrigin(uint32_t             aCaptionSide,
     586             :                                       const LogicalSize&   aContainBlockSize,
     587             :                                       const LogicalSize&   aInnerSize,
     588             :                                       const LogicalMargin& aInnerMargin,
     589             :                                       const LogicalSize&   aCaptionSize,
     590             :                                       LogicalMargin&       aCaptionMargin,
     591             :                                       LogicalPoint&        aOrigin,
     592             :                                       WritingMode          aWM)
     593             : {
     594           0 :   aOrigin.I(aWM) = aOrigin.B(aWM) = 0;
     595           0 :   if ((NS_UNCONSTRAINEDSIZE == aInnerSize.ISize(aWM)) ||
     596           0 :       (NS_UNCONSTRAINEDSIZE == aInnerSize.BSize(aWM)) ||
     597           0 :       (NS_UNCONSTRAINEDSIZE == aCaptionSize.ISize(aWM)) ||
     598           0 :       (NS_UNCONSTRAINEDSIZE == aCaptionSize.BSize(aWM))) {
     599           0 :     return NS_OK;
     600             :   }
     601           0 :   if (mCaptionFrames.IsEmpty()) {
     602           0 :     return NS_OK;
     603             :   }
     604             : 
     605           0 :   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.IStart(aWM) &&
     606             :                NS_AUTOMARGIN != aCaptionMargin.BStart(aWM) &&
     607             :                NS_AUTOMARGIN != aCaptionMargin.BEnd(aWM),
     608             :                "The computed caption margin is auto?");
     609             : 
     610             :   // inline-dir computation
     611           0 :   switch (aCaptionSide) {
     612             :     case NS_STYLE_CAPTION_SIDE_BOTTOM:
     613             :     case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE:
     614           0 :       aOrigin.I(aWM) = aCaptionMargin.IStart(aWM);
     615           0 :       if (aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     616             :         // We placed the caption using only the table's isize as available
     617             :         // isize, and we should position it this way as well.
     618           0 :         aOrigin.I(aWM) += aInnerMargin.IStart(aWM);
     619             :       }
     620           0 :       break;
     621             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     622             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     623           0 :       aOrigin.I(aWM) = aCaptionMargin.IStart(aWM);
     624           0 :       if (aWM.IsBidiLTR() == (aCaptionSide == NS_STYLE_CAPTION_SIDE_RIGHT)) {
     625           0 :         aOrigin.I(aWM) += aInnerMargin.IStart(aWM) + aInnerSize.ISize(aWM);
     626             :       }
     627           0 :       break;
     628             :     default: // block-start
     629           0 :       NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     630             :                    aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE,
     631             :                    "unexpected caption side");
     632           0 :       aOrigin.I(aWM) = aCaptionMargin.IStart(aWM);
     633           0 :       if (aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP) {
     634             :         // We placed the caption using only the table's isize as available
     635             :         // isize, and we should position it this way as well.
     636           0 :         aOrigin.I(aWM) += aInnerMargin.IStart(aWM);
     637             :       }
     638           0 :       break;
     639             :   }
     640             :   // block-dir computation
     641           0 :   switch (aCaptionSide) {
     642             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     643             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     644           0 :       aOrigin.B(aWM) = aInnerMargin.BStart(aWM);
     645           0 :       switch (GetCaptionVerticalAlign()) {
     646             :         case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
     647           0 :           aOrigin.B(aWM) = std::max(0, aInnerMargin.BStart(aWM) +
     648           0 :                                        ((aInnerSize.BSize(aWM) -
     649           0 :                                          aCaptionSize.BSize(aWM)) / 2));
     650           0 :           break;
     651             :         case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
     652           0 :           aOrigin.B(aWM) = std::max(0, aInnerMargin.BStart(aWM) +
     653           0 :                                        aInnerSize.BSize(aWM) -
     654           0 :                                        aCaptionSize.BSize(aWM));
     655           0 :           break;
     656             :         default:
     657           0 :           break;
     658             :       }
     659           0 :       break;
     660             :     case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE:
     661             :     case NS_STYLE_CAPTION_SIDE_BOTTOM:
     662           0 :       aOrigin.B(aWM) = aInnerMargin.BStart(aWM) + aInnerSize.BSize(aWM) +
     663           0 :                        aCaptionMargin.BStart(aWM);
     664           0 :       break;
     665             :     case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
     666             :     case NS_STYLE_CAPTION_SIDE_TOP:
     667           0 :       aOrigin.B(aWM) = aInnerMargin.BStart(aWM) + aCaptionMargin.BStart(aWM);
     668           0 :       break;
     669             :     default:
     670           0 :       NS_NOTREACHED("Unknown caption alignment type");
     671           0 :       break;
     672             :   }
     673           0 :   return NS_OK;
     674             : }
     675             : 
     676             : nsresult
     677           0 : nsTableWrapperFrame::GetInnerOrigin(uint32_t             aCaptionSide,
     678             :                                     const LogicalSize&   aContainBlockSize,
     679             :                                     const LogicalSize&   aCaptionSize,
     680             :                                     const LogicalMargin& aCaptionMargin,
     681             :                                     const LogicalSize&   aInnerSize,
     682             :                                     LogicalMargin&       aInnerMargin,
     683             :                                     LogicalPoint&        aOrigin,
     684             :                                     WritingMode          aWM)
     685             : {
     686           0 :   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.IStart(aWM) &&
     687             :                NS_AUTOMARGIN != aCaptionMargin.IEnd(aWM),
     688             :                "The computed caption margin is auto?");
     689           0 :   NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.IStart(aWM) &&
     690             :                NS_AUTOMARGIN != aInnerMargin.IEnd(aWM) &&
     691             :                NS_AUTOMARGIN != aInnerMargin.BStart(aWM) &&
     692             :                NS_AUTOMARGIN != aInnerMargin.BEnd(aWM),
     693             :                "The computed inner margin is auto?");
     694             : 
     695           0 :   aOrigin.I(aWM) = aOrigin.B(aWM) = 0;
     696           0 :   if ((NS_UNCONSTRAINEDSIZE == aInnerSize.ISize(aWM)) ||
     697           0 :       (NS_UNCONSTRAINEDSIZE == aInnerSize.BSize(aWM)) ||
     698           0 :       (NS_UNCONSTRAINEDSIZE == aCaptionSize.ISize(aWM)) ||
     699           0 :       (NS_UNCONSTRAINEDSIZE == aCaptionSize.BSize(aWM))) {
     700           0 :     return NS_OK;
     701             :   }
     702             : 
     703             :   nscoord minCapISize =
     704           0 :     aCaptionSize.ISize(aWM) + aCaptionMargin.IStartEnd(aWM);
     705             : 
     706             :   // inline-dir computation
     707           0 :   switch (aCaptionSide) {
     708             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     709             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     710           0 :       if (aWM.IsBidiLTR() == (aCaptionSide == NS_STYLE_CAPTION_SIDE_LEFT)) {
     711           0 :         if (aInnerMargin.IStart(aWM) < minCapISize) {
     712             :           // shift the inner table to get some place for the caption
     713           0 :           aInnerMargin.IEnd(aWM) += aInnerMargin.IStart(aWM) - minCapISize;
     714           0 :           aInnerMargin.IEnd(aWM)  = std::max(0, aInnerMargin.IEnd(aWM));
     715           0 :           aInnerMargin.IStart(aWM) = minCapISize;
     716             :         }
     717             :       }
     718           0 :       aOrigin.I(aWM) = aInnerMargin.IStart(aWM);
     719           0 :       break;
     720             :     default:
     721           0 :       NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     722             :                    aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
     723             :                    aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
     724             :                    aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE ||
     725             :                    aCaptionSide == NO_SIDE,
     726             :                    "unexpected caption side");
     727           0 :       aOrigin.I(aWM) = aInnerMargin.IStart(aWM);
     728           0 :       break;
     729             :   }
     730             : 
     731             :   // block-dir computation
     732           0 :   switch (aCaptionSide) {
     733             :     case NS_STYLE_CAPTION_SIDE_BOTTOM:
     734             :     case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE:
     735           0 :       aOrigin.B(aWM) = aInnerMargin.BStart(aWM);
     736           0 :       break;
     737             :     case NS_STYLE_CAPTION_SIDE_LEFT:
     738             :     case NS_STYLE_CAPTION_SIDE_RIGHT:
     739           0 :       aOrigin.B(aWM) = aInnerMargin.BStart(aWM);
     740           0 :       switch (GetCaptionVerticalAlign()) {
     741             :         case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
     742           0 :           aOrigin.B(aWM) =
     743           0 :             std::max(aInnerMargin.BStart(aWM),
     744           0 :                      (aCaptionSize.BSize(aWM) - aInnerSize.BSize(aWM)) / 2);
     745           0 :           break;
     746             :         case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
     747           0 :           aOrigin.B(aWM) =
     748           0 :             std::max(aInnerMargin.BStart(aWM),
     749           0 :                      aCaptionSize.BSize(aWM) - aInnerSize.BSize(aWM));
     750           0 :           break;
     751             :         default:
     752           0 :           break;
     753             :       }
     754           0 :       break;
     755             :     case NO_SIDE:
     756             :     case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
     757             :     case NS_STYLE_CAPTION_SIDE_TOP:
     758           0 :       aOrigin.B(aWM) = aInnerMargin.BStart(aWM) + aCaptionSize.BSize(aWM) +
     759           0 :                        aCaptionMargin.BStartEnd(aWM);
     760           0 :       break;
     761             :     default:
     762           0 :       NS_NOTREACHED("Unknown caption alignment type");
     763           0 :       break;
     764             :   }
     765           0 :   return NS_OK;
     766             : }
     767             : 
     768             : void
     769           0 : nsTableWrapperFrame::OuterBeginReflowChild(nsPresContext*            aPresContext,
     770             :                                            nsIFrame*                 aChildFrame,
     771             :                                            const ReflowInput&  aOuterRI,
     772             :                                            Maybe<ReflowInput>& aChildRI,
     773             :                                            nscoord                   aAvailISize)
     774             : {
     775             :   // work around pixel rounding errors, round down to ensure we don't exceed the avail height in
     776           0 :   WritingMode wm = aChildFrame->GetWritingMode();
     777           0 :   LogicalSize outerSize = aOuterRI.AvailableSize(wm);
     778           0 :   nscoord availBSize = outerSize.BSize(wm);
     779           0 :   if (NS_UNCONSTRAINEDSIZE != availBSize) {
     780           0 :     if (mCaptionFrames.FirstChild() == aChildFrame) {
     781           0 :       availBSize = NS_UNCONSTRAINEDSIZE;
     782             :     } else {
     783           0 :       LogicalMargin margin(wm);
     784           0 :       GetChildMargin(aPresContext, aOuterRI, aChildFrame,
     785           0 :                      outerSize.ISize(wm), margin);
     786             : 
     787           0 :       NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.BStart(wm),
     788             :                    "No unconstrainedsize arithmetic, please");
     789           0 :       availBSize -= margin.BStart(wm);
     790             : 
     791           0 :       NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.BEnd(wm),
     792             :                    "No unconstrainedsize arithmetic, please");
     793           0 :       availBSize -= margin.BEnd(wm);
     794             :     }
     795             :   }
     796           0 :   LogicalSize availSize(wm, aAvailISize, availBSize);
     797             :   // create and init the child reflow state, using passed-in Maybe<>,
     798             :   // so that caller can use it after we return.
     799           0 :   aChildRI.emplace(aPresContext, aOuterRI, aChildFrame, availSize,
     800           0 :                   nullptr, ReflowInput::CALLER_WILL_INIT);
     801           0 :   InitChildReflowInput(*aPresContext, aOuterRI, *aChildRI);
     802             : 
     803             :   // see if we need to reset top-of-page due to a caption
     804           0 :   if (aChildRI->mFlags.mIsTopOfPage &&
     805           0 :       mCaptionFrames.FirstChild() == aChildFrame) {
     806           0 :     uint8_t captionSide = GetCaptionSide();
     807           0 :     if (captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
     808             :         captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) {
     809           0 :       aChildRI->mFlags.mIsTopOfPage = false;
     810             :     }
     811             :   }
     812           0 : }
     813             : 
     814             : void
     815           0 : nsTableWrapperFrame::OuterDoReflowChild(nsPresContext*             aPresContext,
     816             :                                         nsIFrame*                  aChildFrame,
     817             :                                         const ReflowInput&   aChildRI,
     818             :                                         ReflowOutput&       aMetrics,
     819             :                                         nsReflowStatus&            aStatus)
     820             : {
     821             :   // Using zero as containerSize here because we want consistency between
     822             :   // the GetLogicalPosition and ReflowChild calls, to avoid unnecessarily
     823             :   // changing the frame's coordinates; but we don't yet know its final
     824             :   // position anyway so the actual value is unimportant.
     825           0 :   const nsSize zeroCSize;
     826           0 :   WritingMode wm = aChildRI.GetWritingMode();
     827             : 
     828             :   // Use the current position as a best guess for placement.
     829           0 :   LogicalPoint childPt = aChildFrame->GetLogicalPosition(wm, zeroCSize);
     830           0 :   uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
     831             : 
     832             :   // We don't want to delete our next-in-flow's child if it's an inner table
     833             :   // frame, because table wrapper frames always assume that their inner table
     834             :   // frames don't go away. If a table wrapper frame is removed because it is
     835             :   // a next-in-flow of an already complete table wrapper frame, then it will
     836             :   // take care of removing it's inner table frame.
     837           0 :   if (aChildFrame == InnerTableFrame()) {
     838           0 :     flags |= NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD;
     839             :   }
     840             : 
     841           0 :   ReflowChild(aChildFrame, aPresContext, aMetrics, aChildRI,
     842           0 :               wm, childPt, zeroCSize, flags, aStatus);
     843           0 : }
     844             : 
     845             : void
     846           0 : nsTableWrapperFrame::UpdateOverflowAreas(ReflowOutput& aMet)
     847             : {
     848           0 :   aMet.SetOverflowAreasToDesiredBounds();
     849           0 :   ConsiderChildOverflow(aMet.mOverflowAreas, InnerTableFrame());
     850           0 :   if (mCaptionFrames.NotEmpty()) {
     851           0 :     ConsiderChildOverflow(aMet.mOverflowAreas, mCaptionFrames.FirstChild());
     852             :   }
     853           0 : }
     854             : 
     855             : void
     856           0 : nsTableWrapperFrame::Reflow(nsPresContext*           aPresContext,
     857             :                             ReflowOutput&     aDesiredSize,
     858             :                             const ReflowInput& aOuterRI,
     859             :                             nsReflowStatus&          aStatus)
     860             : {
     861           0 :   MarkInReflow();
     862           0 :   DO_GLOBAL_REFLOW_COUNT("nsTableWrapperFrame");
     863           0 :   DISPLAY_REFLOW(aPresContext, this, aOuterRI, aDesiredSize, aStatus);
     864             : 
     865             :   // Initialize out parameters
     866           0 :   aDesiredSize.ClearSize();
     867           0 :   aStatus.Reset();
     868             : 
     869           0 :   if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
     870             :     // Set up our kids.  They're already present, on an overflow list,
     871             :     // or there are none so we'll create them now
     872           0 :     MoveOverflowToChildList();
     873             :   }
     874             : 
     875           0 :   Maybe<ReflowInput> captionRI;
     876           0 :   Maybe<ReflowInput> innerRI;
     877             : 
     878           0 :   nsRect origInnerRect = InnerTableFrame()->GetRect();
     879           0 :   nsRect origInnerVisualOverflow = InnerTableFrame()->GetVisualOverflowRect();
     880             :   bool innerFirstReflow =
     881           0 :     InnerTableFrame()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
     882           0 :   nsRect origCaptionRect;
     883           0 :   nsRect origCaptionVisualOverflow;
     884           0 :   bool captionFirstReflow = false;
     885           0 :   if (mCaptionFrames.NotEmpty()) {
     886           0 :     origCaptionRect = mCaptionFrames.FirstChild()->GetRect();
     887           0 :     origCaptionVisualOverflow =
     888           0 :       mCaptionFrames.FirstChild()->GetVisualOverflowRect();
     889             :     captionFirstReflow =
     890           0 :       mCaptionFrames.FirstChild()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
     891             :   }
     892             : 
     893             :   // ComputeAutoSize has to match this logic.
     894           0 :   WritingMode wm = aOuterRI.GetWritingMode();
     895           0 :   uint8_t captionSide = GetCaptionSide();
     896           0 :   WritingMode captionWM = wm; // will be changed below if necessary
     897             : 
     898           0 :   if (captionSide == NO_SIDE) {
     899             :     // We don't have a caption.
     900           0 :     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI,
     901           0 :                           innerRI, aOuterRI.ComputedSize(wm).ISize(wm));
     902           0 :   } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
     903             :              captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
     904             :     // ComputeAutoSize takes care of making side captions small. Compute
     905             :     // the caption's size first, and tell the table to fit in what's left.
     906           0 :     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRI,
     907           0 :                           captionRI, aOuterRI.ComputedSize(wm).ISize(wm));
     908           0 :     captionWM = captionRI->GetWritingMode();
     909           0 :     nscoord innerAvailISize = aOuterRI.ComputedSize(wm).ISize(wm) -
     910           0 :       captionRI->ComputedSizeWithMarginBorderPadding(wm).ISize(wm);
     911           0 :     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI,
     912           0 :                           innerRI, innerAvailISize);
     913           0 :   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     914             :              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     915             :     // Compute the table's size first, and then prevent the caption from
     916             :     // being larger in the inline dir unless it has to be.
     917             :     //
     918             :     // Note that CSS 2.1 (but not 2.0) says:
     919             :     //   The width of the anonymous box is the border-edge width of the
     920             :     //   table box inside it
     921             :     // We don't actually make our anonymous box that isize (if we did,
     922             :     // it would break 'auto' margins), but this effectively does that.
     923           0 :     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI,
     924           0 :                           innerRI, aOuterRI.ComputedSize(wm).ISize(wm));
     925             :     // It's good that CSS 2.1 says not to include margins, since we
     926             :     // can't, since they already been converted so they exactly
     927             :     // fill the available isize (ignoring the margin on one side if
     928             :     // neither are auto).  (We take advantage of that later when we call
     929             :     // GetCaptionOrigin, though.)
     930             :     nscoord innerBorderISize =
     931           0 :       innerRI->ComputedSizeWithBorderPadding(wm).ISize(wm);
     932           0 :     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRI,
     933           0 :                           captionRI, innerBorderISize);
     934           0 :     captionWM = captionRI->GetWritingMode();
     935             :   } else {
     936           0 :     NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
     937             :                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
     938             :                  "unexpected caption-side");
     939             :     // Size the table and the caption independently.
     940           0 :     captionWM = mCaptionFrames.FirstChild()->GetWritingMode();
     941           0 :     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(),
     942             :                           aOuterRI, captionRI,
     943           0 :                           aOuterRI.ComputedSize(captionWM).ISize(captionWM));
     944           0 :     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI,
     945           0 :                           innerRI, aOuterRI.ComputedSize(wm).ISize(wm));
     946             :   }
     947             : 
     948             :   // First reflow the caption.
     949           0 :   Maybe<ReflowOutput> captionMet;
     950           0 :   LogicalSize captionSize(wm);
     951           0 :   LogicalMargin captionMargin(wm);
     952           0 :   if (mCaptionFrames.NotEmpty()) {
     953           0 :     captionMet.emplace(wm);
     954           0 :     nsReflowStatus capStatus; // don't let the caption cause incomplete
     955           0 :     OuterDoReflowChild(aPresContext, mCaptionFrames.FirstChild(),
     956           0 :                        *captionRI, *captionMet, capStatus);
     957           0 :     captionSize.ISize(wm) = captionMet->ISize(wm);
     958           0 :     captionSize.BSize(wm) = captionMet->BSize(wm);
     959           0 :     captionMargin =
     960           0 :       captionRI->ComputedLogicalMargin().ConvertTo(wm, captionWM);
     961             :     // Now that we know the bsize of the caption, reduce the available bsize
     962             :     // for the table frame if we are bsize constrained and the caption is above
     963             :     // or below the inner table.  Also reduce the CB size that we store for
     964             :     // our children in case we're a grid item, by the same amount.
     965           0 :     LogicalSize* cbSize = GetProperty(GridItemCBSizeProperty());
     966           0 :     if (NS_UNCONSTRAINEDSIZE != aOuterRI.AvailableBSize() || cbSize) {
     967           0 :       nscoord captionBSize = 0;
     968           0 :       nscoord captionISize = 0;
     969           0 :       switch (captionSide) {
     970             :         case NS_STYLE_CAPTION_SIDE_TOP:
     971             :         case NS_STYLE_CAPTION_SIDE_BOTTOM:
     972             :         case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
     973             :         case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE:
     974           0 :           captionBSize = captionSize.BSize(wm) + captionMargin.BStartEnd(wm);
     975           0 :           break;
     976             :         case NS_STYLE_CAPTION_SIDE_LEFT:
     977             :         case NS_STYLE_CAPTION_SIDE_RIGHT:
     978           0 :           captionISize = captionSize.ISize(wm) + captionMargin.IStartEnd(wm);
     979           0 :           break;
     980             :       }
     981           0 :       if (NS_UNCONSTRAINEDSIZE != aOuterRI.AvailableBSize()) {
     982           0 :         innerRI->AvailableBSize() =
     983           0 :           std::max(0, innerRI->AvailableBSize() - captionBSize);
     984             :       }
     985           0 :       if (cbSize) {
     986             :         // Shrink the CB size by the size reserved for the caption.
     987           0 :         LogicalSize oldCBSize = *cbSize;
     988           0 :         cbSize->ISize(wm) = std::max(0, cbSize->ISize(wm) - captionISize);
     989           0 :         cbSize->BSize(wm) = std::max(0, cbSize->BSize(wm) - captionBSize);
     990           0 :         if (oldCBSize != *cbSize) {
     991             :           // Reset the inner table's ReflowInput to stretch it to the new size.
     992           0 :           innerRI.reset();
     993           0 :           OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI,
     994           0 :                                 innerRI, aOuterRI.ComputedSize(wm).ISize(wm));
     995             :         }
     996             :       }
     997             :     }
     998             :   }
     999             : 
    1000             :   // Then, now that we know how much to reduce the isize of the inner
    1001             :   // table to account for side captions, reflow the inner table.
    1002           0 :   ReflowOutput innerMet(innerRI->GetWritingMode());
    1003           0 :   OuterDoReflowChild(aPresContext, InnerTableFrame(), *innerRI,
    1004           0 :                      innerMet, aStatus);
    1005           0 :   LogicalSize innerSize(wm, innerMet.ISize(wm), innerMet.BSize(wm));
    1006           0 :   LogicalMargin innerMargin = innerRI->ComputedLogicalMargin();
    1007             : 
    1008           0 :   LogicalSize containSize(wm, GetContainingBlockSize(aOuterRI));
    1009             : 
    1010             :   // Now that we've reflowed both we can place them.
    1011             :   // XXXldb Most of the input variables here are now uninitialized!
    1012             : 
    1013             :   // XXX Need to recompute inner table's auto margins for the case of side
    1014             :   // captions.  (Caption's are broken too, but that should be fixed earlier.)
    1015             : 
    1016             :   // Compute the desiredSize so that we can use it as the containerSize
    1017             :   // for the FinishReflowChild calls below.
    1018           0 :   LogicalSize desiredSize(wm);
    1019           0 :   SetDesiredSize(captionSide, innerSize, captionSize,
    1020             :                  innerMargin, captionMargin,
    1021           0 :                  desiredSize.ISize(wm), desiredSize.BSize(wm), wm);
    1022           0 :   aDesiredSize.SetSize(wm, desiredSize);
    1023           0 :   nsSize containerSize = aDesiredSize.PhysicalSize();
    1024             :   // XXX It's possible for this to be NS_UNCONSTRAINEDSIZE, which will result
    1025             :   // in assertions from FinishReflowChild.
    1026             : 
    1027           0 :   if (mCaptionFrames.NotEmpty()) {
    1028           0 :     LogicalPoint captionOrigin(wm);
    1029           0 :     GetCaptionOrigin(captionSide, containSize, innerSize, innerMargin,
    1030           0 :                      captionSize, captionMargin, captionOrigin, wm);
    1031           0 :     FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, *captionMet,
    1032           0 :                       captionRI.ptr(), wm, captionOrigin, containerSize, 0);
    1033           0 :     captionRI.reset();
    1034             :   }
    1035             :   // XXX If the bsize is constrained then we need to check whether
    1036             :   // everything still fits...
    1037             : 
    1038           0 :   LogicalPoint innerOrigin(wm);
    1039           0 :   GetInnerOrigin(captionSide, containSize, captionSize, captionMargin,
    1040           0 :                  innerSize, innerMargin, innerOrigin, wm);
    1041           0 :   FinishReflowChild(InnerTableFrame(), aPresContext, innerMet, innerRI.ptr(),
    1042           0 :                     wm, innerOrigin, containerSize, 0);
    1043           0 :   innerRI.reset();
    1044             : 
    1045           0 :   if (InnerTableFrame()->IsBorderCollapse()) {
    1046           0 :     nsTableFrame::InvalidateTableFrame(InnerTableFrame(), origInnerRect,
    1047             :                                        origInnerVisualOverflow,
    1048           0 :                                        innerFirstReflow);
    1049             :   }
    1050             : 
    1051           0 :   if (mCaptionFrames.NotEmpty()) {
    1052           0 :     nsTableFrame::InvalidateTableFrame(mCaptionFrames.FirstChild(),
    1053             :                                        origCaptionRect,
    1054             :                                        origCaptionVisualOverflow,
    1055           0 :                                        captionFirstReflow);
    1056             :   }
    1057             : 
    1058           0 :   UpdateOverflowAreas(aDesiredSize);
    1059             : 
    1060           0 :   if (GetPrevInFlow()) {
    1061           0 :     ReflowOverflowContainerChildren(aPresContext, aOuterRI,
    1062             :                                     aDesiredSize.mOverflowAreas, 0,
    1063           0 :                                     aStatus);
    1064             :   }
    1065             : 
    1066           0 :   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aOuterRI, aStatus);
    1067             : 
    1068             :   // Return our desired rect
    1069             : 
    1070           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aOuterRI, aDesiredSize);
    1071           0 : }
    1072             : 
    1073             : /* ----- global methods ----- */
    1074             : 
    1075             : nsIContent*
    1076           0 : nsTableWrapperFrame::GetCellAt(uint32_t aRowIdx, uint32_t aColIdx) const
    1077             : {
    1078           0 :   nsTableCellMap* cellMap = InnerTableFrame()->GetCellMap();
    1079           0 :   if (!cellMap) {
    1080           0 :     return nullptr;
    1081             :   }
    1082             : 
    1083           0 :   nsTableCellFrame* cell = cellMap->GetCellInfoAt(aRowIdx, aColIdx);
    1084           0 :   if (!cell) {
    1085           0 :     return nullptr;
    1086             :   }
    1087             : 
    1088           0 :   return cell->GetContent();
    1089             : }
    1090             : 
    1091             : 
    1092             : nsTableWrapperFrame*
    1093           0 : NS_NewTableWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    1094             : {
    1095           0 :   return new (aPresShell) nsTableWrapperFrame(aContext);
    1096             : }
    1097             : 
    1098           0 : NS_IMPL_FRAMEARENA_HELPERS(nsTableWrapperFrame)
    1099             : 
    1100             : #ifdef DEBUG_FRAME_DUMP
    1101             : nsresult
    1102           0 : nsTableWrapperFrame::GetFrameName(nsAString& aResult) const
    1103             : {
    1104           0 :   return MakeFrameName(NS_LITERAL_STRING("TableWrapper"), aResult);
    1105             : }
    1106             : #endif
    1107             : 

Generated by: LCOV version 1.13