forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			575 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			575 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| #ifndef nsCellMap_h__
 | |
| #define nsCellMap_h__
 | |
| 
 | |
| #include "nscore.h"
 | |
| #include "celldata.h"
 | |
| #include "nsTArray.h"
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsAlgorithm.h"
 | |
| #include "nsRect.h"
 | |
| #include <algorithm>
 | |
| #include "TableArea.h"
 | |
| 
 | |
| #undef DEBUG_TABLE_CELLMAP
 | |
| 
 | |
| class nsTableCellFrame;
 | |
| class nsTableRowFrame;
 | |
| class nsTableRowGroupFrame;
 | |
| class nsTableFrame;
 | |
| class nsCellMap;
 | |
| class nsPresContext;
 | |
| class nsCellMapColumnIterator;
 | |
| 
 | |
| struct nsColInfo {
 | |
|   int32_t mNumCellsOrig;  // number of cells originating in the col
 | |
|   int32_t mNumCellsSpan;  // number of cells spanning into the col via colspans
 | |
|                           // (not rowspans)
 | |
| 
 | |
|   nsColInfo();
 | |
|   nsColInfo(int32_t aNumCellsOrig, int32_t aNumCellsSpan);
 | |
| };
 | |
| 
 | |
| struct BCInfo {
 | |
|   nsTArray<BCData> mIEndBorders;
 | |
|   nsTArray<BCData> mBEndBorders;
 | |
|   BCData mBEndIEndCorner;
 | |
| };
 | |
| 
 | |
| class nsTableCellMap {
 | |
|   typedef mozilla::TableArea TableArea;
 | |
| 
 | |
|  public:
 | |
|   nsTableCellMap(nsTableFrame& aTableFrame, bool aBorderCollapse);
 | |
| 
 | |
|   /** destructor
 | |
|    * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
 | |
|    */
 | |
|   ~nsTableCellMap();
 | |
| 
 | |
|   void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
 | |
| 
 | |
|   void InsertGroupCellMap(nsTableRowGroupFrame* aNewRowGroup,
 | |
|                           nsTableRowGroupFrame*& aPrevRowGroup);
 | |
| 
 | |
|   /**
 | |
|    * Get the nsCellMap for the given row group.  If aStartHint is non-null,
 | |
|    * will start looking with that cellmap and only fall back to starting at the
 | |
|    * beginning of the list if that doesn't find us the right nsCellMap.
 | |
|    * Otherwise, just start at the beginning.
 | |
|    *
 | |
|    * aRowGroup must not be null.
 | |
|    */
 | |
|   nsCellMap* GetMapFor(const nsTableRowGroupFrame* aRowGroup,
 | |
|                        nsCellMap* aStartHint) const;
 | |
| 
 | |
|   /** synchronize the cellmaps with the rowgroups again **/
 | |
|   void Synchronize(nsTableFrame* aTableFrame);
 | |
| 
 | |
|   nsTableCellFrame* GetCellFrame(int32_t aRowIndex, int32_t aColIndex,
 | |
|                                  CellData& aData, bool aUseRowIfOverlap) const;
 | |
| 
 | |
|   /** return the CellData for the cell at (aRowIndex, aColIndex) */
 | |
|   CellData* GetDataAt(int32_t aRowIndex, int32_t aColIndex) const;
 | |
| 
 | |
|   // this function creates a col if needed
 | |
|   nsColInfo* GetColInfoAt(int32_t aColIndex);
 | |
| 
 | |
|   /** append the cellFrame at the end of the row at aRowIndex and return the col
 | |
|    * index
 | |
|    */
 | |
|   CellData* AppendCell(nsTableCellFrame& aCellFrame, int32_t aRowIndex,
 | |
|                        bool aRebuildIfNecessary, TableArea& aDamageArea);
 | |
| 
 | |
|   void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, int32_t aRowIndex,
 | |
|                    int32_t aColIndexBefore, TableArea& aDamageArea);
 | |
| 
 | |
|   void RemoveCell(nsTableCellFrame* aCellFrame, int32_t aRowIndex,
 | |
|                   TableArea& aDamageArea);
 | |
|   /** Remove the previously gathered column information */
 | |
|   void ClearCols();
 | |
