LCOV - app.info - layout/tables/nsTableOuterFrame.cpp

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