LCOV - code coverage report
Current view: directory - layout/tables - nsTableCellFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 499 0 0.0 %
Date: 2012-06-02 Functions: 68 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 "nsTableFrame.h"
      39                 : #include "nsTableColFrame.h"
      40                 : #include "nsTableCellFrame.h"
      41                 : #include "nsTableRowGroupFrame.h"
      42                 : #include "nsTablePainter.h"
      43                 : #include "nsStyleContext.h"
      44                 : #include "nsStyleConsts.h"
      45                 : #include "nsPresContext.h"
      46                 : #include "nsRenderingContext.h"
      47                 : #include "nsCSSRendering.h"
      48                 : #include "nsIContent.h"
      49                 : #include "nsGenericHTMLElement.h"
      50                 : #include "nsHTMLParts.h"
      51                 : #include "nsGkAtoms.h"
      52                 : #include "nsIPresShell.h"
      53                 : #include "nsCOMPtr.h"
      54                 : #include "nsIDOMHTMLTableCellElement.h"
      55                 : #ifdef ACCESSIBILITY
      56                 : #include "nsAccessibilityService.h"
      57                 : #endif
      58                 : #include "nsIServiceManager.h"
      59                 : #include "nsIDOMNode.h"
      60                 : #include "nsINameSpaceManager.h"
      61                 : #include "nsDisplayList.h"
      62                 : #include "nsLayoutUtils.h"
      63                 : #include "nsTextFrame.h"
      64                 : 
      65                 : //TABLECELL SELECTION
      66                 : #include "nsFrameSelection.h"
      67                 : #include "mozilla/LookAndFeel.h"
      68                 : 
      69                 : using namespace mozilla;
      70                 : 
      71                 : 
      72               0 : nsTableCellFrame::nsTableCellFrame(nsStyleContext* aContext) :
      73               0 :   nsContainerFrame(aContext)
      74                 : {
      75               0 :   mColIndex = 0;
      76               0 :   mPriorAvailWidth = 0;
      77                 : 
      78               0 :   SetContentEmpty(false);
      79               0 :   SetHasPctOverHeight(false);
      80               0 : }
      81                 : 
      82               0 : nsTableCellFrame::~nsTableCellFrame()
      83                 : {
      84               0 : }
      85                 : 
      86               0 : NS_IMPL_FRAMEARENA_HELPERS(nsTableCellFrame)
      87                 : 
      88                 : nsTableCellFrame*
      89               0 : nsTableCellFrame::GetNextCell() const
      90                 : {
      91               0 :   nsIFrame* childFrame = GetNextSibling();
      92               0 :   while (childFrame) {
      93               0 :     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
      94               0 :     if (cellFrame) {
      95               0 :       return cellFrame;
      96                 :     }
      97               0 :     childFrame = childFrame->GetNextSibling();
      98                 :   }
      99               0 :   return nsnull;
     100                 : }
     101                 : 
     102                 : NS_IMETHODIMP
     103               0 : nsTableCellFrame::Init(nsIContent*      aContent,
     104                 :                        nsIFrame*        aParent,
     105                 :                        nsIFrame*        aPrevInFlow)
     106                 : {
     107                 :   // Let the base class do its initialization
     108               0 :   nsresult rv = nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
     109                 : 
     110               0 :   if (aPrevInFlow) {
     111                 :     // Set the column index
     112               0 :     nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
     113                 :     PRInt32           colIndex;
     114               0 :     cellFrame->GetColIndex(colIndex);
     115               0 :     SetColIndex(colIndex);
     116                 :   }
     117                 : 
     118               0 :   return rv;
     119                 : }
     120                 : 
     121                 : // nsIPercentHeightObserver methods
     122                 : 
     123                 : void
     124               0 : nsTableCellFrame::NotifyPercentHeight(const nsHTMLReflowState& aReflowState)
     125                 : {
     126                 :   // nsHTMLReflowState ensures the mCBReflowState of blocks inside a
     127                 :   // cell is the cell frame, not the inner-cell block, and that the
     128                 :   // containing block of an inner table is the containing block of its
     129                 :   // outer table.
     130                 :   // XXXldb Given the now-stricter |NeedsToObserve|, many if not all of
     131                 :   // these tests are probably unnecessary.
     132                 : 
     133                 :   // Maybe the cell reflow state; we sure if we're inside the |if|.
     134               0 :   const nsHTMLReflowState *cellRS = aReflowState.mCBReflowState;
     135                 : 
     136               0 :   if (cellRS && cellRS->frame == this &&
     137               0 :       (cellRS->ComputedHeight() == NS_UNCONSTRAINEDSIZE ||
     138               0 :        cellRS->ComputedHeight() == 0)) { // XXXldb Why 0?
     139                 :     // This is a percentage height on a frame whose percentage heights
     140                 :     // are based on the height of the cell, since its containing block
     141                 :     // is the inner cell frame.
     142                 : 
     143                 :     // We'll only honor the percent height if sibling-cells/ancestors
     144                 :     // have specified/pct height. (Also, siblings only count for this if
     145                 :     // both this cell and the sibling cell span exactly 1 row.)
     146                 : 
     147               0 :     if (nsTableFrame::AncestorsHaveStyleHeight(*cellRS) ||
     148               0 :         (nsTableFrame::GetTableFrame(this)->GetEffectiveRowSpan(*this) == 1 &&
     149               0 :          (cellRS->parentReflowState->frame->GetStateBits() &
     150                 :           NS_ROW_HAS_CELL_WITH_STYLE_HEIGHT))) {
     151                 : 
     152               0 :       for (const nsHTMLReflowState *rs = aReflowState.parentReflowState;
     153                 :            rs != cellRS;
     154                 :            rs = rs->parentReflowState) {
     155               0 :         rs->frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
     156                 :       }
     157                 : 
     158               0 :       nsTableFrame::RequestSpecialHeightReflow(*cellRS);
     159                 :     }
     160                 :   }
     161               0 : }
     162                 : 
     163                 : // The cell needs to observe its block and things inside its block but nothing below that
     164                 : bool
     165               0 : nsTableCellFrame::NeedsToObserve(const nsHTMLReflowState& aReflowState)
     166                 : {
     167               0 :   const nsHTMLReflowState *rs = aReflowState.parentReflowState;
     168               0 :   if (!rs)
     169               0 :     return false;
     170               0 :   if (rs->frame == this) {
     171                 :     // We always observe the child block.  It will never send any
     172                 :     // notifications, but we need this so that the observer gets
     173                 :     // propagated to its kids.
     174               0 :     return true;
     175                 :   }
     176               0 :   rs = rs->parentReflowState;
     177               0 :   if (!rs) {
     178               0 :     return false;
     179                 :   }
     180                 : 
     181                 :   // We always need to let the percent height observer be propagated
     182                 :   // from an outer table frame to an inner table frame.
     183               0 :   nsIAtom *fType = aReflowState.frame->GetType();
     184               0 :   if (fType == nsGkAtoms::tableFrame) {
     185               0 :     return true;
     186                 :   }
     187                 : 
     188                 :   // We need the observer to be propagated to all children of the cell
     189                 :   // (i.e., children of the child block) in quirks mode, but only to
     190                 :   // tables in standards mode.
     191                 :   return rs->frame == this &&
     192               0 :          (PresContext()->CompatibilityMode() == eCompatibility_NavQuirks ||
     193               0 :           fType == nsGkAtoms::tableOuterFrame);
     194                 : }
     195                 : 
     196                 : nsresult
     197               0 : nsTableCellFrame::GetRowIndex(PRInt32 &aRowIndex) const
     198                 : {
     199                 :   nsresult result;
     200               0 :   nsTableRowFrame* row = static_cast<nsTableRowFrame*>(GetParent());
     201               0 :   if (row) {
     202               0 :     aRowIndex = row->GetRowIndex();
     203               0 :     result = NS_OK;
     204                 :   }
     205                 :   else {
     206               0 :     aRowIndex = 0;
     207               0 :     result = NS_ERROR_NOT_INITIALIZED;
     208                 :   }
     209               0 :   return result;
     210                 : }
     211                 : 
     212                 : nsresult
     213               0 : nsTableCellFrame::GetColIndex(PRInt32 &aColIndex) const
     214                 : {
     215               0 :   if (GetPrevInFlow()) {
     216               0 :     return ((nsTableCellFrame*)GetFirstInFlow())->GetColIndex(aColIndex);
     217                 :   }
     218                 :   else {
     219               0 :     aColIndex = mColIndex;
     220               0 :     return  NS_OK;
     221                 :   }
     222                 : }
     223                 : 
     224                 : NS_IMETHODIMP
     225               0 : nsTableCellFrame::AttributeChanged(PRInt32         aNameSpaceID,
     226                 :                                    nsIAtom*        aAttribute,
     227                 :                                    PRInt32         aModType)
     228                 : {
     229                 :   // We need to recalculate in this case because of the nowrap quirk in
     230                 :   // BasicTableLayoutStrategy
     231               0 :   if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::nowrap &&
     232               0 :       PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) {
     233               0 :     PresContext()->PresShell()->
     234               0 :       FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
     235                 :   }
     236                 :   // let the table frame decide what to do
     237               0 :   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     238               0 :   tableFrame->AttributeChangedFor(this, mContent, aAttribute);
     239               0 :   return NS_OK;
     240                 : }
     241                 : 
     242                 : /* virtual */ void
     243               0 : nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     244                 : {
     245               0 :   if (!aOldStyleContext) //avoid this on init
     246               0 :     return;
     247                 : 
     248               0 :   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     249               0 :   if (tableFrame->IsBorderCollapse() &&
     250               0 :       tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
     251                 :     PRInt32 colIndex, rowIndex;
     252               0 :     GetColIndex(colIndex);
     253               0 :     GetRowIndex(rowIndex);
     254                 :     // row span needs to be clamped as we do not create rows in the cellmap
     255                 :     // which do not have cells originating in them
     256               0 :     nsIntRect damageArea(colIndex, rowIndex, GetColSpan(),
     257               0 :       NS_MIN(GetRowSpan(), tableFrame->GetRowCount() - rowIndex));
     258               0 :     tableFrame->AddBCDamageArea(damageArea);
     259                 :   }
     260                 : }
     261                 : 
     262                 : 
     263                 : NS_IMETHODIMP
     264               0 : nsTableCellFrame::AppendFrames(ChildListID     aListID,
     265                 :                                nsFrameList&    aFrameList)
     266                 : {
     267               0 :   NS_PRECONDITION(false, "unsupported operation");
     268               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     269                 : }
     270                 : 
     271                 : NS_IMETHODIMP
     272               0 : nsTableCellFrame::InsertFrames(ChildListID     aListID,
     273                 :                                nsIFrame*       aPrevFrame,
     274                 :                                nsFrameList&    aFrameList)
     275                 : {
     276               0 :   NS_PRECONDITION(false, "unsupported operation");
     277               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     278                 : }
     279                 : 
     280                 : NS_IMETHODIMP
     281               0 : nsTableCellFrame::RemoveFrame(ChildListID     aListID,
     282                 :                               nsIFrame*       aOldFrame)
     283                 : {
     284               0 :   NS_PRECONDITION(false, "unsupported operation");
     285               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     286                 : }
     287                 : 
     288               0 : void nsTableCellFrame::SetColIndex(PRInt32 aColIndex)
     289                 : {
     290               0 :   mColIndex = aColIndex;
     291               0 : }
     292                 : 
     293                 : /* virtual */ nsMargin
     294               0 : nsTableCellFrame::GetUsedMargin() const
     295                 : {
     296               0 :   return nsMargin(0,0,0,0);
     297                 : }
     298                 : 
     299                 : //ASSURE DIFFERENT COLORS for selection
     300               0 : inline nscolor EnsureDifferentColors(nscolor colorA, nscolor colorB)
     301                 : {
     302               0 :     if (colorA == colorB)
     303                 :     {
     304                 :       nscolor res;
     305                 :       res = NS_RGB(NS_GET_R(colorA) ^ 0xff,
     306                 :                    NS_GET_G(colorA) ^ 0xff,
     307               0 :                    NS_GET_B(colorA) ^ 0xff);
     308               0 :       return res;
     309                 :     }
     310               0 :     return colorA;
     311                 : }
     312                 : 
     313                 : void
     314               0 : nsTableCellFrame::DecorateForSelection(nsRenderingContext& aRenderingContext,
     315                 :                                        nsPoint aPt)
     316                 : {
     317               0 :   NS_ASSERTION(IsSelected(), "Should only be called for selected cells");
     318                 :   PRInt16 displaySelection;
     319               0 :   nsPresContext* presContext = PresContext();
     320               0 :   displaySelection = DisplaySelection(presContext);
     321               0 :   if (displaySelection) {
     322                 :     nsRefPtr<nsFrameSelection> frameSelection =
     323               0 :       presContext->PresShell()->FrameSelection();
     324                 : 
     325               0 :     if (frameSelection->GetTableCellSelection()) {
     326                 :       nscolor       bordercolor;
     327               0 :       if (displaySelection == nsISelectionController::SELECTION_DISABLED) {
     328               0 :         bordercolor = NS_RGB(176,176,176);// disabled color
     329                 :       }
     330                 :       else {
     331                 :         bordercolor =
     332               0 :           LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectBackground);
     333                 :       }
     334               0 :       nscoord threePx = nsPresContext::CSSPixelsToAppUnits(3);
     335               0 :       if ((mRect.width > threePx) && (mRect.height > threePx))
     336                 :       {
     337                 :         //compare bordercolor to ((nsStyleColor *)myColor)->mBackgroundColor)
     338                 :         bordercolor = EnsureDifferentColors(bordercolor,
     339               0 :                                             GetStyleBackground()->mBackgroundColor);
     340                 :         nsRenderingContext::AutoPushTranslation
     341               0 :             translate(&aRenderingContext, aPt);
     342               0 :         nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
     343                 : 
     344               0 :         aRenderingContext.SetColor(bordercolor);
     345               0 :         aRenderingContext.DrawLine(onePixel, 0, mRect.width, 0);
     346               0 :         aRenderingContext.DrawLine(0, onePixel, 0, mRect.height);
     347               0 :         aRenderingContext.DrawLine(onePixel, mRect.height, mRect.width, mRect.height);
     348               0 :         aRenderingContext.DrawLine(mRect.width, onePixel, mRect.width, mRect.height);
     349                 :         //middle
     350                 :         aRenderingContext.DrawRect(onePixel, onePixel, mRect.width-onePixel,
     351               0 :                                    mRect.height-onePixel);
     352                 :         //shading
     353                 :         aRenderingContext.DrawLine(2*onePixel, mRect.height-2*onePixel,
     354               0 :                                    mRect.width-onePixel, mRect.height- (2*onePixel));
     355                 :         aRenderingContext.DrawLine(mRect.width - (2*onePixel), 2*onePixel,
     356               0 :                                    mRect.width - (2*onePixel), mRect.height-onePixel);
     357                 :       }
     358                 :     }
     359                 :   }
     360               0 : }
     361                 : 
     362                 : void
     363               0 : nsTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
     364                 :                                   const nsRect&        aDirtyRect,
     365                 :                                   nsPoint              aPt,
     366                 :                                   PRUint32             aFlags)
     367                 : {
     368               0 :   nsRect rect(aPt, GetSize());
     369                 :   nsCSSRendering::PaintBackground(PresContext(), aRenderingContext, this,
     370               0 :                                   aDirtyRect, rect, aFlags);
     371               0 : }
     372                 : 
     373                 : // Called by nsTablePainter
     374                 : void
     375               0 : nsTableCellFrame::PaintCellBackground(nsRenderingContext& aRenderingContext,
     376                 :                                       const nsRect& aDirtyRect, nsPoint aPt,
     377                 :                                       PRUint32 aFlags)
     378                 : {
     379               0 :   if (!GetStyleVisibility()->IsVisible())
     380               0 :     return;
     381                 : 
     382               0 :   PaintBackground(aRenderingContext, aDirtyRect, aPt, aFlags);
     383                 : }
     384                 : 
     385                 : class nsDisplayTableCellBackground : public nsDisplayTableItem {
     386                 : public:
     387               0 :   nsDisplayTableCellBackground(nsDisplayListBuilder* aBuilder,
     388                 :                                nsTableCellFrame* aFrame) :
     389               0 :     nsDisplayTableItem(aBuilder, aFrame) {
     390               0 :     MOZ_COUNT_CTOR(nsDisplayTableCellBackground);
     391               0 :   }
     392                 : #ifdef NS_BUILD_REFCNT_LOGGING
     393               0 :   virtual ~nsDisplayTableCellBackground() {
     394               0 :     MOZ_COUNT_DTOR(nsDisplayTableCellBackground);
     395               0 :   }
     396                 : #endif
     397                 : 
     398               0 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
     399                 :                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
     400               0 :     aOutFrames->AppendElement(mFrame);
     401               0 :   }
     402                 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     403                 :                      nsRenderingContext* aCtx);
     404                 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
     405                 : 
     406               0 :   NS_DISPLAY_DECL_NAME("TableCellBackground", TYPE_TABLE_CELL_BACKGROUND)
     407                 : };
     408                 : 
     409               0 : void nsDisplayTableCellBackground::Paint(nsDisplayListBuilder* aBuilder,
     410                 :                                          nsRenderingContext* aCtx)
     411                 : {
     412                 :   static_cast<nsTableCellFrame*>(mFrame)->
     413               0 :     PaintBackground(*aCtx, mVisibleRect, ToReferenceFrame(),
     414               0 :                     aBuilder->GetBackgroundPaintFlags());
     415               0 : }
     416                 : 
     417                 : nsRect
     418               0 : nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder)
     419                 : {
     420                 :   // revert from nsDisplayTableItem's implementation ... cell backgrounds
     421                 :   // don't overflow the cell
     422               0 :   return nsDisplayItem::GetBounds(aBuilder);
     423                 : }
     424                 : 
     425                 : static void
     426               0 : PaintTableCellSelection(nsIFrame* aFrame, nsRenderingContext* aCtx,
     427                 :                         const nsRect& aRect, nsPoint aPt)
     428                 : {
     429               0 :   static_cast<nsTableCellFrame*>(aFrame)->DecorateForSelection(*aCtx, aPt);
     430               0 : }
     431                 : 
     432                 : NS_IMETHODIMP
     433               0 : nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     434                 :                                    const nsRect&           aDirtyRect,
     435                 :                                    const nsDisplayListSet& aLists)
     436                 : {
     437               0 :   DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
     438               0 :   if (IsVisibleInSelection(aBuilder)) {
     439               0 :     nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     440               0 :     PRInt32 emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
     441               0 :                                 GetStyleTableBorder()->mEmptyCells
     442               0 :                                 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
     443                 :     // take account of 'empty-cells'
     444               0 :     if (GetStyleVisibility()->IsVisible() &&
     445                 :         (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
     446                 :     
     447                 :     
     448               0 :       bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
     449               0 :       if (!isRoot) {
     450               0 :         nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
     451               0 :         if (currentItem) {
     452               0 :           currentItem->UpdateForFrameBackground(this);
     453                 :         }
     454                 :       }
     455                 :     
     456                 :       // display outset box-shadows if we need to.
     457               0 :       bool hasBoxShadow = !!(GetStyleBorder()->mBoxShadow);
     458               0 :       if (hasBoxShadow) {
     459                 :         nsresult rv = aLists.BorderBackground()->AppendNewToTop(
     460               0 :             new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
     461               0 :         NS_ENSURE_SUCCESS(rv, rv);
     462                 :       }
     463                 :     
     464                 :       // display background if we need to.
     465               0 :       if (aBuilder->IsForEventDelivery() ||
     466               0 :           (((!tableFrame->IsBorderCollapse() || isRoot) &&
     467               0 :           (!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance)))) {
     468                 :         // The cell background was not painted by the nsTablePainter,
     469                 :         // so we need to do it. We have special background processing here
     470                 :         // so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline
     471                 :         nsDisplayTableItem* item =
     472               0 :           new (aBuilder) nsDisplayTableCellBackground(aBuilder, this);
     473               0 :         nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
     474               0 :         NS_ENSURE_SUCCESS(rv, rv);
     475               0 :         item->UpdateForFrameBackground(this);
     476                 :       }
     477                 :     
     478                 :       // display inset box-shadows if we need to.
     479               0 :       if (hasBoxShadow) {
     480                 :         nsresult rv = aLists.BorderBackground()->AppendNewToTop(
     481               0 :             new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
     482               0 :         NS_ENSURE_SUCCESS(rv, rv);
     483                 :       }
     484                 :     
     485                 :       // display borders if we need to
     486               0 :       if (!tableFrame->IsBorderCollapse() && HasBorder() &&
     487                 :           emptyCellStyle == NS_STYLE_TABLE_EMPTY_CELLS_SHOW) {
     488                 :         nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     489               0 :             nsDisplayBorder(aBuilder, this));
     490               0 :         NS_ENSURE_SUCCESS(rv, rv);
     491                 :       }
     492                 :     
     493                 :       // and display the selection border if we need to
     494               0 :       if (IsSelected()) {
     495                 :         nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     496                 :             nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
     497                 :                              "TableCellSelection",
     498               0 :                              nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
     499               0 :         NS_ENSURE_SUCCESS(rv, rv);
     500                 :       }
     501                 :     }
     502                 :     
     503                 :     // the 'empty-cells' property has no effect on 'outline'
     504               0 :     nsresult rv = DisplayOutline(aBuilder, aLists);
     505               0 :     NS_ENSURE_SUCCESS(rv, rv);
     506                 :   }
     507                 : 
     508                 :   // Push a null 'current table item' so that descendant tables can't
     509                 :   // accidentally mess with our table
     510               0 :   nsAutoPushCurrentTableItem pushTableItem;
     511               0 :   pushTableItem.Push(aBuilder, nsnull);
     512                 : 
     513               0 :   nsIFrame* kid = mFrames.FirstChild();
     514               0 :   NS_ASSERTION(kid && !kid->GetNextSibling(), "Table cells should have just one child");
     515                 :   // The child's background will go in our BorderBackground() list.
     516                 :   // This isn't a problem since it won't have a real background except for
     517                 :   // event handling. We do not call BuildDisplayListForNonBlockChildren
     518                 :   // because that/ would put the child's background in the Content() list
     519                 :   // which isn't right (e.g., would end up on top of our child floats for
     520                 :   // event handling).
     521               0 :   return BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
     522                 : }
     523                 : 
     524                 : PRIntn
     525               0 : nsTableCellFrame::GetSkipSides() const
     526                 : {
     527               0 :   PRIntn skip = 0;
     528               0 :   if (nsnull != GetPrevInFlow()) {
     529               0 :     skip |= 1 << NS_SIDE_TOP;
     530                 :   }
     531               0 :   if (nsnull != GetNextInFlow()) {
     532               0 :     skip |= 1 << NS_SIDE_BOTTOM;
     533                 :   }
     534               0 :   return skip;
     535                 : }
     536                 : 
     537                 : /* virtual */ nsMargin
     538               0 : nsTableCellFrame::GetBorderOverflow()
     539                 : {
     540               0 :   return nsMargin(0, 0, 0, 0);
     541                 : }
     542                 : 
     543                 : // Align the cell's child frame within the cell
     544                 : 
     545               0 : void nsTableCellFrame::VerticallyAlignChild(nscoord aMaxAscent)
     546                 : {
     547                 :   /* It's the 'border-collapse' on the table that matters */
     548               0 :   nsMargin borderPadding = GetUsedBorderAndPadding();
     549                 : 
     550               0 :   nscoord topInset = borderPadding.top;
     551               0 :   nscoord bottomInset = borderPadding.bottom;
     552                 : 
     553               0 :   PRUint8 verticalAlignFlags = GetVerticalAlign();
     554                 : 
     555               0 :   nscoord height = mRect.height;
     556               0 :   nsIFrame* firstKid = mFrames.FirstChild();
     557               0 :   NS_ASSERTION(firstKid, "Frame construction error, a table cell always has an inner cell frame");
     558               0 :   nsRect kidRect = firstKid->GetRect();
     559               0 :   nscoord childHeight = kidRect.height;
     560                 : 
     561                 :   // Vertically align the child
     562               0 :   nscoord kidYTop = 0;
     563               0 :   switch (verticalAlignFlags)
     564                 :   {
     565                 :     case NS_STYLE_VERTICAL_ALIGN_BASELINE:
     566                 :       // Align the baselines of the child frame with the baselines of
     567                 :       // other children in the same row which have 'vertical-align: baseline'
     568               0 :       kidYTop = topInset + aMaxAscent - GetCellBaseline();
     569               0 :     break;
     570                 : 
     571                 :     case NS_STYLE_VERTICAL_ALIGN_TOP:
     572                 :       // Align the top of the child frame with the top of the content area,
     573               0 :       kidYTop = topInset;
     574               0 :     break;
     575                 : 
     576                 :     case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
     577                 :       // Align the bottom of the child frame with the bottom of the content area,
     578               0 :       kidYTop = height - childHeight - bottomInset;
     579               0 :     break;
     580                 : 
     581                 :     default:
     582                 :     case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
     583                 :       // Align the middle of the child frame with the middle of the content area,
     584               0 :       kidYTop = (height - childHeight - bottomInset + topInset) / 2;
     585                 :   }
     586                 :   // if the content is larger than the cell height align from top
     587               0 :   kidYTop = NS_MAX(0, kidYTop);
     588                 : 
     589               0 :   if (kidYTop != kidRect.y) {
     590                 :     // Invalidate at the old position first
     591               0 :     firstKid->InvalidateFrameSubtree();
     592                 :   }
     593                 : 
     594               0 :   firstKid->SetPosition(nsPoint(kidRect.x, kidYTop));
     595               0 :   nsHTMLReflowMetrics desiredSize;
     596               0 :   desiredSize.width = mRect.width;
     597               0 :   desiredSize.height = mRect.height;
     598                 : 
     599               0 :   nsRect overflow(nsPoint(0,0), GetSize());
     600               0 :   overflow.Inflate(GetBorderOverflow());
     601               0 :   desiredSize.mOverflowAreas.SetAllTo(overflow);
     602               0 :   ConsiderChildOverflow(desiredSize.mOverflowAreas, firstKid);
     603               0 :   FinishAndStoreOverflow(&desiredSize);
     604               0 :   if (kidYTop != kidRect.y) {
     605                 :     // Make sure any child views are correctly positioned. We know the inner table
     606                 :     // cell won't have a view
     607               0 :     nsContainerFrame::PositionChildViews(firstKid);
     608                 : 
     609                 :     // Invalidate new overflow rect
     610               0 :     firstKid->InvalidateFrameSubtree();
     611                 :   }
     612               0 :   if (HasView()) {
     613                 :     nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this,
     614                 :                                                GetView(),
     615               0 :                                                desiredSize.VisualOverflow(), 0);
     616                 :   }
     617               0 : }
     618                 : 
     619                 : bool
     620               0 : nsTableCellFrame::UpdateOverflow()
     621                 : {
     622               0 :   nsRect bounds(nsPoint(0,0), GetSize());
     623               0 :   bounds.Inflate(GetBorderOverflow());
     624               0 :   nsOverflowAreas overflowAreas(bounds, bounds);
     625                 : 
     626               0 :   nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
     627                 : 
     628               0 :   return FinishAndStoreOverflow(overflowAreas, GetSize());
     629                 : }
     630                 : 
     631                 : // Per CSS 2.1, we map 'sub', 'super', 'text-top', 'text-bottom',
     632                 : // length, percentage, and calc() values to 'baseline'.
     633                 : PRUint8
     634               0 : nsTableCellFrame::GetVerticalAlign() const
     635                 : {
     636               0 :   const nsStyleCoord& verticalAlign = GetStyleTextReset()->mVerticalAlign;
     637               0 :   if (verticalAlign.GetUnit() == eStyleUnit_Enumerated) {
     638               0 :     PRUint8 value = verticalAlign.GetIntValue();
     639               0 :     if (value == NS_STYLE_VERTICAL_ALIGN_TOP ||
     640                 :         value == NS_STYLE_VERTICAL_ALIGN_MIDDLE ||
     641                 :         value == NS_STYLE_VERTICAL_ALIGN_BOTTOM) {
     642               0 :       return value;
     643                 :     }
     644                 :   }
     645               0 :   return NS_STYLE_VERTICAL_ALIGN_BASELINE;
     646                 : }
     647                 : 
     648                 : bool
     649               0 : nsTableCellFrame::CellHasVisibleContent(nscoord       height,
     650                 :                                         nsTableFrame* tableFrame,
     651                 :                                         nsIFrame*     kidFrame)
     652                 : {
     653                 :   // see  http://www.w3.org/TR/CSS21/tables.html#empty-cells
     654               0 :   if (height > 0)
     655               0 :     return true;
     656               0 :   if (tableFrame->IsBorderCollapse())
     657               0 :     return true;
     658               0 :   nsIFrame* innerFrame = kidFrame->GetFirstPrincipalChild();
     659               0 :   while(innerFrame) {
     660               0 :     nsIAtom* frameType = innerFrame->GetType();
     661               0 :     if (nsGkAtoms::textFrame == frameType) {
     662               0 :        nsTextFrame* textFrame = static_cast<nsTextFrame*>(innerFrame);
     663               0 :        if (textFrame->HasNoncollapsedCharacters())
     664               0 :          return true;
     665                 :     }
     666               0 :     else if (nsGkAtoms::placeholderFrame != frameType) {
     667               0 :       return true;
     668                 :     }
     669                 :     else {
     670               0 :       nsIFrame *floatFrame = nsLayoutUtils::GetFloatFromPlaceholder(innerFrame);
     671               0 :       if (floatFrame)
     672               0 :         return true;
     673                 :     }
     674               0 :     innerFrame = innerFrame->GetNextSibling();
     675                 :   }     
     676               0 :   return false;
     677                 : }
     678                 : 
     679                 : nscoord
     680               0 : nsTableCellFrame::GetCellBaseline() const
     681                 : {
     682                 :   // Ignore the position of the inner frame relative to the cell frame
     683                 :   // since we want the position as though the inner were top-aligned.
     684               0 :   nsIFrame *inner = mFrames.FirstChild();
     685               0 :   nscoord borderPadding = GetUsedBorderAndPadding().top;
     686                 :   nscoord result;
     687               0 :   if (nsLayoutUtils::GetFirstLineBaseline(inner, &result))
     688               0 :     return result + borderPadding;
     689               0 :   return inner->GetContentRect().YMost() - inner->GetPosition().y +
     690               0 :          borderPadding;
     691                 : }
     692                 : 
     693               0 : PRInt32 nsTableCellFrame::GetRowSpan()
     694                 : {
     695               0 :   PRInt32 rowSpan=1;
     696               0 :   nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
     697                 : 
     698                 :   // Don't look at the content's rowspan if we're a pseudo cell
     699               0 :   if (hc && !GetStyleContext()->GetPseudo()) {
     700               0 :     const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::rowspan);
     701                 :     // Note that we don't need to check the tag name, because only table cells
     702                 :     // and table headers parse the "rowspan" attribute into an integer.
     703               0 :     if (attr && attr->Type() == nsAttrValue::eInteger) {
     704               0 :        rowSpan = attr->GetIntegerValue();
     705                 :     }
     706                 :   }
     707               0 :   return rowSpan;
     708                 : }
     709                 : 
     710               0 : PRInt32 nsTableCellFrame::GetColSpan()
     711                 : {
     712               0 :   PRInt32 colSpan=1;
     713               0 :   nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
     714                 : 
     715                 :   // Don't look at the content's colspan if we're a pseudo cell
     716               0 :   if (hc && !GetStyleContext()->GetPseudo()) {
     717               0 :     const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::colspan);
     718                 :     // Note that we don't need to check the tag name, because only table cells
     719                 :     // and table headers parse the "colspan" attribute into an integer.
     720               0 :     if (attr && attr->Type() == nsAttrValue::eInteger) {
     721               0 :        colSpan = attr->GetIntegerValue();
     722                 :     }
     723                 :   }
     724               0 :   return colSpan;
     725                 : }
     726                 : 
     727                 : /* virtual */ nscoord
     728               0 : nsTableCellFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
     729                 : {
     730               0 :   nscoord result = 0;
     731               0 :   DISPLAY_MIN_WIDTH(this, result);
     732                 : 
     733               0 :   nsIFrame *inner = mFrames.FirstChild();
     734                 :   result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner,
     735               0 :                                                     nsLayoutUtils::MIN_WIDTH);
     736               0 :   return result;
     737                 : }
     738                 : 
     739                 : /* virtual */ nscoord
     740               0 : nsTableCellFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
     741                 : {
     742               0 :   nscoord result = 0;
     743               0 :   DISPLAY_PREF_WIDTH(this, result);
     744                 : 
     745               0 :   nsIFrame *inner = mFrames.FirstChild();
     746                 :   result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner,
     747               0 :                                                 nsLayoutUtils::PREF_WIDTH);
     748               0 :   return result;
     749                 : }
     750                 : 
     751                 : /* virtual */ nsIFrame::IntrinsicWidthOffsetData
     752               0 : nsTableCellFrame::IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext)
     753                 : {
     754                 :   IntrinsicWidthOffsetData result =
     755               0 :     nsContainerFrame::IntrinsicWidthOffsets(aRenderingContext);
     756                 : 
     757               0 :   result.hMargin = 0;
     758               0 :   result.hPctMargin = 0;
     759                 : 
     760               0 :   nsMargin border;
     761               0 :   GetBorderWidth(border);
     762               0 :   result.hBorder = border.LeftRight();
     763                 : 
     764                 :   return result;
     765                 : }
     766                 : 
     767                 : #ifdef DEBUG
     768                 : #define PROBABLY_TOO_LARGE 1000000
     769                 : static
     770               0 : void DebugCheckChildSize(nsIFrame*            aChild,
     771                 :                          nsHTMLReflowMetrics& aMet,
     772                 :                          nsSize&              aAvailSize)
     773                 : {
     774               0 :   if ((aMet.width < 0) || (aMet.width > PROBABLY_TOO_LARGE)) {
     775                 :     printf("WARNING: cell content %p has large width %d \n",
     776               0 :            static_cast<void*>(aChild), PRInt32(aMet.width));
     777                 :   }
     778               0 : }
     779                 : #endif
     780                 : 
     781                 : // the computed height for the cell, which descendants use for percent height calculations
     782                 : // it is the height (minus border, padding) of the cell's first in flow during its final
     783                 : // reflow without an unconstrained height.
     784                 : static nscoord
     785               0 : CalcUnpaginagedHeight(nsPresContext*        aPresContext,
     786                 :                       nsTableCellFrame&     aCellFrame,
     787                 :                       nsTableFrame&         aTableFrame,
     788                 :                       nscoord               aVerticalBorderPadding)
     789                 : {
     790               0 :   const nsTableCellFrame* firstCellInFlow   = (nsTableCellFrame*)aCellFrame.GetFirstInFlow();
     791               0 :   nsTableFrame*           firstTableInFlow  = (nsTableFrame*)aTableFrame.GetFirstInFlow();
     792                 :   nsTableRowFrame*        row
     793               0 :     = static_cast<nsTableRowFrame*>(firstCellInFlow->GetParent());
     794                 :   nsTableRowGroupFrame*   firstRGInFlow
     795               0 :     = static_cast<nsTableRowGroupFrame*>(row->GetParent());
     796                 : 
     797                 :   PRInt32 rowIndex;
     798               0 :   firstCellInFlow->GetRowIndex(rowIndex);
     799               0 :   PRInt32 rowSpan = aTableFrame.GetEffectiveRowSpan(*firstCellInFlow);
     800               0 :   nscoord cellSpacing = firstTableInFlow->GetCellSpacingX();
     801                 : 
     802               0 :   nscoord computedHeight = ((rowSpan - 1) * cellSpacing) - aVerticalBorderPadding;
     803                 :   PRInt32 rowX;
     804               0 :   for (row = firstRGInFlow->GetFirstRow(), rowX = 0; row; row = row->GetNextRow(), rowX++) {
     805               0 :     if (rowX > rowIndex + rowSpan - 1) {
     806               0 :       break;
     807                 :     }
     808               0 :     else if (rowX >= rowIndex) {
     809               0 :       computedHeight += row->GetUnpaginatedHeight(aPresContext);
     810                 :     }
     811                 :   }
     812               0 :   return computedHeight;
     813                 : }
     814                 : 
     815               0 : NS_METHOD nsTableCellFrame::Reflow(nsPresContext*           aPresContext,
     816                 :                                    nsHTMLReflowMetrics&     aDesiredSize,
     817                 :                                    const nsHTMLReflowState& aReflowState,
     818                 :                                    nsReflowStatus&          aStatus)
     819                 : {
     820               0 :   DO_GLOBAL_REFLOW_COUNT("nsTableCellFrame");
     821               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
     822                 : 
     823               0 :   if (aReflowState.mFlags.mSpecialHeightReflow) {
     824               0 :     GetFirstInFlow()->AddStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW);
     825                 :   }
     826                 : 
     827                 :   // see if a special height reflow needs to occur due to having a pct height
     828               0 :   nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
     829                 : 
     830               0 :   aStatus = NS_FRAME_COMPLETE;
     831               0 :   nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight);
     832                 : 
     833               0 :   nsMargin borderPadding = aReflowState.mComputedPadding;
     834               0 :   nsMargin border;
     835               0 :   GetBorderWidth(border);
     836               0 :   borderPadding += border;
     837                 : 
     838               0 :   nscoord topInset    = borderPadding.top;
     839               0 :   nscoord rightInset  = borderPadding.right;
     840               0 :   nscoord bottomInset = borderPadding.bottom;
     841               0 :   nscoord leftInset   = borderPadding.left;
     842                 : 
     843                 :   // reduce available space by insets, if we're in a constrained situation
     844               0 :   availSize.width -= leftInset + rightInset;
     845               0 :   if (NS_UNCONSTRAINEDSIZE != availSize.height)
     846               0 :     availSize.height -= topInset + bottomInset;
     847                 : 
     848                 :   // Try to reflow the child into the available space. It might not
     849                 :   // fit or might need continuing.
     850               0 :   if (availSize.height < 0)
     851               0 :     availSize.height = 1;
     852                 : 
     853               0 :   nsHTMLReflowMetrics kidSize(aDesiredSize.mFlags);
     854               0 :   kidSize.width = kidSize.height = 0;
     855               0 :   SetPriorAvailWidth(aReflowState.availableWidth);
     856               0 :   nsIFrame* firstKid = mFrames.FirstChild();
     857               0 :   NS_ASSERTION(firstKid, "Frame construction error, a table cell always has an inner cell frame");
     858               0 :   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     859                 : 
     860               0 :   if (aReflowState.mFlags.mSpecialHeightReflow) {
     861               0 :     const_cast<nsHTMLReflowState&>(aReflowState).SetComputedHeight(mRect.height - topInset - bottomInset);
     862               0 :     DISPLAY_REFLOW_CHANGE();
     863                 :   }
     864               0 :   else if (aPresContext->IsPaginated()) {
     865                 :     nscoord computedUnpaginatedHeight =
     866                 :       CalcUnpaginagedHeight(aPresContext, (nsTableCellFrame&)*this,
     867               0 :                             *tableFrame, topInset + bottomInset);
     868               0 :     if (computedUnpaginatedHeight > 0) {
     869               0 :       const_cast<nsHTMLReflowState&>(aReflowState).SetComputedHeight(computedUnpaginatedHeight);
     870               0 :       DISPLAY_REFLOW_CHANGE();
     871                 :     }
     872                 :   }
     873                 :   else {
     874               0 :     SetHasPctOverHeight(false);
     875                 :   }
     876                 : 
     877                 :   nsHTMLReflowState kidReflowState(aPresContext, aReflowState, firstKid,
     878               0 :                                    availSize);
     879                 : 
     880                 :   // Don't be a percent height observer if we're in the middle of
     881                 :   // special-height reflow, in case we get an accidental NotifyPercentHeight()
     882                 :   // call (which we shouldn't honor during special-height reflow)
     883               0 :   if (!aReflowState.mFlags.mSpecialHeightReflow) {
     884                 :     // mPercentHeightObserver is for children of cells in quirks mode,
     885                 :     // but only those than are tables in standards mode.  NeedsToObserve
     886                 :     // will determine how far this is propagated to descendants.
     887               0 :     kidReflowState.mPercentHeightObserver = this;
     888                 :   }
     889                 :   // Don't propagate special height reflow state to our kids
     890               0 :   kidReflowState.mFlags.mSpecialHeightReflow = false;
     891                 : 
     892               0 :   if (aReflowState.mFlags.mSpecialHeightReflow ||
     893               0 :       (GetFirstInFlow()->GetStateBits() & NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) {
     894                 :     // We need to force the kid to have mVResize set if we've had a
     895                 :     // special reflow in the past, since the non-special reflow needs to
     896                 :     // resize back to what it was without the special height reflow.
     897               0 :     kidReflowState.mFlags.mVResize = true;
     898                 :   }
     899                 : 
     900               0 :   nsPoint kidOrigin(leftInset, topInset);
     901               0 :   nsRect origRect = firstKid->GetRect();
     902               0 :   nsRect origVisualOverflow = firstKid->GetVisualOverflowRect();
     903               0 :   bool firstReflow = (firstKid->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
     904                 : 
     905                 :   ReflowChild(firstKid, aPresContext, kidSize, kidReflowState,
     906               0 :               kidOrigin.x, kidOrigin.y, NS_FRAME_INVALIDATE_ON_MOVE, aStatus);
     907               0 :   if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
     908                 :     // Don't pass OVERFLOW_INCOMPLETE through tables until they can actually handle it
     909                 :     //XXX should paginate overflow as overflow, but not in this patch (bug 379349)
     910               0 :     NS_FRAME_SET_INCOMPLETE(aStatus);
     911               0 :     printf("Set table cell incomplete %p\n", static_cast<void*>(this));
     912                 :   }
     913                 : 
     914                 :   // XXXbz is this invalidate actually needed, really?
     915               0 :   if (GetStateBits() & NS_FRAME_IS_DIRTY) {
     916               0 :     InvalidateFrameSubtree();
     917                 :   }
     918                 : 
     919                 : #ifdef NS_DEBUG
     920               0 :   DebugCheckChildSize(firstKid, kidSize, availSize);
     921                 : #endif
     922                 : 
     923                 :   // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode
     924                 :   // see testcase "emptyCells.html"
     925               0 :   nsIFrame* prevInFlow = GetPrevInFlow();
     926                 :   bool isEmpty;
     927               0 :   if (prevInFlow) {
     928               0 :     isEmpty = static_cast<nsTableCellFrame*>(prevInFlow)->GetContentEmpty();
     929                 :   } else {
     930               0 :     isEmpty = !CellHasVisibleContent(kidSize.height, tableFrame, firstKid);
     931                 :   }
     932               0 :   SetContentEmpty(isEmpty);
     933                 : 
     934                 :   // Place the child
     935                 :   FinishReflowChild(firstKid, aPresContext, &kidReflowState, kidSize,
     936               0 :                     kidOrigin.x, kidOrigin.y, 0);
     937                 : 
     938                 :   nsTableFrame::InvalidateFrame(firstKid, origRect, origVisualOverflow,
     939               0 :                                 firstReflow);
     940                 : 
     941                 :   // first, compute the height which can be set w/o being restricted by aMaxSize.height
     942               0 :   nscoord cellHeight = kidSize.height;
     943                 : 
     944               0 :   if (NS_UNCONSTRAINEDSIZE != cellHeight) {
     945               0 :     cellHeight += topInset + bottomInset;
     946                 :   }
     947                 : 
     948                 :   // next determine the cell's width
     949               0 :   nscoord cellWidth = kidSize.width;      // at this point, we've factored in the cell's style attributes
     950                 : 
     951                 :   // factor in border and padding
     952               0 :   if (NS_UNCONSTRAINEDSIZE != cellWidth) {
     953               0 :     cellWidth += leftInset + rightInset;
     954                 :   }
     955                 : 
     956                 :   // set the cell's desired size and max element size
     957               0 :   aDesiredSize.width   = cellWidth;
     958               0 :   aDesiredSize.height  = cellHeight;
     959                 : 
     960                 :   // the overflow area will be computed when the child will be vertically aligned
     961                 : 
     962               0 :   if (aReflowState.mFlags.mSpecialHeightReflow) {
     963               0 :     if (aDesiredSize.height > mRect.height) {
     964                 :       // set a bit indicating that the pct height contents exceeded
     965                 :       // the height that they could honor in the pass 2 reflow
     966               0 :       SetHasPctOverHeight(true);
     967                 :     }
     968               0 :     if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) {
     969               0 :       aDesiredSize.height = mRect.height;
     970                 :     }
     971                 :   }
     972                 : 
     973                 :   // If our parent is in initial reflow, it'll handle invalidating our
     974                 :   // entire overflow rect.
     975               0 :   if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     976               0 :     CheckInvalidateSizeChange(aDesiredSize);
     977                 :   }
     978                 : 
     979                 :   // remember the desired size for this reflow
     980               0 :   SetDesiredSize(aDesiredSize);
     981                 : 
     982               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
     983               0 :   return NS_OK;
     984                 : }
     985                 : 
     986                 : /* ----- global methods ----- */
     987                 : 
     988               0 : NS_QUERYFRAME_HEAD(nsTableCellFrame)
     989               0 :   NS_QUERYFRAME_ENTRY(nsTableCellFrame)
     990               0 :   NS_QUERYFRAME_ENTRY(nsITableCellLayout)
     991               0 :   NS_QUERYFRAME_ENTRY(nsIPercentHeightObserver)
     992               0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
     993                 : 
     994                 : #ifdef ACCESSIBILITY
     995                 : already_AddRefed<nsAccessible>
     996               0 : nsTableCellFrame::CreateAccessible()
     997                 : {
     998               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
     999               0 :   if (accService) {
    1000                 :     return accService->CreateHTMLTableCellAccessible(mContent,
    1001               0 :                                                      PresContext()->PresShell());
    1002                 :   }
    1003                 : 
    1004               0 :   return nsnull;
    1005                 : }
    1006                 : #endif
    1007                 : 
    1008                 : /* This is primarily for editor access via nsITableLayout */
    1009                 : NS_IMETHODIMP
    1010               0 : nsTableCellFrame::GetCellIndexes(PRInt32 &aRowIndex, PRInt32 &aColIndex)
    1011                 : {
    1012               0 :   nsresult res = GetRowIndex(aRowIndex);
    1013               0 :   if (NS_FAILED(res))
    1014                 :   {
    1015               0 :     aColIndex = 0;
    1016               0 :     return res;
    1017                 :   }
    1018               0 :   aColIndex = mColIndex;
    1019               0 :   return  NS_OK;
    1020                 : }
    1021                 : 
    1022                 : nsIFrame*
    1023               0 : NS_NewTableCellFrame(nsIPresShell*   aPresShell,
    1024                 :                      nsStyleContext* aContext,
    1025                 :                      bool            aIsBorderCollapse)
    1026                 : {
    1027               0 :   if (aIsBorderCollapse)
    1028               0 :     return new (aPresShell) nsBCTableCellFrame(aContext);
    1029                 :   else
    1030               0 :     return new (aPresShell) nsTableCellFrame(aContext);
    1031                 : }
    1032                 : 
    1033               0 : NS_IMPL_FRAMEARENA_HELPERS(nsBCTableCellFrame)
    1034                 : 
    1035                 : nsMargin*
    1036               0 : nsTableCellFrame::GetBorderWidth(nsMargin&  aBorder) const
    1037                 : {
    1038               0 :   aBorder = GetStyleBorder()->GetActualBorder();
    1039               0 :   return &aBorder;
    1040                 : }
    1041                 : 
    1042                 : nsIAtom*
    1043               0 : nsTableCellFrame::GetType() const
    1044                 : {
    1045               0 :   return nsGkAtoms::tableCellFrame;
    1046                 : }
    1047                 : 
    1048                 : #ifdef DEBUG
    1049                 : NS_IMETHODIMP
    1050               0 : nsTableCellFrame::GetFrameName(nsAString& aResult) const
    1051                 : {
    1052               0 :   return MakeFrameName(NS_LITERAL_STRING("TableCell"), aResult);
    1053                 : }
    1054                 : #endif
    1055                 : 
    1056                 : // nsBCTableCellFrame
    1057                 : 
    1058               0 : nsBCTableCellFrame::nsBCTableCellFrame(nsStyleContext* aContext)
    1059               0 : :nsTableCellFrame(aContext)
    1060                 : {
    1061               0 :   mTopBorder = mRightBorder = mBottomBorder = mLeftBorder = 0;
    1062               0 : }
    1063                 : 
    1064               0 : nsBCTableCellFrame::~nsBCTableCellFrame()
    1065                 : {
    1066               0 : }
    1067                 : 
    1068                 : nsIAtom*
    1069               0 : nsBCTableCellFrame::GetType() const
    1070                 : {
    1071               0 :   return nsGkAtoms::bcTableCellFrame;
    1072                 : }
    1073                 : 
    1074                 : /* virtual */ nsMargin
    1075               0 : nsBCTableCellFrame::GetUsedBorder() const
    1076                 : {
    1077               0 :   nsMargin result;
    1078               0 :   GetBorderWidth(result);
    1079                 :   return result;
    1080                 : }
    1081                 : 
    1082                 : /* virtual */ bool
    1083               0 : nsBCTableCellFrame::GetBorderRadii(nscoord aRadii[8]) const
    1084                 : {
    1085               0 :   NS_FOR_CSS_HALF_CORNERS(corner) {
    1086               0 :     aRadii[corner] = 0;
    1087                 :   }
    1088               0 :   return false;
    1089                 : }
    1090                 : 
    1091                 : #ifdef DEBUG
    1092                 : NS_IMETHODIMP
    1093               0 : nsBCTableCellFrame::GetFrameName(nsAString& aResult) const
    1094                 : {
    1095               0 :   return MakeFrameName(NS_LITERAL_STRING("BCTableCell"), aResult);
    1096                 : }
    1097                 : #endif
    1098                 : 
    1099                 : nsMargin*
    1100               0 : nsBCTableCellFrame::GetBorderWidth(nsMargin&  aBorder) const
    1101                 : {
    1102               0 :   PRInt32 aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
    1103               0 :   aBorder.top    = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips, mTopBorder);
    1104               0 :   aBorder.right  = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips, mRightBorder);
    1105               0 :   aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, mBottomBorder);
    1106               0 :   aBorder.left   = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mLeftBorder);
    1107               0 :   return &aBorder;
    1108                 : }
    1109                 : 
    1110                 : BCPixelSize
    1111               0 : nsBCTableCellFrame::GetBorderWidth(mozilla::css::Side aSide) const
    1112                 : {
    1113               0 :   switch(aSide) {
    1114                 :   case NS_SIDE_TOP:
    1115               0 :     return BC_BORDER_BOTTOM_HALF(mTopBorder);
    1116                 :   case NS_SIDE_RIGHT:
    1117               0 :     return BC_BORDER_LEFT_HALF(mRightBorder);
    1118                 :   case NS_SIDE_BOTTOM:
    1119               0 :     return BC_BORDER_TOP_HALF(mBottomBorder);
    1120                 :   default:
    1121               0 :     return BC_BORDER_RIGHT_HALF(mLeftBorder);
    1122                 :   }
    1123                 : }
    1124                 : 
    1125                 : void
    1126               0 : nsBCTableCellFrame::SetBorderWidth(mozilla::css::Side aSide,
    1127                 :                                    BCPixelSize aValue)
    1128                 : {
    1129               0 :   switch(aSide) {
    1130                 :   case NS_SIDE_TOP:
    1131               0 :     mTopBorder = aValue;
    1132               0 :     break;
    1133                 :   case NS_SIDE_RIGHT:
    1134               0 :     mRightBorder = aValue;
    1135               0 :     break;
    1136                 :   case NS_SIDE_BOTTOM:
    1137               0 :     mBottomBorder = aValue;
    1138               0 :     break;
    1139                 :   default:
    1140               0 :     mLeftBorder = aValue;
    1141                 :   }
    1142               0 : }
    1143                 : 
    1144                 : /* virtual */ nsMargin
    1145               0 : nsBCTableCellFrame::GetBorderOverflow()
    1146                 : {
    1147               0 :   nsMargin halfBorder;
    1148               0 :   PRInt32 p2t = nsPresContext::AppUnitsPerCSSPixel();
    1149               0 :   halfBorder.top = BC_BORDER_TOP_HALF_COORD(p2t, mTopBorder);
    1150               0 :   halfBorder.right = BC_BORDER_RIGHT_HALF_COORD(p2t, mRightBorder);
    1151               0 :   halfBorder.bottom = BC_BORDER_BOTTOM_HALF_COORD(p2t, mBottomBorder);
    1152               0 :   halfBorder.left = BC_BORDER_LEFT_HALF_COORD(p2t, mLeftBorder);
    1153                 :   return halfBorder;
    1154                 : }
    1155                 : 
    1156                 : 
    1157                 : void
    1158               0 : nsBCTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
    1159                 :                                     const nsRect&        aDirtyRect,
    1160                 :                                     nsPoint              aPt,
    1161                 :                                     PRUint32             aFlags)
    1162                 : {
    1163                 :   // make border-width reflect the half of the border-collapse
    1164                 :   // assigned border that's inside the cell
    1165               0 :   nsMargin borderWidth;
    1166               0 :   GetBorderWidth(borderWidth);
    1167                 : 
    1168               0 :   nsStyleBorder myBorder(*GetStyleBorder());
    1169                 :   // We're making an ephemeral stack copy here, so just copy this debug-only
    1170                 :   // member to prevent assertions.
    1171                 : #ifdef DEBUG
    1172               0 :   myBorder.mImageTracked = GetStyleBorder()->mImageTracked;
    1173                 : #endif
    1174                 : 
    1175               0 :   NS_FOR_CSS_SIDES(side) {
    1176               0 :     myBorder.SetBorderWidth(side, borderWidth.Side(side));
    1177                 :   }
    1178                 : 
    1179               0 :   nsRect rect(aPt, GetSize());
    1180                 :   // bypassing nsCSSRendering::PaintBackground is safe because this kind
    1181                 :   // of frame cannot be used for the root element
    1182                 :   nsCSSRendering::PaintBackgroundWithSC(PresContext(), aRenderingContext, this,
    1183                 :                                         aDirtyRect, rect,
    1184                 :                                         GetStyleContext(), myBorder,
    1185               0 :                                         aFlags, nsnull);
    1186                 : 
    1187                 : #ifdef DEBUG
    1188               0 :   myBorder.mImageTracked = false;
    1189                 : #endif
    1190               0 : }

Generated by: LCOV version 1.7