|   void InsertRows(nsTableRowGroupFrame* aRowGroup,
 | |
|                   nsTArray<nsTableRowFrame*>& aRows, int32_t aFirstRowIndex,
 | |
|                   bool aConsiderSpans, TableArea& aDamageArea);
 | |
| 
 | |
|   void RemoveRows(int32_t aFirstRowIndex, int32_t aNumRowsToRemove,
 | |
|                   bool aConsiderSpans, TableArea& aDamageArea);
 | |
| 
 | |
|   int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const;
 | |
|   int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const;
 | |
| 
 | |
|   /** indicate whether the row has more than one cell that either originates
 | |
|    * or is spanned from the rows above
 | |
|    */
 | |
|   bool HasMoreThanOneCell(int32_t aRowIndex) const;
 | |
| 
 | |
|   int32_t GetEffectiveRowSpan(int32_t aRowIndex, int32_t aColIndex) const;
 | |
|   int32_t GetEffectiveColSpan(int32_t aRowIndex, int32_t aColIndex) const;
 | |
| 
 | |
|   /** return the total number of columns in the table represented by this
 | |
|    * CellMap */
 | |
|   int32_t GetColCount() const;
 | |
| 
 | |
|   /** return the actual number of rows in the table represented by this CellMap
 | |
|    */
 | |
|   int32_t GetRowCount() const;
 | |
| 
 | |
|   nsTableCellFrame* GetCellInfoAt(int32_t aRowX, int32_t aColX,
 | |
|                                   bool* aOriginates = nullptr,
 | |
|                                   int32_t* aColSpan = nullptr) const;
 | |
| 
 | |
|   /**
 | |
|    * Returns the index at the given row and column coordinates.
 | |
|    *
 | |
|    * @see  nsITableLayout::GetIndexByRowAndColumn()
 | |
|    *
 | |
|    * @param aRow     [in] the row coordinate
 | |
|    * @param aColumn  [in] the column coordinate
 | |
|    * @returns             the index for the cell
 | |
|    */
 | |
|   int32_t GetIndexByRowAndColumn(int32_t aRow, int32_t aColumn) const;
 | |
| 
 | |
|   /**
 | |
|    * Retrieves the row and column coordinates for the given index.
 | |
|    *
 | |
|    * @see  nsITableLayout::GetRowAndColumnByIndex()
 | |
|    *
 | |
|    * @param aIndex  [in] the index for which coordinates are to be retrieved
 | |
|    * @param aRow    [out] the row coordinate to be returned
 | |
|    * @param aColumn [out] the column coordinate to be returned
 | |
|    */
 | |
|   void GetRowAndColumnByIndex(int32_t aIndex, int32_t* aRow,
 | |
|                               int32_t* aColumn) const;
 | |
| 
 | |
|   void AddColsAtEnd(uint32_t aNumCols);
 | |
|   void RemoveColsAtEnd();
 | |
| 
 | |
|   bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols) const;
 | |
|   bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) const;
 | |
|   void RebuildConsideringCells(nsCellMap* aCellMap,
 | |
|                                nsTArray<nsTableCellFrame*>* aCellFrames,
 | |
|                                int32_t aRowIndex, int32_t aColIndex,
 | |
|                                bool aInsert, TableArea& aDamageArea);
 | |
| 
 | |
|  protected:
 | |
|   /**
 | |
|    * Rebuild due to rows being inserted or deleted with cells spanning
 | |
|    * into or out of the rows.  This function can only handle insertion
 | |
|    * or deletion but NOT both.  So either aRowsToInsert must be null
 | |
|    * or aNumRowsToRemove must be 0.
 | |
|    *
 | |
|    * // XXXbz are both allowed to happen?  That'd be a no-op...
 | |
|    */
 | |
|   void RebuildConsideringRows(nsCellMap* aCellMap, int32_t aStartRowIndex,
 | |
|                               nsTArray<nsTableRowFrame*>* aRowsToInsert,
 | |
|                               int32_t aNumRowsToRemove, TableArea& aDamageArea);
 | |
| 
 | |
|  public:
 | |
|   void ResetBStartStart(mozilla::LogicalSide aSide, nsCellMap& aCellMap,
 | |
|                         uint32_t aRowGroupStart, uint32_t aYPos,
 | |
|                         uint32_t aXPos);
 | |
| 
 | |
