1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/tables/nsTableFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,947 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +#ifndef nsTableFrame_h__ 1.9 +#define nsTableFrame_h__ 1.10 + 1.11 +#include "mozilla/Attributes.h" 1.12 +#include "celldata.h" 1.13 +#include "nscore.h" 1.14 +#include "nsContainerFrame.h" 1.15 +#include "nsStyleCoord.h" 1.16 +#include "nsStyleConsts.h" 1.17 +#include "nsTableColFrame.h" 1.18 +#include "nsTableColGroupFrame.h" 1.19 +#include "nsCellMap.h" 1.20 +#include "nsGkAtoms.h" 1.21 +#include "nsDisplayList.h" 1.22 + 1.23 +class nsTableCellFrame; 1.24 +class nsTableCellMap; 1.25 +class nsTableColFrame; 1.26 +class nsColGroupFrame; 1.27 +class nsTableRowGroupFrame; 1.28 +class nsTableRowFrame; 1.29 +class nsTableColGroupFrame; 1.30 +class nsITableLayoutStrategy; 1.31 +class nsStyleContext; 1.32 + 1.33 +struct nsTableReflowState; 1.34 +struct nsStylePosition; 1.35 +struct BCPropertyData; 1.36 + 1.37 +static inline bool IS_TABLE_CELL(nsIAtom* frameType) { 1.38 + return nsGkAtoms::tableCellFrame == frameType || 1.39 + nsGkAtoms::bcTableCellFrame == frameType; 1.40 +} 1.41 + 1.42 +static inline bool FrameHasBorderOrBackground(nsIFrame* f) { 1.43 + return (f->StyleVisibility()->IsVisible() && 1.44 + (!f->StyleBackground()->IsTransparent() || 1.45 + f->StyleDisplay()->mAppearance || 1.46 + f->StyleBorder()->HasBorder())); 1.47 +} 1.48 + 1.49 +class nsDisplayTableItem : public nsDisplayItem 1.50 +{ 1.51 +public: 1.52 + nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : 1.53 + nsDisplayItem(aBuilder, aFrame), 1.54 + mPartHasFixedBackground(false) {} 1.55 + 1.56 + virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder, 1.57 + nsIFrame* aFrame) MOZ_OVERRIDE; 1.58 + // With collapsed borders, parts of the collapsed border can extend outside 1.59 + // the table part frames, so allow this display element to blow out to our 1.60 + // overflow rect. This is also useful for row frames that have spanning 1.61 + // cells extending outside them. 1.62 + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; 1.63 + 1.64 + void UpdateForFrameBackground(nsIFrame* aFrame); 1.65 + 1.66 +private: 1.67 + bool mPartHasFixedBackground; 1.68 +}; 1.69 + 1.70 +class nsAutoPushCurrentTableItem 1.71 +{ 1.72 +public: 1.73 + nsAutoPushCurrentTableItem() : mBuilder(nullptr) {} 1.74 + 1.75 + void Push(nsDisplayListBuilder* aBuilder, nsDisplayTableItem* aPushItem) 1.76 + { 1.77 + mBuilder = aBuilder; 1.78 + mOldCurrentItem = aBuilder->GetCurrentTableItem(); 1.79 + aBuilder->SetCurrentTableItem(aPushItem); 1.80 +#ifdef DEBUG 1.81 + mPushedItem = aPushItem; 1.82 +#endif 1.83 + } 1.84 + ~nsAutoPushCurrentTableItem() { 1.85 + if (!mBuilder) 1.86 + return; 1.87 +#ifdef DEBUG 1.88 + NS_ASSERTION(mBuilder->GetCurrentTableItem() == mPushedItem, 1.89 + "Someone messed with the current table item behind our back!"); 1.90 +#endif 1.91 + mBuilder->SetCurrentTableItem(mOldCurrentItem); 1.92 + } 1.93 + 1.94 +private: 1.95 + nsDisplayListBuilder* mBuilder; 1.96 + nsDisplayTableItem* mOldCurrentItem; 1.97 +#ifdef DEBUG 1.98 + nsDisplayTableItem* mPushedItem; 1.99 +#endif 1.100 +}; 1.101 + 1.102 +/* ============================================================================ */ 1.103 + 1.104 +/** 1.105 + * nsTableFrame maps the inner portion of a table (everything except captions.) 1.106 + * Used as a pseudo-frame within nsTableOuterFrame, it may also be used 1.107 + * stand-alone as the top-level frame. 1.108 + * 1.109 + * The principal child list contains row group frames. There is also an 1.110 + * additional child list, kColGroupList, which contains the col group frames. 1.111 + */ 1.112 +class nsTableFrame : public nsContainerFrame 1.113 +{ 1.114 +public: 1.115 + NS_DECL_FRAMEARENA_HELPERS 1.116 + 1.117 + static void DestroyPositionedTablePartArray(void* aPropertyValue); 1.118 + NS_DECLARE_FRAME_PROPERTY(PositionedTablePartArray, DestroyPositionedTablePartArray) 1.119 + 1.120 + /** nsTableOuterFrame has intimate knowledge of the inner table frame */ 1.121 + friend class nsTableOuterFrame; 1.122 + 1.123 + /** instantiate a new instance of nsTableRowFrame. 1.124 + * @param aPresShell the pres shell for this frame 1.125 + * 1.126 + * @return the frame that was created 1.127 + */ 1.128 + friend nsIFrame* NS_NewTableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); 1.129 + 1.130 + /** sets defaults for table-specific style. 1.131 + * @see nsIFrame::Init 1.132 + */ 1.133 + virtual void Init(nsIContent* aContent, 1.134 + nsIFrame* aParent, 1.135 + nsIFrame* aPrevInFlow) MOZ_OVERRIDE; 1.136 + 1.137 + static float GetTwipsToPixels(nsPresContext* aPresContext); 1.138 + 1.139 + // Return true if aParentReflowState.frame or any of its ancestors within 1.140 + // the containing table have non-auto height. (e.g. pct or fixed height) 1.141 + static bool AncestorsHaveStyleHeight(const nsHTMLReflowState& aParentReflowState); 1.142 + 1.143 + // See if a special height reflow will occur due to having a pct height when 1.144 + // the pct height basis may not yet be valid. 1.145 + static void CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState); 1.146 + 1.147 + // Notify the frame and its ancestors (up to the containing table) that a special 1.148 + // height reflow will occur. 1.149 + static void RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState); 1.150 + 1.151 + static void RePositionViews(nsIFrame* aFrame); 1.152 + 1.153 + static bool PageBreakAfter(nsIFrame* aSourceFrame, 1.154 + nsIFrame* aNextFrame); 1.155 + 1.156 + // Register a positioned table part with its nsTableFrame. These objects will 1.157 + // be visited by FixupPositionedTableParts after reflow is complete. (See that 1.158 + // function for more explanation.) Should be called during frame construction. 1.159 + static void RegisterPositionedTablePart(nsIFrame* aFrame); 1.160 + 1.161 + // Unregister a positioned table part with its nsTableFrame. 1.162 + static void UnregisterPositionedTablePart(nsIFrame* aFrame, 1.163 + nsIFrame* aDestructRoot); 1.164 + 1.165 + nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const; 1.166 + /* 1.167 + * Notification that aAttribute has changed for content inside a table (cell, row, etc) 1.168 + */ 1.169 + void AttributeChangedFor(nsIFrame* aFrame, 1.170 + nsIContent* aContent, 1.171 + nsIAtom* aAttribute); 1.172 + 1.173 + /** @see nsIFrame::DestroyFrom */ 1.174 + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; 1.175 + 1.176 + /** @see nsIFrame::DidSetStyleContext */ 1.177 + virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; 1.178 + 1.179 + virtual nsresult AppendFrames(ChildListID aListID, 1.180 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.181 + virtual nsresult InsertFrames(ChildListID aListID, 1.182 + nsIFrame* aPrevFrame, 1.183 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.184 + virtual nsresult RemoveFrame(ChildListID aListID, 1.185 + nsIFrame* aOldFrame) MOZ_OVERRIDE; 1.186 + 1.187 + virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE; 1.188 + virtual nsMargin GetUsedPadding() const MOZ_OVERRIDE; 1.189 + virtual nsMargin GetUsedMargin() const MOZ_OVERRIDE; 1.190 + 1.191 + // Get the offset from the border box to the area where the row groups fit 1.192 + nsMargin GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const; 1.193 + 1.194 + /** helper method to find the table parent of any table frame object */ 1.195 + static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame); 1.196 + 1.197 + /* Like GetTableFrame, but will return nullptr if we don't pass through 1.198 + * aMustPassThrough on the way to the table. 1.199 + */ 1.200 + static nsTableFrame* GetTableFramePassingThrough(nsIFrame* aMustPassThrough, 1.201 + nsIFrame* aSourceFrame); 1.202 + 1.203 + typedef void (* DisplayGenericTablePartTraversal) 1.204 + (nsDisplayListBuilder* aBuilder, nsFrame* aFrame, 1.205 + const nsRect& aDirtyRect, const nsDisplayListSet& aLists); 1.206 + static void GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, 1.207 + const nsRect& aDirtyRect, const nsDisplayListSet& aLists); 1.208 + 1.209 + /** 1.210 + * Helper method to handle display common to table frames, rowgroup frames 1.211 + * and row frames. It creates a background display item for handling events 1.212 + * if necessary, an outline display item if necessary, and displays 1.213 + * all the the frame's children. 1.214 + * @param aDisplayItem the display item created for this part, or null 1.215 + * if this part's border/background painting is delegated to an ancestor 1.216 + * @param aTraversal a function that gets called to traverse the table 1.217 + * part's child frames and add their display list items to a 1.218 + * display list set. 1.219 + */ 1.220 + static void DisplayGenericTablePart(nsDisplayListBuilder* aBuilder, 1.221 + nsFrame* aFrame, 1.222 + const nsRect& aDirtyRect, 1.223 + const nsDisplayListSet& aLists, 1.224 + nsDisplayTableItem* aDisplayItem, 1.225 + DisplayGenericTablePartTraversal aTraversal = GenericTraversal); 1.226 + 1.227 + // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame) 1.228 + // of type aChildType. 1.229 + static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame, 1.230 + nsIFrame* aPriorChildFrame, 1.231 + nsIAtom* aChildType); 1.232 + bool IsAutoHeight(); 1.233 + 1.234 + /** @return true if aDisplayType represents a rowgroup of any sort 1.235 + * (header, footer, or body) 1.236 + */ 1.237 + bool IsRowGroup(int32_t aDisplayType) const; 1.238 + 1.239 + /** Initialize the table frame with a set of children. 1.240 + * @see nsIFrame::SetInitialChildList 1.241 + */ 1.242 + virtual nsresult SetInitialChildList(ChildListID aListID, 1.243 + nsFrameList& aChildList) MOZ_OVERRIDE; 1.244 + 1.245 + virtual const nsFrameList& GetChildList(ChildListID aListID) const MOZ_OVERRIDE; 1.246 + virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE; 1.247 + 1.248 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.249 + const nsRect& aDirtyRect, 1.250 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.251 + 1.252 + /** 1.253 + * Paint the background of the table and its parts (column groups, 1.254 + * columns, row groups, rows, and cells), and the table border, and all 1.255 + * internal borders if border-collapse is on. 1.256 + */ 1.257 + void PaintTableBorderBackground(nsRenderingContext& aRenderingContext, 1.258 + const nsRect& aDirtyRect, 1.259 + nsPoint aPt, uint32_t aBGPaintFlags); 1.260 + 1.261 + /** 1.262 + * Determines if any table part has a background image that is currently not 1.263 + * decoded. Does not look into cell contents (ie only table parts). 1.264 + */ 1.265 + static bool AnyTablePartHasUndecodedBackgroundImage(nsIFrame* aStart, 1.266 + nsIFrame* aEnd); 1.267 + 1.268 + /** Get the outer half (i.e., the part outside the height and width of 1.269 + * the table) of the largest segment (?) of border-collapsed border on 1.270 + * the table on each side, or 0 for non border-collapsed tables. 1.271 + */ 1.272 + nsMargin GetOuterBCBorder() const; 1.273 + 1.274 + /** Same as above, but only if it's included from the border-box width 1.275 + * of the table. 1.276 + */ 1.277 + nsMargin GetIncludedOuterBCBorder() const; 1.278 + 1.279 + /** Same as above, but only if it's excluded from the border-box width 1.280 + * of the table. This is the area that leaks out into the margin 1.281 + * (or potentially past it, if there is no margin). 1.282 + */ 1.283 + nsMargin GetExcludedOuterBCBorder() const; 1.284 + 1.285 + /** 1.286 + * In quirks mode, the size of the table background is reduced 1.287 + * by the outer BC border. Compute the reduction needed. 1.288 + */ 1.289 + nsMargin GetDeflationForBackground(nsPresContext* aPresContext) const; 1.290 + 1.291 + /** Get width of table + colgroup + col collapse: elements that 1.292 + * continue along the length of the whole left side. 1.293 + * see nsTablePainter about continuous borders 1.294 + */ 1.295 + nscoord GetContinuousLeftBCBorderWidth() const; 1.296 + void SetContinuousLeftBCBorderWidth(nscoord aValue); 1.297 + 1.298 + friend class nsDelayedCalcBCBorders; 1.299 + 1.300 + void AddBCDamageArea(const nsIntRect& aValue); 1.301 + bool BCRecalcNeeded(nsStyleContext* aOldStyleContext, 1.302 + nsStyleContext* aNewStyleContext); 1.303 + void PaintBCBorders(nsRenderingContext& aRenderingContext, 1.304 + const nsRect& aDirtyRect); 1.305 + 1.306 + virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE; 1.307 + // For border-collapse tables, the caller must not add padding and 1.308 + // border to the results of these functions. 1.309 + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.310 + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.311 + virtual IntrinsicWidthOffsetData 1.312 + IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; 1.313 + 1.314 + virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, 1.315 + nsSize aCBSize, nscoord aAvailableWidth, 1.316 + nsSize aMargin, nsSize aBorder, nsSize aPadding, 1.317 + uint32_t aFlags) MOZ_OVERRIDE; 1.318 + virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext, 1.319 + nsSize aCBSize, nscoord aAvailableWidth, 1.320 + nsSize aMargin, nsSize aBorder, 1.321 + nsSize aPadding, bool aShrinkWrap) MOZ_OVERRIDE; 1.322 + /** 1.323 + * A copy of nsFrame::ShrinkWidthToFit that calls a different 1.324 + * GetPrefWidth, since tables have two different ones. 1.325 + */ 1.326 + nscoord TableShrinkWidthToFit(nsRenderingContext *aRenderingContext, 1.327 + nscoord aWidthInCB); 1.328 + 1.329 + // XXXldb REWRITE THIS COMMENT! 1.330 + /** inner tables are reflowed in two steps. 1.331 + * <pre> 1.332 + * if mFirstPassValid is false, this is our first time through since content was last changed 1.333 + * set pass to 1 1.334 + * do pass 1 1.335 + * get min/max info for all cells in an infinite space 1.336 + * do column balancing 1.337 + * set mFirstPassValid to true 1.338 + * do pass 2 1.339 + * use column widths to Reflow cells 1.340 + * </pre> 1.341 + * 1.342 + * @see nsIFrame::Reflow 1.343 + */ 1.344 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.345 + nsHTMLReflowMetrics& aDesiredSize, 1.346 + const nsHTMLReflowState& aReflowState, 1.347 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.348 + 1.349 + nsresult ReflowTable(nsHTMLReflowMetrics& aDesiredSize, 1.350 + const nsHTMLReflowState& aReflowState, 1.351 + nscoord aAvailHeight, 1.352 + nsIFrame*& aLastChildReflowed, 1.353 + nsReflowStatus& aStatus); 1.354 + 1.355 + nsFrameList& GetColGroups(); 1.356 + 1.357 + virtual nsIFrame* GetParentStyleContextFrame() const MOZ_OVERRIDE; 1.358 + 1.359 + /** 1.360 + * Get the "type" of the frame 1.361 + * 1.362 + * @see nsGkAtoms::tableFrame 1.363 + */ 1.364 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.365 + 1.366 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.367 + { 1.368 + if (aFlags & eSupportsCSSTransforms) { 1.369 + return false; 1.370 + } 1.371 + return nsContainerFrame::IsFrameOfType(aFlags); 1.372 + } 1.373 + 1.374 +#ifdef DEBUG_FRAME_DUMP 1.375 + /** @see nsIFrame::GetFrameName */ 1.376 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; 1.377 +#endif 1.378 + 1.379 + /** return the width of the column at aColIndex */ 1.380 + int32_t GetColumnWidth(int32_t aColIndex); 1.381 + 1.382 + /** helper to get the cell spacing X style value */ 1.383 + nscoord GetCellSpacingX(); 1.384 + 1.385 + /** helper to get the cell spacing Y style value */ 1.386 + nscoord GetCellSpacingY(); 1.387 + 1.388 + virtual nscoord GetBaseline() const MOZ_OVERRIDE; 1.389 + /** return the row span of a cell, taking into account row span magic at the bottom 1.390 + * of a table. The row span equals the number of rows spanned by aCell starting at 1.391 + * aStartRowIndex, and can be smaller if aStartRowIndex is greater than the row 1.392 + * index in which aCell originates. 1.393 + * 1.394 + * @param aStartRowIndex the cell 1.395 + * @param aCell the cell 1.396 + * 1.397 + * @return the row span, correcting for row spans that extend beyond the bottom 1.398 + * of the table. 1.399 + */ 1.400 + int32_t GetEffectiveRowSpan(int32_t aStartRowIndex, 1.401 + const nsTableCellFrame& aCell) const; 1.402 + int32_t GetEffectiveRowSpan(const nsTableCellFrame& aCell, 1.403 + nsCellMap* aCellMap = nullptr); 1.404 + 1.405 + /** return the col span of a cell, taking into account col span magic at the edge 1.406 + * of a table. 1.407 + * 1.408 + * @param aCell the cell 1.409 + * 1.410 + * @return the col span, correcting for col spans that extend beyond the edge 1.411 + * of the table. 1.412 + */ 1.413 + int32_t GetEffectiveColSpan(const nsTableCellFrame& aCell, 1.414 + nsCellMap* aCellMap = nullptr) const; 1.415 + 1.416 + /** indicate whether the row has more than one cell that either originates 1.417 + * or is spanned from the rows above 1.418 + */ 1.419 + bool HasMoreThanOneCell(int32_t aRowIndex) const; 1.420 + 1.421 + /** return the column frame associated with aColIndex 1.422 + * returns nullptr if the col frame has not yet been allocated, or if 1.423 + * aColIndex is out of range 1.424 + */ 1.425 + nsTableColFrame* GetColFrame(int32_t aColIndex) const; 1.426 + 1.427 + /** Insert a col frame reference into the colframe cache and adapt the cellmap 1.428 + * @param aColFrame - the column frame 1.429 + * @param aColIndex - index where the column should be inserted into the 1.430 + * colframe cache 1.431 + */ 1.432 + void InsertCol(nsTableColFrame& aColFrame, 1.433 + int32_t aColIndex); 1.434 + 1.435 + nsTableColGroupFrame* CreateAnonymousColGroupFrame(nsTableColGroupType aType); 1.436 + 1.437 + int32_t DestroyAnonymousColFrames(int32_t aNumFrames); 1.438 + 1.439 + // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our 1.440 + // last eColGroupAnonymousCell colgroup. If we have no such colgroup, then 1.441 + // create one. 1.442 + void AppendAnonymousColFrames(int32_t aNumColsToAdd); 1.443 + 1.444 + // Append aNumColsToAdd anonymous col frames of type aColType to 1.445 + // aColGroupFrame. If aAddToTable is true, also call AddColsToTable on the 1.446 + // new cols. 1.447 + void AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame, 1.448 + int32_t aNumColsToAdd, 1.449 + nsTableColType aColType, 1.450 + bool aAddToTable); 1.451 + 1.452 + void MatchCellMapToColCache(nsTableCellMap* aCellMap); 1.453 + /** empty the column frame cache */ 1.454 + void ClearColCache(); 1.455 + 1.456 + void DidResizeColumns(); 1.457 + 1.458 + void AppendCell(nsTableCellFrame& aCellFrame, 1.459 + int32_t aRowIndex); 1.460 + 1.461 + void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, 1.462 + int32_t aRowIndex, 1.463 + int32_t aColIndexBefore); 1.464 + 1.465 + void RemoveCell(nsTableCellFrame* aCellFrame, 1.466 + int32_t aRowIndex); 1.467 + 1.468 + void AppendRows(nsTableRowGroupFrame* aRowGroupFrame, 1.469 + int32_t aRowIndex, 1.470 + nsTArray<nsTableRowFrame*>& aRowFrames); 1.471 + 1.472 + int32_t InsertRows(nsTableRowGroupFrame* aRowGroupFrame, 1.473 + nsTArray<nsTableRowFrame*>& aFrames, 1.474 + int32_t aRowIndex, 1.475 + bool aConsiderSpans); 1.476 + 1.477 + void RemoveRows(nsTableRowFrame& aFirstRowFrame, 1.478 + int32_t aNumRowsToRemove, 1.479 + bool aConsiderSpans); 1.480 + 1.481 + /** Insert multiple rowgroups into the table cellmap handling 1.482 + * @param aRowGroups - iterator that iterates over the rowgroups to insert 1.483 + */ 1.484 + void InsertRowGroups(const nsFrameList::Slice& aRowGroups); 1.485 + 1.486 + void InsertColGroups(int32_t aStartColIndex, 1.487 + const nsFrameList::Slice& aColgroups); 1.488 + 1.489 + void RemoveCol(nsTableColGroupFrame* aColGroupFrame, 1.490 + int32_t aColIndex, 1.491 + bool aRemoveFromCache, 1.492 + bool aRemoveFromCellMap); 1.493 + 1.494 + bool ColumnHasCellSpacingBefore(int32_t aColIndex) const; 1.495 + 1.496 + bool HasPctCol() const; 1.497 + void SetHasPctCol(bool aValue); 1.498 + 1.499 + bool HasCellSpanningPctCol() const; 1.500 + void SetHasCellSpanningPctCol(bool aValue); 1.501 + 1.502 + /** 1.503 + * To be called on a frame by its parent after setting its size/position and 1.504 + * calling DidReflow (possibly via FinishReflowChild()). This can also be 1.505 + * used for child frames which are not being reflowed but did have their size 1.506 + * or position changed. 1.507 + * 1.508 + * @param aFrame The frame to invalidate 1.509 + * @param aOrigRect The original rect of aFrame (before the change). 1.510 + * @param aOrigVisualOverflow The original overflow rect of aFrame. 1.511 + * @param aIsFirstReflow True if the size/position change is due to the 1.512 + * first reflow of aFrame. 1.513 + */ 1.514 + static void InvalidateTableFrame(nsIFrame* aFrame, 1.515 + const nsRect& aOrigRect, 1.516 + const nsRect& aOrigVisualOverflow, 1.517 + bool aIsFirstReflow); 1.518 + 1.519 + virtual bool UpdateOverflow() MOZ_OVERRIDE; 1.520 + 1.521 +protected: 1.522 + 1.523 + /** protected constructor. 1.524 + * @see NewFrame 1.525 + */ 1.526 + nsTableFrame(nsStyleContext* aContext); 1.527 + 1.528 + /** destructor, responsible for mColumnLayoutData */ 1.529 + virtual ~nsTableFrame(); 1.530 + 1.531 + void InitChildReflowState(nsHTMLReflowState& aReflowState); 1.532 + 1.533 + virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; 1.534 + 1.535 +public: 1.536 + bool IsRowInserted() const; 1.537 + void SetRowInserted(bool aValue); 1.538 + 1.539 +protected: 1.540 + 1.541 + // A helper function to reflow a header or footer with unconstrained height 1.542 + // to see if it should be made repeatable and also to determine its desired 1.543 + // height. 1.544 + nsresult SetupHeaderFooterChild(const nsTableReflowState& aReflowState, 1.545 + nsTableRowGroupFrame* aFrame, 1.546 + nscoord* aDesiredHeight); 1.547 + 1.548 + nsresult ReflowChildren(nsTableReflowState& aReflowState, 1.549 + nsReflowStatus& aStatus, 1.550 + nsIFrame*& aLastChildReflowed, 1.551 + nsOverflowAreas& aOverflowAreas); 1.552 + 1.553 + // This calls the col group and column reflow methods, which do two things: 1.554 + // (1) set all the dimensions to 0 1.555 + // (2) notify the table about colgroups or columns with hidden visibility 1.556 + void ReflowColGroups(nsRenderingContext* aRenderingContext); 1.557 + 1.558 + /** return the width of the table taking into account visibility collapse 1.559 + * on columns and colgroups 1.560 + * @param aBorderPadding the border and padding of the table 1.561 + */ 1.562 + nscoord GetCollapsedWidth(nsMargin aBorderPadding); 1.563 + 1.564 + 1.565 + /** Adjust the table for visibility.collapse set on rowgroups, rows, 1.566 + * colgroups and cols 1.567 + * @param aDesiredSize the metrics of the table 1.568 + * @param aBorderPadding the border and padding of the table 1.569 + */ 1.570 + void AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize, 1.571 + nsMargin aBorderPadding); 1.572 + 1.573 + /** FixupPositionedTableParts is called at the end of table reflow to reflow 1.574 + * the absolutely positioned descendants of positioned table parts. This is 1.575 + * necessary because the dimensions of table parts may change after they've 1.576 + * been reflowed (e.g. in AdjustForCollapsingRowsCols). 1.577 + */ 1.578 + void FixupPositionedTableParts(nsPresContext* aPresContext, 1.579 + nsHTMLReflowMetrics& aDesiredSize, 1.580 + const nsHTMLReflowState& aReflowState); 1.581 + 1.582 + // Clears the list of positioned table parts. 1.583 + void ClearAllPositionedTableParts(); 1.584 + 1.585 + nsITableLayoutStrategy* LayoutStrategy() const { 1.586 + return static_cast<nsTableFrame*>(FirstInFlow())-> 1.587 + mTableLayoutStrategy; 1.588 + } 1.589 + 1.590 + // Helper for InsertFrames. 1.591 + void HomogenousInsertFrames(ChildListID aListID, 1.592 + nsIFrame* aPrevFrame, 1.593 + nsFrameList& aFrameList); 1.594 +private: 1.595 + /* Handle a row that got inserted during reflow. aNewHeight is the 1.596 + new height of the table after reflow. */ 1.597 + void ProcessRowInserted(nscoord aNewHeight); 1.598 + 1.599 + // WIDTH AND HEIGHT CALCULATION 1.600 + 1.601 +public: 1.602 + 1.603 + // calculate the computed height of aFrame including its border and padding given 1.604 + // its reflow state. 1.605 + nscoord CalcBorderBoxHeight(const nsHTMLReflowState& aReflowState); 1.606 + 1.607 +protected: 1.608 + 1.609 + // update the desired height of this table taking into account the current 1.610 + // reflow state, the table attributes and the content driven rowgroup heights 1.611 + // this function can change the overflow area 1.612 + void CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize); 1.613 + 1.614 + // The following is a helper for CalcDesiredHeight 1.615 + 1.616 + void DistributeHeightToRows(const nsHTMLReflowState& aReflowState, 1.617 + nscoord aAmount); 1.618 + 1.619 + void PlaceChild(nsTableReflowState& aReflowState, 1.620 + nsIFrame* aKidFrame, 1.621 + nsHTMLReflowMetrics& aKidDesiredSize, 1.622 + const nsRect& aOriginalKidRect, 1.623 + const nsRect& aOriginalKidVisualOverflow); 1.624 + void PlaceRepeatedFooter(nsTableReflowState& aReflowState, 1.625 + nsTableRowGroupFrame *aTfoot, 1.626 + nscoord aFooterHeight); 1.627 + 1.628 + nsIFrame* GetFirstBodyRowGroupFrame(); 1.629 +public: 1.630 + typedef nsAutoTArray<nsTableRowGroupFrame*, 8> RowGroupArray; 1.631 + /** 1.632 + * Push all our child frames from the aRowGroups array, in order, starting 1.633 + * from the frame at aPushFrom to the end of the array. The frames are put on 1.634 + * our overflow list or moved directly to our next-in-flow if one exists. 1.635 + */ 1.636 +protected: 1.637 + void PushChildren(const RowGroupArray& aRowGroups, int32_t aPushFrom); 1.638 + 1.639 +public: 1.640 + // put the children frames in the display order (e.g. thead before tbodies 1.641 + // before tfoot). This will handle calling GetRowGroupFrame() on the 1.642 + // children, and not append nulls, so the array is guaranteed to contain 1.643 + // nsTableRowGroupFrames. If there are multiple theads or tfoots, all but 1.644 + // the first one are treated as tbodies instead. 1.645 + 1.646 + void OrderRowGroups(RowGroupArray& aChildren, 1.647 + nsTableRowGroupFrame** aHead = nullptr, 1.648 + nsTableRowGroupFrame** aFoot = nullptr) const; 1.649 + 1.650 + // Return the thead, if any 1.651 + nsTableRowGroupFrame* GetTHead() const; 1.652 + 1.653 + // Return the tfoot, if any 1.654 + nsTableRowGroupFrame* GetTFoot() const; 1.655 + 1.656 + // Returns true if there are any cells above the row at 1.657 + // aRowIndex and spanning into the row at aRowIndex, the number of 1.658 + // effective columns limits the search up to that column 1.659 + bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols); 1.660 + 1.661 + // Returns true if there is a cell originating in aRowIndex 1.662 + // which spans into the next row, the number of effective 1.663 + // columns limits the search up to that column 1.664 + bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols); 1.665 + 1.666 +protected: 1.667 + 1.668 + bool HaveReflowedColGroups() const; 1.669 + void SetHaveReflowedColGroups(bool aValue); 1.670 + 1.671 +public: 1.672 + bool IsBorderCollapse() const; 1.673 + 1.674 + bool NeedToCalcBCBorders() const; 1.675 + void SetNeedToCalcBCBorders(bool aValue); 1.676 + 1.677 + bool NeedToCollapse() const; 1.678 + void SetNeedToCollapse(bool aValue); 1.679 + 1.680 + bool HasZeroColSpans() const; 1.681 + void SetHasZeroColSpans(bool aValue); 1.682 + 1.683 + bool NeedColSpanExpansion() const; 1.684 + void SetNeedColSpanExpansion(bool aValue); 1.685 + 1.686 + /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame 1.687 + * state bit, which implies that all descendants are dirty. The 1.688 + * GeometryDirty still implies that all the parts of the table are 1.689 + * dirty, but resizing optimizations should still apply to the 1.690 + * contents of the individual cells. 1.691 + */ 1.692 + void SetGeometryDirty() { mBits.mGeometryDirty = true; } 1.693 + void ClearGeometryDirty() { mBits.mGeometryDirty = false; } 1.694 + bool IsGeometryDirty() const { return mBits.mGeometryDirty; } 1.695 + 1.696 + /** Get the cell map for this table frame. It is not always mCellMap. 1.697 + * Only the firstInFlow has a legit cell map 1.698 + */ 1.699 + nsTableCellMap* GetCellMap() const; 1.700 + 1.701 + /** Iterate over the row groups and adjust the row indices of all rows 1.702 + * whose index is >= aRowIndex. 1.703 + * @param aRowIndex - start adjusting with this index 1.704 + * @param aAdjustment - shift the row index by this amount 1.705 + */ 1.706 + void AdjustRowIndices(int32_t aRowIndex, 1.707 + int32_t aAdjustment); 1.708 + 1.709 + /** Reset the rowindices of all rows as they might have changed due to 1.710 + * rowgroup reordering, exclude new row group frames that show in the 1.711 + * reordering but are not yet inserted into the cellmap 1.712 + * @param aRowGroupsToExclude - an iterator that will produce the row groups 1.713 + * to exclude. 1.714 + */ 1.715 + void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude); 1.716 + 1.717 + nsTArray<nsTableColFrame*>& GetColCache(); 1.718 + 1.719 + 1.720 +protected: 1.721 + 1.722 + void SetBorderCollapse(bool aValue); 1.723 + 1.724 + BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const; 1.725 + void SetFullBCDamageArea(); 1.726 + void CalcBCBorders(); 1.727 + 1.728 + void ExpandBCDamageArea(nsIntRect& aRect) const; 1.729 + 1.730 + void SetColumnDimensions(nscoord aHeight, 1.731 + const nsMargin& aReflowState); 1.732 + 1.733 + int32_t CollectRows(nsIFrame* aFrame, 1.734 + nsTArray<nsTableRowFrame*>& aCollection); 1.735 + 1.736 +public: /* ----- Cell Map public methods ----- */ 1.737 + 1.738 + int32_t GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame); 1.739 + 1.740 + /** returns the number of rows in this table. 1.741 + */ 1.742 + int32_t GetRowCount () const 1.743 + { 1.744 + return GetCellMap()->GetRowCount(); 1.745 + } 1.746 + 1.747 + /** returns the number of columns in this table after redundant columns have been removed 1.748 + */ 1.749 + int32_t GetEffectiveColCount() const; 1.750 + 1.751 + /* return the col count including dead cols */ 1.752 + int32_t GetColCount () const 1.753 + { 1.754 + return GetCellMap()->GetColCount(); 1.755 + } 1.756 + 1.757 + // return the last col index which isn't of type eColAnonymousCell 1.758 + int32_t GetIndexOfLastRealCol(); 1.759 + 1.760 + /** returns true if table-layout:auto */ 1.761 + bool IsAutoLayout(); 1.762 + 1.763 +public: 1.764 + 1.765 +#ifdef DEBUG 1.766 + void Dump(bool aDumpRows, 1.767 + bool aDumpCols, 1.768 + bool aDumpCellMap); 1.769 +#endif 1.770 + 1.771 +protected: 1.772 + /** 1.773 + * Helper method for RemoveFrame. 1.774 + */ 1.775 + void DoRemoveFrame(ChildListID aListID, nsIFrame* aOldFrame); 1.776 +#ifdef DEBUG 1.777 + void DumpRowGroup(nsIFrame* aChildFrame); 1.778 +#endif 1.779 + // DATA MEMBERS 1.780 + nsAutoTArray<nsTableColFrame*, 8> mColFrames; 1.781 + 1.782 + struct TableBits { 1.783 + uint32_t mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow 1.784 + uint32_t mHasPctCol:1; // does any cell or col have a pct width 1.785 + uint32_t mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width) 1.786 + uint32_t mIsBorderCollapse:1; // border collapsing model vs. separate model 1.787 + uint32_t mRowInserted:1; 1.788 + uint32_t mNeedToCalcBCBorders:1; 1.789 + uint32_t mGeometryDirty:1; 1.790 + uint32_t mLeftContBCBorder:8; 1.791 + uint32_t mNeedToCollapse:1; // rows, cols that have visibility:collapse need to be collapsed 1.792 + uint32_t mHasZeroColSpans:1; 1.793 + uint32_t mNeedColSpanExpansion:1; 1.794 + uint32_t mResizedColumns:1; // have we resized columns since last reflow? 1.795 + } mBits; 1.796 + 1.797 + nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells 1.798 + nsITableLayoutStrategy* mTableLayoutStrategy;// the layout strategy for this frame 1.799 + nsFrameList mColGroups; // the list of colgroup frames 1.800 +}; 1.801 + 1.802 + 1.803 +inline bool nsTableFrame::IsRowGroup(int32_t aDisplayType) const 1.804 +{ 1.805 + return bool((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aDisplayType) || 1.806 + (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aDisplayType) || 1.807 + (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == aDisplayType)); 1.808 +} 1.809 + 1.810 +inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue) 1.811 +{ 1.812 + mBits.mHaveReflowedColGroups = aValue; 1.813 +} 1.814 + 1.815 +inline bool nsTableFrame::HaveReflowedColGroups() const 1.816 +{ 1.817 + return (bool)mBits.mHaveReflowedColGroups; 1.818 +} 1.819 + 1.820 +inline bool nsTableFrame::HasPctCol() const 1.821 +{ 1.822 + return (bool)mBits.mHasPctCol; 1.823 +} 1.824 + 1.825 +inline void nsTableFrame::SetHasPctCol(bool aValue) 1.826 +{ 1.827 + mBits.mHasPctCol = (unsigned)aValue; 1.828 +} 1.829 + 1.830 +inline bool nsTableFrame::HasCellSpanningPctCol() const 1.831 +{ 1.832 + return (bool)mBits.mCellSpansPctCol; 1.833 +} 1.834 + 1.835 +inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue) 1.836 +{ 1.837 + mBits.mCellSpansPctCol = (unsigned)aValue; 1.838 +} 1.839 + 1.840 +inline bool nsTableFrame::IsRowInserted() const 1.841 +{ 1.842 + return (bool)mBits.mRowInserted; 1.843 +} 1.844 + 1.845 +inline void nsTableFrame::SetRowInserted(bool aValue) 1.846 +{ 1.847 + mBits.mRowInserted = (unsigned)aValue; 1.848 +} 1.849 + 1.850 +inline void nsTableFrame::SetNeedToCollapse(bool aValue) 1.851 +{ 1.852 + static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse = (unsigned)aValue; 1.853 +} 1.854 + 1.855 +inline bool nsTableFrame::NeedToCollapse() const 1.856 +{ 1.857 + return (bool) static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse; 1.858 +} 1.859 + 1.860 +inline void nsTableFrame::SetHasZeroColSpans(bool aValue) 1.861 +{ 1.862 + mBits.mHasZeroColSpans = (unsigned)aValue; 1.863 +} 1.864 + 1.865 +inline bool nsTableFrame::HasZeroColSpans() const 1.866 +{ 1.867 + return (bool)mBits.mHasZeroColSpans; 1.868 +} 1.869 + 1.870 +inline void nsTableFrame::SetNeedColSpanExpansion(bool aValue) 1.871 +{ 1.872 + mBits.mNeedColSpanExpansion = (unsigned)aValue; 1.873 +} 1.874 + 1.875 +inline bool nsTableFrame::NeedColSpanExpansion() const 1.876 +{ 1.877 + return (bool)mBits.mNeedColSpanExpansion; 1.878 +} 1.879 + 1.880 + 1.881 +inline nsFrameList& nsTableFrame::GetColGroups() 1.882 +{ 1.883 + return static_cast<nsTableFrame*>(FirstInFlow())->mColGroups; 1.884 +} 1.885 + 1.886 +inline nsTArray<nsTableColFrame*>& nsTableFrame::GetColCache() 1.887 +{ 1.888 + return mColFrames; 1.889 +} 1.890 + 1.891 +inline bool nsTableFrame::IsBorderCollapse() const 1.892 +{ 1.893 + return (bool)mBits.mIsBorderCollapse; 1.894 +} 1.895 + 1.896 +inline void nsTableFrame::SetBorderCollapse(bool aValue) 1.897 +{ 1.898 + mBits.mIsBorderCollapse = aValue; 1.899 +} 1.900 + 1.901 +inline bool nsTableFrame::NeedToCalcBCBorders() const 1.902 +{ 1.903 + return (bool)mBits.mNeedToCalcBCBorders; 1.904 +} 1.905 + 1.906 +inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue) 1.907 +{ 1.908 + mBits.mNeedToCalcBCBorders = (unsigned)aValue; 1.909 +} 1.910 + 1.911 +inline nscoord 1.912 +nsTableFrame::GetContinuousLeftBCBorderWidth() const 1.913 +{ 1.914 + int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); 1.915 + return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mBits.mLeftContBCBorder); 1.916 +} 1.917 + 1.918 +inline void nsTableFrame::SetContinuousLeftBCBorderWidth(nscoord aValue) 1.919 +{ 1.920 + mBits.mLeftContBCBorder = (unsigned) aValue; 1.921 +} 1.922 + 1.923 +class nsTableIterator 1.924 +{ 1.925 +public: 1.926 + nsTableIterator(nsIFrame& aSource); 1.927 + nsTableIterator(nsFrameList& aSource); 1.928 + nsIFrame* First(); 1.929 + nsIFrame* Next(); 1.930 + bool IsLeftToRight(); 1.931 + int32_t Count(); 1.932 + 1.933 +protected: 1.934 + void Init(nsIFrame* aFirstChild); 1.935 + bool mLeftToRight; 1.936 + nsIFrame* mFirstListChild; 1.937 + nsIFrame* mFirstChild; 1.938 + nsIFrame* mCurrentChild; 1.939 + int32_t mCount; 1.940 +}; 1.941 + 1.942 +#define ABORT0() \ 1.943 +{NS_ASSERTION(false, "CellIterator program error"); \ 1.944 +return;} 1.945 + 1.946 +#define ABORT1(aReturn) \ 1.947 +{NS_ASSERTION(false, "CellIterator program error"); \ 1.948 +return aReturn;} 1.949 + 1.950 +#endif