layout/tables/nsTableOuterFrame.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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 #include "nsTableOuterFrame.h"
     6 #include "nsTableFrame.h"
     7 #include "nsTableCellFrame.h"
     8 #include "nsStyleContext.h"
     9 #include "nsStyleConsts.h"
    10 #include "nsPresContext.h"
    11 #include "nsCSSRendering.h"
    12 #include "nsIContent.h"
    13 #include "prinrval.h"
    14 #include "nsGkAtoms.h"
    15 #include "nsHTMLParts.h"
    16 #include "nsIPresShell.h"
    17 #include "nsIServiceManager.h"
    18 #include "nsIDOMNode.h"
    19 #include "nsDisplayList.h"
    20 #include "nsLayoutUtils.h"
    21 #include <algorithm>
    23 using namespace mozilla;
    24 using namespace mozilla::layout;
    26 /* ----------- nsTableCaptionFrame ---------- */
    28 #define NS_TABLE_FRAME_CAPTION_LIST_INDEX 1
    29 #define NO_SIDE 100
    31 // caption frame
    32 nsTableCaptionFrame::nsTableCaptionFrame(nsStyleContext* aContext):
    33   nsBlockFrame(aContext)
    34 {
    35   // shrink wrap 
    36   SetFlags(NS_BLOCK_FLOAT_MGR);
    37 }
    39 nsTableCaptionFrame::~nsTableCaptionFrame()
    40 {
    41 }
    43 nsIAtom*
    44 nsTableCaptionFrame::GetType() const
    45 {
    46   return nsGkAtoms::tableCaptionFrame;
    47 }
    49 /* virtual */ nscoord
    50 nsTableOuterFrame::GetBaseline() const
    51 {
    52   nsIFrame* kid = mFrames.FirstChild();
    53   if (!kid) {
    54     NS_NOTREACHED("no inner table");
    55     return nsContainerFrame::GetBaseline();
    56   }
    58   return kid->GetBaseline() + kid->GetPosition().y;
    59 }
    61 /* virtual */ nsSize
    62 nsTableCaptionFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
    63                                      nsSize aCBSize, nscoord aAvailableWidth,
    64                                      nsSize aMargin, nsSize aBorder,
    65                                      nsSize aPadding, bool aShrinkWrap)
    66 {
    67   nsSize result = nsBlockFrame::ComputeAutoSize(aRenderingContext, aCBSize,
    68                     aAvailableWidth, aMargin, aBorder, aPadding, aShrinkWrap);
    70   // If we're a container for font size inflation, then shrink
    71   // wrapping inside of us should not apply font size inflation.
    72   AutoMaybeDisableFontInflation an(this);
    74   uint8_t captionSide = StyleTableBorder()->mCaptionSide;
    75   if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
    76       captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
    77     result.width = GetMinWidth(aRenderingContext);
    78   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
    79              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
    80     // The outer frame constrains our available width to the width of
    81     // the table.  Grow if our min-width is bigger than that, but not
    82     // larger than the containing block width.  (It would really be nice
    83     // to transmit that information another way, so we could grow up to
    84     // the table's available width, but that's harder.)
    85     nscoord min = GetMinWidth(aRenderingContext);
    86     if (min > aCBSize.width)
    87       min = aCBSize.width;
    88     if (min > result.width)
    89       result.width = min;
    90   }
    91   return result;
    92 }
    94 nsIFrame*
    95 nsTableCaptionFrame::GetParentStyleContextFrame() const
    96 {
    97   NS_PRECONDITION(mContent->GetParent(),
    98                   "How could we not have a parent here?");
   100   // The caption's style context parent is the inner frame, unless
   101   // it's anonymous.
   102   nsIFrame* outerFrame = GetParent();
   103   if (outerFrame && outerFrame->GetType() == nsGkAtoms::tableOuterFrame) {
   104     nsIFrame* innerFrame = outerFrame->GetFirstPrincipalChild();
   105     if (innerFrame) {
   106       return nsFrame::CorrectStyleParentFrame(innerFrame,
   107                                               StyleContext()->GetPseudo());
   108     }
   109   }
   111   NS_NOTREACHED("Where is our inner table frame?");
   112   return nsBlockFrame::GetParentStyleContextFrame();
   113 }
   115 #ifdef ACCESSIBILITY
   116 a11y::AccType
   117 nsTableCaptionFrame::AccessibleType()
   118 {
   119   if (!GetRect().IsEmpty()) {
   120     return a11y::eHTMLCaptionType;
   121   }
   123   return a11y::eNoType;
   124 }
   125 #endif
   127 #ifdef DEBUG_FRAME_DUMP
   128 nsresult
   129 nsTableCaptionFrame::GetFrameName(nsAString& aResult) const
   130 {
   131   return MakeFrameName(NS_LITERAL_STRING("Caption"), aResult);
   132 }
   133 #endif
   135 nsIFrame* 
   136 NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
   137 {
   138   return new (aPresShell) nsTableCaptionFrame(aContext);
   139 }
   141 NS_IMPL_FRAMEARENA_HELPERS(nsTableCaptionFrame)
   143 /* ----------- nsTableOuterFrame ---------- */
   145 nsTableOuterFrame::nsTableOuterFrame(nsStyleContext* aContext):
   146   nsContainerFrame(aContext)
   147 {
   148 }
   150 nsTableOuterFrame::~nsTableOuterFrame()
   151 {
   152 }
   154 NS_QUERYFRAME_HEAD(nsTableOuterFrame)
   155   NS_QUERYFRAME_ENTRY(nsTableOuterFrame)
   156 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
   158 #ifdef ACCESSIBILITY
   159 a11y::AccType
   160 nsTableOuterFrame::AccessibleType()
   161 {
   162   return a11y::eHTMLTableType;
   163 }
   164 #endif
   166 void
   167 nsTableOuterFrame::DestroyFrom(nsIFrame* aDestructRoot)
   168 {
   169   DestroyAbsoluteFrames(aDestructRoot);
   170   mCaptionFrames.DestroyFramesFrom(aDestructRoot);
   171   nsContainerFrame::DestroyFrom(aDestructRoot);
   172 }
   174 const nsFrameList&
   175 nsTableOuterFrame::GetChildList(ChildListID aListID) const
   176 {
   177   if (aListID == kCaptionList) {
   178     return mCaptionFrames;
   179   }
   181   return nsContainerFrame::GetChildList(aListID);
   182 }
   184 void
   185 nsTableOuterFrame::GetChildLists(nsTArray<ChildList>* aLists) const
   186 {
   187   nsContainerFrame::GetChildLists(aLists);
   188   mCaptionFrames.AppendIfNonempty(aLists, kCaptionList);
   189 }
   191 nsresult 
   192 nsTableOuterFrame::SetInitialChildList(ChildListID     aListID,
   193                                        nsFrameList&    aChildList)
   194 {
   195   if (kCaptionList == aListID) {
   196     // the frame constructor already checked for table-caption display type
   197     mCaptionFrames.SetFrames(aChildList);
   198   }
   199   else {
   200     NS_ASSERTION(aListID == kPrincipalList, "wrong childlist");
   201     NS_ASSERTION(mFrames.IsEmpty(), "Frame leak!");
   202     NS_ASSERTION(aChildList.FirstChild() &&
   203                  nsGkAtoms::tableFrame == aChildList.FirstChild()->GetType(),
   204                  "expected a table frame");
   205     mFrames.SetFrames(aChildList);
   206   }
   208   return NS_OK;
   209 }
   211 nsresult
   212 nsTableOuterFrame::AppendFrames(ChildListID     aListID,
   213                                 nsFrameList&    aFrameList)
   214 {
   215   nsresult rv;
   217   // We only have two child frames: the inner table and a caption frame.
   218   // The inner frame is provided when we're initialized, and it cannot change
   219   if (kCaptionList == aListID) {
   220     NS_ASSERTION(aFrameList.IsEmpty() ||
   221                  aFrameList.FirstChild()->GetType() == nsGkAtoms::tableCaptionFrame,
   222                  "appending non-caption frame to captionList");
   223     mCaptionFrames.AppendFrames(this, aFrameList);
   224     rv = NS_OK;
   226     // Reflow the new caption frame. It's already marked dirty, so
   227     // just tell the pres shell.
   228     PresContext()->PresShell()->
   229       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
   230                        NS_FRAME_HAS_DIRTY_CHILDREN);
   231   }
   232   else {
   233     NS_PRECONDITION(false, "unexpected child list");
   234     rv = NS_ERROR_UNEXPECTED;
   235   }
   237   return rv;
   238 }
   240 nsresult
   241 nsTableOuterFrame::InsertFrames(ChildListID     aListID,
   242                                 nsIFrame*       aPrevFrame,
   243                                 nsFrameList&    aFrameList)
   244 {
   245   if (kCaptionList == aListID) {
   246     NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
   247                  "inserting after sibling frame with different parent");
   248     NS_ASSERTION(aFrameList.IsEmpty() ||
   249                  aFrameList.FirstChild()->GetType() == nsGkAtoms::tableCaptionFrame,
   250                  "inserting non-caption frame into captionList");
   251     mCaptionFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
   253     // Reflow the new caption frame. It's already marked dirty, so
   254     // just tell the pres shell.
   255     PresContext()->PresShell()->
   256       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
   257                        NS_FRAME_HAS_DIRTY_CHILDREN);
   258     return NS_OK;
   259   }
   260   else {
   261     NS_PRECONDITION(!aPrevFrame, "invalid previous frame");
   262     return AppendFrames(aListID, aFrameList);
   263   }
   264 }
   266 nsresult
   267 nsTableOuterFrame::RemoveFrame(ChildListID     aListID,
   268                                nsIFrame*       aOldFrame)
   269 {
   270   // We only have two child frames: the inner table and one caption frame.
   271   // The inner frame can't be removed so this should be the caption
   272   NS_PRECONDITION(kCaptionList == aListID, "can't remove inner frame");
   274   if (HasSideCaption()) {
   275     // The old caption width had an effect on the inner table width so
   276     // we're going to need to reflow it. Mark it dirty
   277     InnerTableFrame()->AddStateBits(NS_FRAME_IS_DIRTY);
   278   }
   280   // Remove the frame and destroy it
   281   mCaptionFrames.DestroyFrame(aOldFrame);
   283   PresContext()->PresShell()->
   284     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
   285                      NS_FRAME_HAS_DIRTY_CHILDREN); // also means child removed
   287   return NS_OK;
   288 }
   290 void
   291 nsTableOuterFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   292                                     const nsRect&           aDirtyRect,
   293                                     const nsDisplayListSet& aLists)
   294 {
   295   // No border, background or outline are painted because they all belong
   296   // to the inner table.
   298   // If there's no caption, take a short cut to avoid having to create
   299   // the special display list set and then sort it.
   300   if (mCaptionFrames.IsEmpty()) {
   301     BuildDisplayListForInnerTable(aBuilder, aDirtyRect, aLists);
   302     return;
   303   }
   305   nsDisplayListCollection set;
   306   BuildDisplayListForInnerTable(aBuilder, aDirtyRect, set);
   308   nsDisplayListSet captionSet(set, set.BlockBorderBackgrounds());
   309   BuildDisplayListForChild(aBuilder, mCaptionFrames.FirstChild(),
   310                            aDirtyRect, captionSet);
   312   // Now we have to sort everything by content order, since the caption
   313   // may be somewhere inside the table
   314   set.SortAllByContentOrder(aBuilder, GetContent());
   315   set.MoveTo(aLists);
   316 }
   318 void
   319 nsTableOuterFrame::BuildDisplayListForInnerTable(nsDisplayListBuilder*   aBuilder,
   320                                                  const nsRect&           aDirtyRect,
   321                                                  const nsDisplayListSet& aLists)
   322 {
   323   // Just paint the regular children, but the children's background is our
   324   // true background (there should only be one, the real table)
   325   nsIFrame* kid = mFrames.FirstChild();
   326   // The children should be in content order
   327   while (kid) {
   328     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
   329     kid = kid->GetNextSibling();
   330   }
   331 }
   333 nsIFrame*
   334 nsTableOuterFrame::GetParentStyleContextFrame() const
   335 {
   336   // The table outer frame and the (inner) table frame split the style
   337   // data by giving the table frame the style context associated with
   338   // the table content node and creating a style context for the outer
   339   // frame that is a *child* of the table frame's style context,
   340   // matching the ::-moz-table-outer pseudo-element.  html.css has a
   341   // rule that causes that pseudo-element (and thus the outer table)
   342   // to inherit *some* style properties from the table frame.  The
   343   // children of the table inherit directly from the inner table, and
   344   // the outer table's style context is a leaf.
   346   return InnerTableFrame();
   347 }
   349 // INCREMENTAL REFLOW HELPER FUNCTIONS 
   351 void
   352 nsTableOuterFrame::InitChildReflowState(nsPresContext&    aPresContext,                     
   353                                         nsHTMLReflowState& aReflowState)
   355 {
   356   nsMargin collapseBorder;
   357   nsMargin collapsePadding(0,0,0,0);
   358   nsMargin* pCollapseBorder  = nullptr;
   359   nsMargin* pCollapsePadding = nullptr;
   360   if (aReflowState.frame == InnerTableFrame() &&
   361       InnerTableFrame()->IsBorderCollapse()) {
   362     collapseBorder  = InnerTableFrame()->GetIncludedOuterBCBorder();
   363     pCollapseBorder = &collapseBorder;
   364     pCollapsePadding = &collapsePadding;
   365   }
   366   aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder, pCollapsePadding);
   367 }
   369 // get the margin and padding data. nsHTMLReflowState doesn't handle the
   370 // case of auto margins
   371 void
   372 nsTableOuterFrame::GetChildMargin(nsPresContext*           aPresContext,
   373                                   const nsHTMLReflowState& aOuterRS,
   374                                   nsIFrame*                aChildFrame,
   375                                   nscoord                  aAvailWidth,
   376                                   nsMargin&                aMargin)
   377 {
   378   // construct a reflow state to compute margin and padding. Auto margins
   379   // will not be computed at this time.
   381   // create and init the child reflow state
   382   // XXX We really shouldn't construct a reflow state to do this.
   383   nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame,
   384                             nsSize(aAvailWidth, aOuterRS.AvailableHeight()),
   385                             -1, -1, nsHTMLReflowState::CALLER_WILL_INIT);
   386   InitChildReflowState(*aPresContext, childRS);
   388   aMargin = childRS.ComputedPhysicalMargin();
   389 }
   391 static nsSize
   392 GetContainingBlockSize(const nsHTMLReflowState& aOuterRS)
   393 {
   394   nsSize size(0,0);
   395   const nsHTMLReflowState* containRS =
   396     aOuterRS.mCBReflowState;
   398   if (containRS) {
   399     size.width = containRS->ComputedWidth();
   400     if (NS_UNCONSTRAINEDSIZE == size.width) {
   401       size.width = 0;
   402     }
   403     size.height = containRS->ComputedHeight();
   404     if (NS_UNCONSTRAINEDSIZE == size.height) {
   405       size.height = 0;
   406     }
   407   }
   408   return size;
   409 }
   411 /* virtual */ nscoord
   412 nsTableOuterFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   413 {
   414   nscoord width = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
   415                     InnerTableFrame(), nsLayoutUtils::MIN_WIDTH);
   416   DISPLAY_MIN_WIDTH(this, width);
   417   if (mCaptionFrames.NotEmpty()) {
   418     nscoord capWidth =
   419       nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
   420                                            mCaptionFrames.FirstChild(),
   421                                            nsLayoutUtils::MIN_WIDTH);
   422     if (HasSideCaption()) {
   423       width += capWidth;
   424     } else {
   425       if (capWidth > width) {
   426         width = capWidth;
   427       }
   428     }
   429   }
   430   return width;
   431 }
   433 /* virtual */ nscoord
   434 nsTableOuterFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   435 {
   436   nscoord maxWidth;
   437   DISPLAY_PREF_WIDTH(this, maxWidth);
   439   maxWidth = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
   440                InnerTableFrame(), nsLayoutUtils::PREF_WIDTH);
   441   if (mCaptionFrames.NotEmpty()) {
   442     uint8_t captionSide = GetCaptionSide();
   443     switch(captionSide) {
   444     case NS_STYLE_CAPTION_SIDE_LEFT:
   445     case NS_STYLE_CAPTION_SIDE_RIGHT:
   446       {
   447         nscoord capMin =
   448           nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
   449                                                mCaptionFrames.FirstChild(),
   450                                                nsLayoutUtils::MIN_WIDTH);
   451         maxWidth += capMin;
   452       }
   453       break;
   454     default:
   455       {
   456         nsLayoutUtils::IntrinsicWidthType iwt;
   457         if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
   458             captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
   459           // Don't let the caption's pref width expand the table's pref
   460           // width.
   461           iwt = nsLayoutUtils::MIN_WIDTH;
   462         } else {
   463           NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
   464                        captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
   465                        "unexpected caption side");
   466           iwt = nsLayoutUtils::PREF_WIDTH;
   467         }
   468         nscoord capPref =
   469           nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
   470                                                mCaptionFrames.FirstChild(),
   471                                                iwt);
   472         maxWidth = std::max(maxWidth, capPref);
   473       }
   474       break;
   475     }
   476   }
   477   return maxWidth;
   478 }
   480 // Compute the margin-box width of aChildFrame given the inputs.  If
   481 // aMarginResult is non-null, fill it with the part of the margin-width
   482 // that was contributed by the margin.
   483 static nscoord
   484 ChildShrinkWrapWidth(nsRenderingContext *aRenderingContext,
   485                      nsIFrame *aChildFrame,
   486                      nsSize aCBSize, nscoord aAvailableWidth,
   487                      nscoord *aMarginResult = nullptr)
   488 {
   489   AutoMaybeDisableFontInflation an(aChildFrame);
   491   nsCSSOffsetState offsets(aChildFrame, aRenderingContext, aCBSize.width);
   492   nsSize size = aChildFrame->ComputeSize(aRenderingContext, aCBSize,
   493                   aAvailableWidth,
   494                   nsSize(offsets.ComputedPhysicalMargin().LeftRight(),
   495                          offsets.ComputedPhysicalMargin().TopBottom()),
   496                   nsSize(offsets.ComputedPhysicalBorderPadding().LeftRight() -
   497                            offsets.ComputedPhysicalPadding().LeftRight(),
   498                          offsets.ComputedPhysicalBorderPadding().TopBottom() -
   499                            offsets.ComputedPhysicalPadding().TopBottom()),
   500                   nsSize(offsets.ComputedPhysicalPadding().LeftRight(),
   501                          offsets.ComputedPhysicalPadding().TopBottom()),
   502                   true);
   503   if (aMarginResult)
   504     *aMarginResult = offsets.ComputedPhysicalMargin().LeftRight();
   505   return size.width + offsets.ComputedPhysicalMargin().LeftRight() +
   506                       offsets.ComputedPhysicalBorderPadding().LeftRight();
   507 }
   509 /* virtual */ nsSize
   510 nsTableOuterFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
   511                                    nsSize aCBSize, nscoord aAvailableWidth,
   512                                    nsSize aMargin, nsSize aBorder,
   513                                    nsSize aPadding, bool aShrinkWrap)
   514 {
   515   nscoord kidAvailableWidth = aAvailableWidth - aMargin.width;
   516   NS_ASSERTION(aBorder == nsSize(0, 0) &&
   517                aPadding == nsSize(0, 0),
   518                "Table outer frames cannot hae borders or paddings");
   520   // When we're shrink-wrapping, our auto size needs to wrap around the
   521   // actual size of the table, which (if it is specified as a percent)
   522   // could be something that is not reflected in our GetMinWidth and
   523   // GetPrefWidth.  See bug 349457 for an example.
   525   // Match the availableWidth logic in Reflow.
   526   uint8_t captionSide = GetCaptionSide();
   527   nscoord width;
   528   if (captionSide == NO_SIDE) {
   529     width = ChildShrinkWrapWidth(aRenderingContext, InnerTableFrame(),
   530                                  aCBSize, kidAvailableWidth);
   531   } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
   532              captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
   533     nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext,
   534                                             mCaptionFrames.FirstChild(),
   535                                             aCBSize, kidAvailableWidth);
   536     width = capWidth + ChildShrinkWrapWidth(aRenderingContext,
   537                                             InnerTableFrame(), aCBSize,
   538                                             kidAvailableWidth - capWidth);
   539   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
   540              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
   541     nscoord margin;
   542     width = ChildShrinkWrapWidth(aRenderingContext, InnerTableFrame(),
   543                                  aCBSize, kidAvailableWidth, &margin);
   544     nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext,
   545                                             mCaptionFrames.FirstChild(), aCBSize,
   546                                             width - margin);
   547     if (capWidth > width)
   548       width = capWidth;
   549   } else {
   550     NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
   551                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
   552                  "unexpected caption-side");
   553     width = ChildShrinkWrapWidth(aRenderingContext, InnerTableFrame(),
   554                                  aCBSize, kidAvailableWidth);
   555     nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext,
   556                                             mCaptionFrames.FirstChild(),
   557                                             aCBSize, kidAvailableWidth);
   558     if (capWidth > width)
   559       width = capWidth;
   560   }
   562   return nsSize(width, NS_UNCONSTRAINEDSIZE);
   563 }
   565 uint8_t
   566 nsTableOuterFrame::GetCaptionSide()
   567 {
   568   if (mCaptionFrames.NotEmpty()) {
   569     return mCaptionFrames.FirstChild()->StyleTableBorder()->mCaptionSide;
   570   }
   571   else {
   572     return NO_SIDE; // no caption
   573   }
   574 }
   576 uint8_t
   577 nsTableOuterFrame::GetCaptionVerticalAlign()
   578 {
   579   const nsStyleCoord& va =
   580     mCaptionFrames.FirstChild()->StyleTextReset()->mVerticalAlign;
   581   return (va.GetUnit() == eStyleUnit_Enumerated)
   582            ? va.GetIntValue()
   583            : NS_STYLE_VERTICAL_ALIGN_TOP;
   584 }
   586 void
   587 nsTableOuterFrame::SetDesiredSize(uint8_t         aCaptionSide,
   588                                   const nsMargin& aInnerMargin,
   589                                   const nsMargin& aCaptionMargin,
   590                                   nscoord&        aWidth,
   591                                   nscoord&        aHeight)
   592 {
   593   aWidth = aHeight = 0;
   595   nsRect innerRect = InnerTableFrame()->GetRect();
   596   nscoord innerWidth = innerRect.width;
   598   nsRect captionRect(0,0,0,0);
   599   nscoord captionWidth = 0;
   600   if (mCaptionFrames.NotEmpty()) {
   601     captionRect = mCaptionFrames.FirstChild()->GetRect();
   602     captionWidth = captionRect.width;
   603   }
   604   switch(aCaptionSide) {
   605     case NS_STYLE_CAPTION_SIDE_LEFT:
   606       aWidth = std::max(aInnerMargin.left, aCaptionMargin.left + captionWidth + aCaptionMargin.right) +
   607                innerWidth + aInnerMargin.right;
   608       break;
   609     case NS_STYLE_CAPTION_SIDE_RIGHT:
   610       aWidth = std::max(aInnerMargin.right, aCaptionMargin.left + captionWidth + aCaptionMargin.right) +
   611                innerWidth + aInnerMargin.left;
   612       break;
   613     default:
   614       aWidth = aInnerMargin.left + innerWidth + aInnerMargin.right;
   615       aWidth = std::max(aWidth, captionRect.XMost() + aCaptionMargin.right);
   616   }
   617   aHeight = innerRect.YMost() + aInnerMargin.bottom;
   618   if (NS_STYLE_CAPTION_SIDE_BOTTOM != aCaptionSide) {
   619     aHeight = std::max(aHeight, captionRect.YMost() + aCaptionMargin.bottom);
   620   }
   621   else {
   622     aHeight = std::max(aHeight, captionRect.YMost() + aCaptionMargin.bottom +
   623                               aInnerMargin.bottom);
   624   }
   626 }
   628 nsresult 
   629 nsTableOuterFrame::GetCaptionOrigin(uint32_t         aCaptionSide,
   630                                     const nsSize&    aContainBlockSize,
   631                                     const nsSize&    aInnerSize, 
   632                                     const nsMargin&  aInnerMargin,
   633                                     const nsSize&    aCaptionSize,
   634                                     nsMargin&        aCaptionMargin,
   635                                     nsPoint&         aOrigin)
   636 {
   637   aOrigin.x = aOrigin.y = 0;
   638   if ((NS_UNCONSTRAINEDSIZE == aInnerSize.width) || (NS_UNCONSTRAINEDSIZE == aInnerSize.height) ||  
   639       (NS_UNCONSTRAINEDSIZE == aCaptionSize.width) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.height)) {
   640     return NS_OK;
   641   }
   642   if (mCaptionFrames.IsEmpty()) return NS_OK;
   644   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.left,   "The computed caption margin is auto?");
   645   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.top,    "The computed caption margin is auto?");
   646   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.bottom, "The computed caption margin is auto?");
   648   // horizontal computation
   649   switch(aCaptionSide) {
   650   case NS_STYLE_CAPTION_SIDE_BOTTOM:
   651   case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: {
   652     // FIXME: Position relative to right edge for RTL.  (Based on table
   653     // direction or table parent direction?)
   654     aOrigin.x = aCaptionMargin.left;
   655     if (aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
   656       // We placed the caption using only the table's width as available
   657       // width, and we should position it this way as well.
   658       aOrigin.x += aInnerMargin.left;
   659     }
   660   } break;
   661   case NS_STYLE_CAPTION_SIDE_LEFT: {
   662     aOrigin.x = aCaptionMargin.left;
   663   } break;
   664   case NS_STYLE_CAPTION_SIDE_RIGHT: {
   665     aOrigin.x = aInnerMargin.left + aInnerSize.width + aCaptionMargin.left;
   666   } break;
   667   default: { // top
   668     NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP ||
   669                  aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE,
   670                  "unexpected caption side");
   671     // FIXME: Position relative to right edge for RTL.  (Based on table
   672     // direction or table parent direction?)
   673     aOrigin.x = aCaptionMargin.left;
   674     if (aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP) {
   675       // We placed the caption using only the table's width as available
   676       // width, and we should position it this way as well.
   677       aOrigin.x += aInnerMargin.left;
   678     }
   680   } break;
   681   }
   682   // vertical computation
   683   switch (aCaptionSide) {
   684     case NS_STYLE_CAPTION_SIDE_RIGHT:
   685     case NS_STYLE_CAPTION_SIDE_LEFT:
   686       aOrigin.y = aInnerMargin.top;
   687       switch (GetCaptionVerticalAlign()) {
   688         case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
   689           aOrigin.y = std::max(0, aInnerMargin.top + ((aInnerSize.height - aCaptionSize.height) / 2));
   690           break;
   691         case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
   692           aOrigin.y = std::max(0, aInnerMargin.top + aInnerSize.height - aCaptionSize.height);
   693           break;
   694         default:
   695           break;
   696       }
   697       break;
   698     case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE:
   699     case NS_STYLE_CAPTION_SIDE_BOTTOM: {
   700       aOrigin.y = aInnerMargin.top + aInnerSize.height + aCaptionMargin.top;
   701     } break;
   702     case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
   703     case NS_STYLE_CAPTION_SIDE_TOP: {
   704       aOrigin.y = aInnerMargin.top + aCaptionMargin.top;
   705     } break;
   706     default:
   707       NS_NOTREACHED("Unknown caption alignment type");
   708       break;
   709   }
   710   return NS_OK;
   711 }
   713 nsresult 
   714 nsTableOuterFrame::GetInnerOrigin(uint32_t         aCaptionSide,
   715                                   const nsSize&    aContainBlockSize,
   716                                   const nsSize&    aCaptionSize, 
   717                                   const nsMargin&  aCaptionMargin,
   718                                   const nsSize&    aInnerSize,
   719                                   nsMargin&        aInnerMargin,
   720                                   nsPoint&         aOrigin)
   721 {
   723   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.left,  "The computed caption margin is auto?");
   724   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.right, "The computed caption margin is auto?");
   725   NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.left,    "The computed inner margin is auto?");
   726   NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.right,   "The computed inner margin is auto?");
   727   NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.top,     "The computed inner margin is auto?");
   728   NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.bottom,  "The computed inner margin is auto?");
   730   aOrigin.x = aOrigin.y = 0;
   731   if ((NS_UNCONSTRAINEDSIZE == aInnerSize.width) || (NS_UNCONSTRAINEDSIZE == aInnerSize.height) ||  
   732       (NS_UNCONSTRAINEDSIZE == aCaptionSize.width) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.height)) {
   733     return NS_OK;
   734   }
   736   nscoord minCapWidth = aCaptionSize.width;
   738   minCapWidth += aCaptionMargin.left;
   739   minCapWidth += aCaptionMargin.right;
   741   // horizontal computation
   742   switch (aCaptionSide) {
   743   case NS_STYLE_CAPTION_SIDE_LEFT: {
   744     if (aInnerMargin.left < minCapWidth) {
   745       // shift the inner table to get some place for the caption
   746       aInnerMargin.right += aInnerMargin.left - minCapWidth;
   747       aInnerMargin.right  = std::max(0, aInnerMargin.right);
   748       aInnerMargin.left   = minCapWidth;
   749     }
   750     aOrigin.x = aInnerMargin.left;
   751   } break;
   752   default: {
   753     NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP ||
   754                  aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
   755                  aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
   756                  aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE ||
   757                  aCaptionSide == NS_STYLE_CAPTION_SIDE_RIGHT ||
   758                  aCaptionSide == NO_SIDE,
   759                  "unexpected caption side");
   760     aOrigin.x = aInnerMargin.left;
   761   } break;
   762   }
   764   // vertical computation
   765   switch (aCaptionSide) {
   766     case NS_STYLE_CAPTION_SIDE_BOTTOM:
   767     case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: {
   768       aOrigin.y = aInnerMargin.top;
   769     } break;
   770     case NS_STYLE_CAPTION_SIDE_LEFT:
   771     case NS_STYLE_CAPTION_SIDE_RIGHT: {
   772       aOrigin.y = aInnerMargin.top;
   773       switch (GetCaptionVerticalAlign()) {
   774         case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
   775           aOrigin.y = std::max(aInnerMargin.top, (aCaptionSize.height - aInnerSize.height) / 2);
   776           break;
   777         case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
   778           aOrigin.y = std::max(aInnerMargin.top, aCaptionSize.height - aInnerSize.height);
   779           break;
   780         default:
   781           break;
   782       }
   783     } break;
   784     case NO_SIDE:
   785     case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
   786     case NS_STYLE_CAPTION_SIDE_TOP: {
   787       aOrigin.y = aInnerMargin.top + aCaptionMargin.top + aCaptionSize.height +
   788                   aCaptionMargin.bottom;
   789     } break;
   790     default:
   791       NS_NOTREACHED("Unknown caption alignment type");
   792       break;
   793   }
   794   return NS_OK;
   795 }
   797 void
   798 nsTableOuterFrame::OuterBeginReflowChild(nsPresContext*           aPresContext,
   799                                          nsIFrame*                aChildFrame,
   800                                          const nsHTMLReflowState& aOuterRS,
   801                                          void*                    aChildRSSpace,
   802                                          nscoord                  aAvailWidth)
   803 { 
   804   // work around pixel rounding errors, round down to ensure we don't exceed the avail height in
   805   nscoord availHeight = aOuterRS.AvailableHeight();
   806   if (NS_UNCONSTRAINEDSIZE != availHeight) {
   807     if (mCaptionFrames.FirstChild() == aChildFrame) {
   808       availHeight = NS_UNCONSTRAINEDSIZE;
   809     } else {
   810       nsMargin margin;
   811       GetChildMargin(aPresContext, aOuterRS, aChildFrame,
   812                      aOuterRS.AvailableWidth(), margin);
   814       NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.top, "No unconstrainedsize arithmetic, please");
   815       availHeight -= margin.top;
   817       NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.bottom, "No unconstrainedsize arithmetic, please");
   818       availHeight -= margin.bottom;
   819     }
   820   }
   821   nsSize availSize(aAvailWidth, availHeight);
   822   // create and init the child reflow state, using placement new on
   823   // stack space allocated by the caller, so that the caller can destroy
   824   // it
   825   nsHTMLReflowState &childRS = * new (aChildRSSpace)
   826     nsHTMLReflowState(aPresContext, aOuterRS, aChildFrame, availSize,
   827                       -1, -1, nsHTMLReflowState::CALLER_WILL_INIT);
   828   InitChildReflowState(*aPresContext, childRS);
   830   // see if we need to reset top-of-page due to a caption
   831   if (childRS.mFlags.mIsTopOfPage &&
   832       mCaptionFrames.FirstChild() == aChildFrame) {
   833     uint8_t captionSide = GetCaptionSide();
   834     if (captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
   835         captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) {
   836       childRS.mFlags.mIsTopOfPage = false;
   837     }
   838   }
   839 }
   841 nsresult
   842 nsTableOuterFrame::OuterDoReflowChild(nsPresContext*             aPresContext,
   843                                       nsIFrame*                  aChildFrame,
   844                                       const nsHTMLReflowState&   aChildRS,
   845                                       nsHTMLReflowMetrics&       aMetrics,
   846                                       nsReflowStatus&            aStatus)
   847 { 
   849   // use the current position as a best guess for placement
   850   nsPoint childPt = aChildFrame->GetPosition();
   851   uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
   853   // We don't want to delete our next-in-flow's child if it's an inner table
   854   // frame, because outer table frames always assume that their inner table
   855   // frames don't go away. If an outer table frame is removed because it is
   856   // a next-in-flow of an already complete outer table frame, then it will
   857   // take care of removing it's inner table frame.
   858   if (aChildFrame == InnerTableFrame()) {
   859     flags |= NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD;
   860   }
   862   return ReflowChild(aChildFrame, aPresContext, aMetrics, aChildRS,
   863                      childPt.x, childPt.y, flags, aStatus);
   864 }
   866 void 
   867 nsTableOuterFrame::UpdateReflowMetrics(uint8_t              aCaptionSide,
   868                                        nsHTMLReflowMetrics& aMet,
   869                                        const nsMargin&      aInnerMargin,
   870                                        const nsMargin&      aCaptionMargin)
   871 {
   872   SetDesiredSize(aCaptionSide, aInnerMargin, aCaptionMargin,
   873                  aMet.Width(), aMet.Height());
   875   aMet.SetOverflowAreasToDesiredBounds();
   876   ConsiderChildOverflow(aMet.mOverflowAreas, InnerTableFrame());
   877   if (mCaptionFrames.NotEmpty()) {
   878     ConsiderChildOverflow(aMet.mOverflowAreas, mCaptionFrames.FirstChild());
   879   }
   880 }
   882 nsresult nsTableOuterFrame::Reflow(nsPresContext*           aPresContext,
   883                                     nsHTMLReflowMetrics&     aDesiredSize,
   884                                     const nsHTMLReflowState& aOuterRS,
   885                                     nsReflowStatus&          aStatus)
   886 {
   887   DO_GLOBAL_REFLOW_COUNT("nsTableOuterFrame");
   888   DISPLAY_REFLOW(aPresContext, this, aOuterRS, aDesiredSize, aStatus);
   890   nsresult rv = NS_OK;
   891   uint8_t captionSide = GetCaptionSide();
   893   // Initialize out parameters
   894   aDesiredSize.Width() = aDesiredSize.Height() = 0;
   895   aStatus = NS_FRAME_COMPLETE;
   897   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
   898     // Set up our kids.  They're already present, on an overflow list, 
   899     // or there are none so we'll create them now
   900     MoveOverflowToChildList();
   901   }
   903   // Use longs to get more-aligned space.
   904   #define LONGS_IN_HTMLRS \
   905     ((sizeof(nsHTMLReflowState) + sizeof(long) - 1) / sizeof(long))
   906   long captionRSSpace[LONGS_IN_HTMLRS];
   907   nsHTMLReflowState *captionRS =
   908     static_cast<nsHTMLReflowState*>((void*)captionRSSpace);
   909   long innerRSSpace[LONGS_IN_HTMLRS];
   910   nsHTMLReflowState *innerRS =
   911     static_cast<nsHTMLReflowState*>((void*) innerRSSpace);
   913   nsRect origInnerRect = InnerTableFrame()->GetRect();
   914   nsRect origInnerVisualOverflow = InnerTableFrame()->GetVisualOverflowRect();
   915   bool innerFirstReflow =
   916     (InnerTableFrame()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
   917   nsRect origCaptionRect;
   918   nsRect origCaptionVisualOverflow;
   919   bool captionFirstReflow;
   920   if (mCaptionFrames.NotEmpty()) {
   921     origCaptionRect = mCaptionFrames.FirstChild()->GetRect();
   922     origCaptionVisualOverflow =
   923       mCaptionFrames.FirstChild()->GetVisualOverflowRect();
   924     captionFirstReflow =
   925       (mCaptionFrames.FirstChild()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
   926   }
   928   // ComputeAutoSize has to match this logic.
   929   if (captionSide == NO_SIDE) {
   930     // We don't have a caption.
   931     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
   932                           innerRSSpace, aOuterRS.ComputedWidth());
   933   } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
   934              captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
   935     // nsTableCaptionFrame::ComputeAutoSize takes care of making side
   936     // captions small.  Compute the caption's size first, and tell the
   937     // table to fit in what's left.
   938     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
   939                           captionRSSpace, aOuterRS.ComputedWidth());
   940     nscoord innerAvailWidth = aOuterRS.ComputedWidth() -
   941       (captionRS->ComputedWidth() + captionRS->ComputedPhysicalMargin().LeftRight() +
   942        captionRS->ComputedPhysicalBorderPadding().LeftRight());
   943     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
   944                           innerRSSpace, innerAvailWidth);
   946   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
   947              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
   948     // Compute the table's size first, and then prevent the caption from
   949     // being wider unless it has to be.
   950     //
   951     // Note that CSS 2.1 (but not 2.0) says:
   952     //   The width of the anonymous box is the border-edge width of the
   953     //   table box inside it
   954     // We don't actually make our anonymous box that width (if we did,
   955     // it would break 'auto' margins), but this effectively does that.
   956     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
   957                           innerRSSpace, aOuterRS.ComputedWidth());
   958     // It's good that CSS 2.1 says not to include margins, since we
   959     // can't, since they already been converted so they exactly
   960     // fill the available width (ignoring the margin on one side if
   961     // neither are auto).  (We take advantage of that later when we call
   962     // GetCaptionOrigin, though.)
   963     nscoord innerBorderWidth = innerRS->ComputedWidth() +
   964                                innerRS->ComputedPhysicalBorderPadding().LeftRight();
   965     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
   966                           captionRSSpace, innerBorderWidth);
   967   } else {
   968     NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
   969                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
   970                  "unexpected caption-side");
   971     // Size the table and the caption independently.
   972     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
   973                           captionRSSpace, aOuterRS.ComputedWidth());
   974     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
   975                           innerRSSpace, aOuterRS.ComputedWidth());
   976   }
   978   // First reflow the caption.
   979   nsHTMLReflowMetrics captionMet(captionRS->GetWritingMode());
   980   nsSize captionSize;
   981   nsMargin captionMargin;
   982   if (mCaptionFrames.NotEmpty()) {
   983     nsReflowStatus capStatus; // don't let the caption cause incomplete
   984     rv = OuterDoReflowChild(aPresContext, mCaptionFrames.FirstChild(),
   985                             *captionRS, captionMet, capStatus);
   986     if (NS_FAILED(rv)) return rv;
   987     captionSize.width = captionMet.Width();
   988     captionSize.height = captionMet.Height();
   989     captionMargin = captionRS->ComputedPhysicalMargin();
   990     // Now that we know the height of the caption, reduce the available height
   991     // for the table frame if we are height constrained and the caption is above
   992     // or below the inner table.
   993     if (NS_UNCONSTRAINEDSIZE != aOuterRS.AvailableHeight()) {
   994       nscoord captionHeight = 0;
   995       switch (captionSide) {
   996         case NS_STYLE_CAPTION_SIDE_TOP:
   997         case NS_STYLE_CAPTION_SIDE_BOTTOM:
   998         case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE:
   999         case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: {
  1000           captionHeight = captionSize.height + captionMargin.TopBottom();
  1001           break;
  1004       innerRS->AvailableHeight() =
  1005         std::max(0, innerRS->AvailableHeight() - captionHeight);
  1007   } else {
  1008     captionSize.SizeTo(0,0);
  1009     captionMargin.SizeTo(0,0,0,0);
  1012   // Then, now that we know how much to reduce the width of the inner
  1013   // table to account for side captions, reflow the inner table.
  1014   nsHTMLReflowMetrics innerMet(innerRS->GetWritingMode());
  1015   rv = OuterDoReflowChild(aPresContext, InnerTableFrame(), *innerRS,
  1016                           innerMet, aStatus);
  1017   if (NS_FAILED(rv)) return rv;
  1018   nsSize innerSize;
  1019   innerSize.width = innerMet.Width();
  1020   innerSize.height = innerMet.Height();
  1021   nsMargin innerMargin = innerRS->ComputedPhysicalMargin();
  1023   nsSize   containSize = GetContainingBlockSize(aOuterRS);
  1025   // Now that we've reflowed both we can place them.
  1026   // XXXldb Most of the input variables here are now uninitialized!
  1028   // XXX Need to recompute inner table's auto margins for the case of side
  1029   // captions.  (Caption's are broken too, but that should be fixed earlier.)
  1031   if (mCaptionFrames.NotEmpty()) {
  1032     nsPoint captionOrigin;
  1033     GetCaptionOrigin(captionSide, containSize, innerSize, 
  1034                      innerMargin, captionSize, captionMargin, captionOrigin);
  1035     FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, captionMet,
  1036                       captionRS, captionOrigin.x, captionOrigin.y, 0);
  1037     captionRS->~nsHTMLReflowState();
  1039   // XXX If the height is constrained then we need to check whether
  1040   // everything still fits...
  1042   nsPoint innerOrigin;
  1043   GetInnerOrigin(captionSide, containSize, captionSize, 
  1044                  captionMargin, innerSize, innerMargin, innerOrigin);
  1045   FinishReflowChild(InnerTableFrame(), aPresContext, innerMet, innerRS,
  1046                     innerOrigin.x, innerOrigin.y, 0);
  1047   innerRS->~nsHTMLReflowState();
  1049   nsTableFrame::InvalidateTableFrame(InnerTableFrame(), origInnerRect,
  1050                                      origInnerVisualOverflow, innerFirstReflow);
  1051   if (mCaptionFrames.NotEmpty()) {
  1052     nsTableFrame::InvalidateTableFrame(mCaptionFrames.FirstChild(), origCaptionRect,
  1053                                        origCaptionVisualOverflow,
  1054                                        captionFirstReflow);
  1057   UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, captionMargin);
  1059   if (GetPrevInFlow()) {
  1060     ReflowOverflowContainerChildren(aPresContext, aOuterRS,
  1061                                     aDesiredSize.mOverflowAreas, 0,
  1062                                     aStatus);
  1065   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aOuterRS, aStatus);
  1067   // Return our desired rect
  1069   NS_FRAME_SET_TRUNCATION(aStatus, aOuterRS, aDesiredSize);
  1070   return rv;
  1073 nsIAtom*
  1074 nsTableOuterFrame::GetType() const
  1076   return nsGkAtoms::tableOuterFrame;
  1079 /* ----- global methods ----- */
  1081 nsIContent*
  1082 nsTableOuterFrame::GetCellAt(uint32_t aRowIdx, uint32_t aColIdx) const
  1084   nsTableCellMap* cellMap = InnerTableFrame()->GetCellMap();
  1085   if (!cellMap) {
  1086     return nullptr;
  1089   nsTableCellFrame* cell = cellMap->GetCellInfoAt(aRowIdx, aColIdx);
  1090   if (!cell) {
  1091     return nullptr;
  1094   return cell->GetContent();
  1098 nsIFrame*
  1099 NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  1101   return new (aPresShell) nsTableOuterFrame(aContext);
  1104 NS_IMPL_FRAMEARENA_HELPERS(nsTableOuterFrame)
  1106 #ifdef DEBUG_FRAME_DUMP
  1107 nsresult
  1108 nsTableOuterFrame::GetFrameName(nsAString& aResult) const
  1110   return MakeFrameName(NS_LITERAL_STRING("TableOuter"), aResult);
  1112 #endif

mercurial