|   void SetBCBorderEdge(mozilla::LogicalSide aEdge, nsCellMap& aCellMap,
 | |
|                        uint32_t aCellMapStart, uint32_t aYPos, uint32_t aXPos,
 | |
|                        uint32_t aLength, BCBorderOwner aOwner, nscoord aSize,
 | |
|                        bool aChanged);
 | |
| 
 | |
|   void SetBCBorderCorner(mozilla::LogicalCorner aCorner, nsCellMap& aCellMap,
 | |
|                          uint32_t aCellMapStart, uint32_t aYPos, uint32_t aXPos,
 | |
|                          mozilla::LogicalSide aOwner, nscoord aSubSize,
 | |
|                          bool aBevel, bool aIsBottomRight = false);
 | |
| 
 | |
|   /** dump a representation of the cell map to stdout for debugging */
 | |
| #ifdef DEBUG
 | |
|   void Dump(char* aString = nullptr) const;
 | |
| #endif
 | |
| 
 | |
|  protected:
 | |
|   BCData* GetIEndMostBorder(int32_t aRowIndex);
 | |
|   BCData* GetBEndMostBorder(int32_t aColIndex);
 | |
| 
 | |
|   friend class nsCellMap;
 | |
|   friend class BCMapCellIterator;
 | |
|   friend class BCPaintBorderIterator;
 | |
|   friend class nsCellMapColumnIterator;
 | |
| 
 | |
|   /** Insert a row group cellmap after aPrevMap, if aPrefMap is null insert it
 | |
|    * at the beginning, the ordering of the cellmap corresponds to the ordering
 | |
|    * of rowgroups once OrderRowGroups has been called
 | |
|    */
 | |
|   void InsertGroupCellMap(nsCellMap* aPrevMap, nsCellMap& aNewMap);
 | |
|   void DeleteIEndBEndBorders();
 | |
| 
 | |
|   nsTableFrame& mTableFrame;
 | |
|   AutoTArray<nsColInfo, 8> mCols;
 | |
|   nsCellMap* mFirstMap;
 | |
|   // border collapsing info
 | |
|   BCInfo* mBCInfo;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * It maintains an Rows x Columns grid onto which the cells of the table are
 | |
|  * mapped. This makes processing of rowspan and colspan attributes much easier.
 | |
|  * Each cell is represented by a CellData object.
 | |
|  *
 | |
|  * @see CellData
 | |
|  * @see nsTableFrame::AddCellToMap
 | |
|  * @see nsTableFrame::GrowCellMap
 | |
|  * @see nsTableFrame::BuildCellIntoMap
 | |
|  *
 | |
|  * mRows is an array of rows.  Each row is an array of cells.  a cell
 | |
|  * can be null.
 | |
|  */
 | |
| class nsCellMap {
 | |
|   typedef mozilla::TableArea TableArea;
 | |
| 
 | |
|  public:
 | |
|   /** constructor
 | |
|    * @param aRowGroupFrame the row group frame this is a cellmap for
 | |
|    * @param aIsBC whether the table is doing border-collapse
 | |
|    */
 | |
|   nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, bool aIsBC);
 | |
| 
 | |
|   /** destructor
 | |
|    * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
 | |
|    */
 | |
|   ~nsCellMap();
 | |
| 
 | |
|   static void Init();
 | |
|   static void Shutdown();
 | |
| 
 | |
|   nsCellMap* GetNextSibling() const;
 | |
|   void SetNextSibling(nsCellMap* aSibling);
 | |
| 
 | |
|   nsTableRowGroupFrame* GetRowGroup() const;
 | |
| 
 | |
|   nsTableCellFrame* GetCellFrame(int32_t aRowIndex, int32_t aColIndex,
 | |
|                                  CellData& aData,
 | |
|                                  bool aUseRowSpanIfOverlap) const;
 | |
| 
 | |
|   /**
 | |
|    * Returns highest cell index within the cell map.
 | |
|    *
 | |
|    * @param  aColCount  [in] the number of columns in the table
 | |
|    */
 | |
|   int32_t GetHighestIndex(int32_t aColCount);
 | |
| 
 | |
|   /**
 | |
|    * Returns the index of the given row and column coordinates.
 | |
|    *
 | |
|    * @see  nsITableLayout::GetIndexByRowAndColumn()
 | |
|    *
 | |
|    * @param aColCount    [in] the number of columns in the table
 | |
|    * @param aRow         [in] the row coordinate
 | |
|    * @param aColumn      [in] the column coordinate
 | |
|    */
 | |
