LCOV - code coverage report
Current view: directory - layout/tables - nsTableOuterFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 463 0 0.0 %
Date: 2012-06-02 Functions: 52 0 0.0 %

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

Generated by: LCOV version 1.7