|   int32_t GetIndexByRowAndColumn(int32_t aColCount, int32_t aRow,
 | |
|                                  int32_t aColumn) const;
 | |
| 
 | |
|   /**
 | |
|    * Get the row and column coordinates at the given index.
 | |
|    *
 | |
|    * @see  nsITableLayout::GetRowAndColumnByIndex()
 | |
|    *
 | |
|    * @param aColCount  [in] the number of columns in the table
 | |
|    * @param aIndex     [in] the index for which coordinates are to be retrieved
 | |
|    * @param aRow       [out] the row coordinate to be returned
 | |
|    * @param aColumn    [out] the column coordinate to be returned
 | |
|    */
 | |
|   void GetRowAndColumnByIndex(int32_t aColCount, int32_t aIndex, int32_t* aRow,
 | |
|                               int32_t* aColumn) const;
 | |
| 
 | |
|   /** append the cellFrame at an empty or dead cell or finally at the end of
 | |
|    * the row at aRowIndex and return a pointer to the celldata entry in the
 | |
|    * cellmap
 | |
|    *
 | |
|    * @param aMap               - reference to the table cell map
 | |
|    * @param aCellFrame         - a pointer to the cellframe which will be
 | |
|    *                             appended to the row
 | |
|    * @param aRowIndex          - to this row the celldata entry will be added
 | |
|    * @param aRebuildIfNecessay - if a cell spans into a row below it might be
 | |
|    *                             necesserary to rebuild the cellmap as this
 | |
|    *                             rowspan might overlap another cell.
 | |
|    * @param aDamageArea        - area in cellmap coordinates which have been
 | |
|    *                             updated.
 | |
|    * @param aColToBeginSearch  - if not null contains the column number where
 | |
|    *                             the search for a empty or dead cell in the
 | |
|    *                             row should start
 | |
|    * @return                   - a pointer to the celldata entry inserted into
 | |
|    *                             the cellmap
 | |
|    */
 | |
|   CellData* AppendCell(nsTableCellMap& aMap, nsTableCellFrame* aCellFrame,
 | |
|                        int32_t aRowIndex, bool aRebuildIfNecessary,
 | |
|                        int32_t aRgFirstRowIndex, TableArea& aDamageArea,
 | |
|                        int32_t* aBeginSearchAtCol = nullptr);
 | |
| 
 | |
|   void InsertCells(nsTableCellMap& aMap,
 | |
|                    nsTArray<nsTableCellFrame*>& aCellFrames, int32_t aRowIndex,
 | |
|                    int32_t aColIndexBefore, int32_t aRgFirstRowIndex,
 | |
|                    TableArea& aDamageArea);
 | |
| 
 | |
|   void RemoveCell(nsTableCellMap& aMap, nsTableCellFrame* aCellFrame,
 | |
|                   int32_t aRowIndex, int32_t aRgFirstRowIndex,
 | |
|                   TableArea& aDamageArea);
 | |
| 
 | |
|   void InsertRows(nsTableCellMap& aMap, nsTArray<nsTableRowFrame*>& aRows,
 | |
|                   int32_t aFirstRowIndex, bool aConsiderSpans,
 | |
|                   int32_t aRgFirstRowIndex, TableArea& aDamageArea);
 | |
| 
 | |
|   void RemoveRows(nsTableCellMap& aMap, int32_t aFirstRowIndex,
 | |
|                   int32_t aNumRowsToRemove, bool aConsiderSpans,
 | |
|                   int32_t aRgFirstRowIndex, TableArea& aDamageArea);
 | |
| 
 | |
|   int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const;
 | |
|   int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const;
 | |
| 
 | |
|   /** return the number of rows in the table represented by this CellMap */
 | |
|   int32_t GetRowCount(bool aConsiderDeadRowSpanRows = false) const;
 | |
| 
 | |
|   nsTableCellFrame* GetCellInfoAt(const nsTableCellMap& aMap, int32_t aRowX,
 | |
|                                   int32_t aColX, bool* aOriginates = nullptr,
 | |
|                                   int32_t* aColSpan = nullptr) const;
 | |
| 
 | |
|   bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols) const;
 | |
| 
 | |
|   bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) const;
 | |
| 
 | |
|   /** indicate whether the row has more than one cell that either originates
 | |
|    * or is spanned from the rows above
 | |
|    */
 | |
|   bool HasMoreThanOneCell(int32_t aRowIndex) const;
 | |
| 
 | |
|   /* Get the rowspan for a cell starting at aRowIndex and aColIndex.
 | |
|    * If aGetEffective is true the size will not exceed the last content based
 | |
|    * row. Cells can have a specified rowspan that extends below the last
 | |
|    * content based row. This is legitimate considering incr. reflow where the
 | |
|    * content rows will arive later.
 | |
|    */
 | |
|   int32_t GetRowSpan(int32_t aRowIndex, int32_t aColIndex,
 | |
|                      bool aGetEffective) const;
 | |
| 
 | |
|   int32_t GetEffectiveColSpan(const nsTableCellMap& aMap, int32_t aRowIndex,
 | |
|                               int32_t aColIndex) const;
 | |
| 
 | |
|   typedef nsTArray<CellData*> CellDataArray;
 | |
| 
 | |
|   /** dump a representation of the cell map to stdout for debugging */
 | |
| #ifdef DEBUG
 | |
|   void Dump(bool aIsBorderCollapse) const;
 | |
| #endif
 | |
| 
 | |
|  protected:
 | |
|   friend class nsTableCellMap;
 | |
|   friend class BCMapCellIterator;
 | |
|   friend class BCPaintBorderIterator;
 | |
|   friend class nsTableFrame;
 | |
|   friend class nsCellMapColumnIterator;
 | |
| 
 | |
|   /**
 | |
|    * Increase the number of rows in this cellmap by aNumRows.  Put the
 | |
|    * new rows at aRowIndex.  If aRowIndex is -1, put them at the end.
 | |
|    */
 | |
|   bool Grow(nsTableCellMap& aMap, int32_t aNumRows, int32_t aRowIndex = -1);
 | |
| 
 | |
|   void GrowRow(CellDataArray& aRow, int32_t aNumCols);
 | |
| 
 | |
|   /** assign aCellData to the cell at (aRow,aColumn) */
 | |
|   void SetDataAt(nsTableCellMap& aMap, CellData& aCellData,
 | |
|                  int32_t aMapRowIndex, int32_t aColIndex);
 | |
| 
 | |
|   CellData* GetDataAt(int32_t aMapRowIndex, int32_t aColIndex) const;
 | |
| 
 | |
|   int32_t GetNumCellsIn(int32_t aColIndex) const;
 | |
| 
 | |
|   void ExpandWithRows(nsTableCellMap& aMap,
 | |
|                       nsTArray<nsTableRowFrame*>& aRowFrames,
 | |
|                       int32_t aStartRowIndex, int32_t aRgFirstRowIndex,
 | |
|                       TableArea& aDamageArea);
 | |
| 
 | |
|   void ExpandWithCells(nsTableCellMap& aMap,
 | |
|                        nsTArray<nsTableCellFrame*>& aCellFrames,
 | |
|                        int32_t aRowIndex, int32_t aColIndex, int32_t aRowSpan,
 | |
|                        bool aRowSpanIsZero, int32_t aRgFirstRowIndex,
 | |
|                        TableArea& aDamageArea);
 | |
| 
 | |
|   void ShrinkWithoutRows(nsTableCellMap& aMap, int32_t aFirstRowIndex,
 | |
|                          int32_t aNumRowsToRemove, int32_t aRgFirstRowIndex,
 | |
|                          TableArea& aDamageArea);
 | |
| 
 | |
|   void ShrinkWithoutCell(nsTableCellMap& aMap, nsTableCellFrame& aCellFrame,
 | |
|                          int32_t aRowIndex, int32_t aColIndex,
 | |
|                          int32_t aRgFirstRowIndex, TableArea& aDamageArea);
 | |
| 
 | |
|   /**
 | |
|    * Rebuild due to rows being inserted or deleted with cells spanning
 | |
|    * into or out of the rows.  This function can only handle insertion
 | |
|    * or deletion but NOT both.  So either aRowsToInsert must be null
 | |
|    * or aNumRowsToRemove must be 0.
 | |
|    *
 | |
|    * // XXXbz are both allowed to happen?  That'd be a no-op...
 | |
|    */
 | |
|   void RebuildConsideringRows(nsTableCellMap& aMap, int32_t aStartRowIndex,
 | |
|                               nsTArray<nsTableRowFrame*>* aRowsToInsert,
 | |
|                               int32_t aNumRowsToRemove);
 | |
| 
 | |
|   void RebuildConsideringCells(nsTableCellMap& aMap, int32_t aNumOrigCols,
 | |
|                                nsTArray<nsTableCellFrame*>* aCellFrames,
 | |
|                                int32_t aRowIndex, int32_t aColIndex,
 | |
|                                bool aInsert);
 | |
| 
 | |
|   bool CellsSpanOut(nsTArray<nsTableRowFrame*>& aNewRows) const;
 | |
| 
 | |
|   /** If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex
 | |
|     * and aStartColIndex, aEndColIndex the cellmap changes are more severe so
 | |
|     * the corresponding routines needs to be called. This is also necessary if
 | |
|     * cells outside spans into this region.
 | |
|     * @aStartRowIndex       - y start index
 | |
|     * @aEndRowIndex         - y end index
 | |
|     * @param aStartColIndex - x start index
 | |
|     * @param aEndColIndex   - x end index
 | |
|     * @return               - true if a cell span crosses the border of the
 | |
|                               region
 | |
|     */
 | |
|   bool CellsSpanInOrOut(int32_t aStartRowIndex, int32_t aEndRowIndex,
 | |
|                         int32_t aStartColIndex, int32_t aEndColIndex) const;
 | |
| 
 | |
|   bool CreateEmptyRow(int32_t aRowIndex, int32_t aNumCols);
 | |
| 
 | |
|   int32_t GetRowSpanForNewCell(nsTableCellFrame* aCellFrameToAdd,
 | |
|                                int32_t aRowIndex, bool& aIsZeroRowSpan) const;
 | |
| 
 | |
|   // Destroy a CellData struct.  This will handle the case of aData
 | |
|   // actually being a BCCellData properly.
 | |
|   void DestroyCellData(CellData* aData);
 | |
|   // Allocate a CellData struct.  This will handle needing to create a
 | |
|   // BCCellData properly.
 | |
|   // @param aOrigCell the originating cell to pass to the celldata constructor
 | |
|   CellData* AllocCellData(nsTableCellFrame* aOrigCell);
 | |
| 
 | |
|   /** an array containing, for each row, the CellDatas for the cells
 | |
|    * in that row.  It can be larger than mContentRowCount due to row spans
 | |
|    * extending beyond the table */
 | |
|   // XXXbz once we have auto TArrays, we should probably use them here.
 | |
|   nsTArray<CellDataArray> mRows;
 | |
| 
 | |
|   /** the number of rows in the table (content) which is not indentical to the
 | |
|    * number of rows in the cell map due to row spans extending beyond the end
 | |
|    * of thetable (dead rows) or empty tr tags
 | |
|    */
 | |
|   int32_t mContentRowCount;
 | |
| 
 | |
|   // the row group that corresponds to this map
 | |
|   nsTableRowGroupFrame* mRowGroupFrame;
 | |
| 
 | |
|   // the next row group cell map
 | |
|   nsCellMap* mNextSibling;
 | |
| 
 | |
|   // Whether this is a BC cellmap or not
 | |
|   bool mIsBC;
 | |
| 
 | |
|   // Prescontext to deallocate and allocate celldata
 | |
|   RefPtr<nsPresContext> mPresContext;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * A class for iterating the cells in a given column.  Must be given a
 | |
|  * non-null nsTableCellMap and a column number valid for that cellmap.
 | |
|  */
 | |
| class nsCellMapColumnIterator {
 | |
|  public:
 | |
|   nsCellMapColumnIterator(const nsTableCellMap* aMap, int32_t aCol)
 | |
|       : mMap(aMap),
 | |
|         mCurMap(aMap->mFirstMap),
 | |
|         mCurMapStart(0),
 | |
|         mCurMapRow(0),
 | |
|         mCol(aCol),
 | |
|         mFoundCells(0),
 | |
|         mCurMapContentRowCount(0),
 | |
|         mCurMapRelevantRowCount(0) {
 | |
|     MOZ_ASSERT(aMap, "Must have map");
 | |
|     MOZ_ASSERT(mCol < aMap->GetColCount(), "Invalid column");
 | |
|     mOrigCells = aMap->GetNumCellsOriginatingInCol(mCol);
 | |
|     if (mCurMap) {
 | |
|       mCurMapContentRowCount = mCurMap->GetRowCount();
 | |
|       uint32_t rowArrayLength = mCurMap->mRows.Length();
 | |
|       mCurMapRelevantRowCount =
 | |
|           std::min(mCurMapContentRowCount, rowArrayLength);
 | |
|       if (mCurMapRelevantRowCount == 0 && mOrigCells > 0) {
 | |
|         // This row group is useless; advance!
 | |
|         AdvanceRowGroup();
 | |
|       }
 | |
|     }
 | |
| #ifdef DEBUG
 | |
|     else {
 | |
|       NS_ASSERTION(mOrigCells == 0, "Why no rowgroups?");
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   nsTableCellFrame* GetNextFrame(int32_t* aRow, int32_t* aColSpan);
 | |
| 
 | |
|  private:
 | |
|   void AdvanceRowGroup();
 | |
| 
 | |
|   // Advance the row; aIncrement is considered to be a cell's rowspan,
 | |
|   // so if 0 is passed in we'll advance to the next rowgroup.
 | |
|   void IncrementRow(int32_t aIncrement);
 | |
| 
 | |
|   const nsTableCellMap* mMap;
 | |
|   const nsCellMap* mCurMap;
 | |
| 
 | |
|   // mCurMapStart is the row in the entire nsTableCellMap where
 | |
|   // mCurMap starts.  This is used to compute row indices to pass to
 | |
|   // nsTableCellMap::GetDataAt, so must be a _content_ row index.
 | |
|   uint32_t mCurMapStart;
 | |
| 
 | |
|   // In steady-state mCurMapRow is the row in our current nsCellMap
 | |
|   // that we'll use the next time GetNextFrame() is called.  Due to
 | |
|   // the way we skip over rowspans, the entry in mCurMapRow and mCol
 | |
|   // is either null, dead, originating, or a colspan.  In particular,
 | |
|   // it cannot be a rowspan or overlap entry.
 | |
|   uint32_t mCurMapRow;
 | |
|   const int32_t mCol;
 | |
|   uint32_t mOrigCells;
 | |
|   uint32_t mFoundCells;
 | |
| 
 | |
|   // The number of content rows in mCurMap.  This may be bigger than the number
 | |
|   // of "relevant" rows, or it might be smaller.
 | |
|   uint32_t mCurMapContentRowCount;
 | |
| 
 | |
|   // The number of "relevant" rows in mCurMap.  That is, the number of rows
 | |
|   // which might have an originating cell in them.  Once mCurMapRow reaches
 | |
|   // mCurMapRelevantRowCount, we should move to the next map.
 | |
|   uint32_t mCurMapRelevantRowCount;
 | |
| };
 | |
| 
 | |
| /* ----- inline methods ----- */
 | |
| inline int32_t nsTableCellMap::GetColCount() const { return mCols.Length(); }
 | |
| 
 | |
| inline nsCellMap* nsCellMap::GetNextSibling() const { return mNextSibling; }
 | |
| 
 | |
| inline void nsCellMap::SetNextSibling(nsCellMap* aSibling) {
 | |
|   mNextSibling = aSibling;
 | |
| }
 | |
| 
 | |
| inline nsTableRowGroupFrame* nsCellMap::GetRowGroup() const {
 | |
|   return mRowGroupFrame;
 | |
| }
 | |
| 
 | |
| inline int32_t nsCellMap::GetRowCount(bool aConsiderDeadRowSpanRows) const {
 | |
|   int32_t rowCount =
 | |
|       (aConsiderDeadRowSpanRows) ? mRows.Length() : mContentRowCount;
 | |
|   return rowCount;
 | |
| }
 | |
| 
 | |
| // nsColInfo
 | |
| 
 | |
| inline nsColInfo::nsColInfo() : mNumCellsOrig(0), mNumCellsSpan(0) {}
 | |
| 
 | |
| inline nsColInfo::nsColInfo(int32_t aNumCellsOrig, int32_t aNumCellsSpan)
 | |
|     : mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan) {}
 | |
| 
 | |
| #endif
 | 
