1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/tables/nsCellMap.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,692 @@ 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 nsCellMap_h__ 1.9 +#define nsCellMap_h__ 1.10 + 1.11 +#include "nscore.h" 1.12 +#include "celldata.h" 1.13 +#include "nsTArray.h" 1.14 +#include "nsTArray.h" 1.15 +#include "nsCOMPtr.h" 1.16 +#include "nsAlgorithm.h" 1.17 +#include "nsAutoPtr.h" 1.18 +#include <algorithm> 1.19 + 1.20 +#undef DEBUG_TABLE_CELLMAP 1.21 + 1.22 +class nsTableColFrame; 1.23 +class nsTableCellFrame; 1.24 +class nsTableRowFrame; 1.25 +class nsTableRowGroupFrame; 1.26 +class nsTableFrame; 1.27 +class nsCellMap; 1.28 +class nsPresContext; 1.29 +class nsCellMapColumnIterator; 1.30 +struct nsIntRect; 1.31 + 1.32 +struct nsColInfo 1.33 +{ 1.34 + int32_t mNumCellsOrig; // number of cells originating in the col 1.35 + int32_t mNumCellsSpan; // number of cells spanning into the col via colspans (not rowspans) 1.36 + 1.37 + nsColInfo(); 1.38 + nsColInfo(int32_t aNumCellsOrig, 1.39 + int32_t aNumCellsSpan); 1.40 +}; 1.41 + 1.42 +enum Corner 1.43 +{ 1.44 + eTopLeft = 0, 1.45 + eTopRight = 1, 1.46 + eBottomRight = 2, 1.47 + eBottomLeft = 3 1.48 +}; 1.49 + 1.50 +struct BCInfo 1.51 +{ 1.52 + nsTArray<BCData> mRightBorders; 1.53 + nsTArray<BCData> mBottomBorders; 1.54 + BCData mLowerRightCorner; 1.55 +}; 1.56 + 1.57 +class nsTableCellMap 1.58 +{ 1.59 +public: 1.60 + nsTableCellMap(nsTableFrame& aTableFrame, 1.61 + bool aBorderCollapse); 1.62 + 1.63 + /** destructor 1.64 + * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED 1.65 + */ 1.66 + ~nsTableCellMap(); 1.67 + 1.68 + void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup); 1.69 + 1.70 + void InsertGroupCellMap(nsTableRowGroupFrame* aNewRowGroup, 1.71 + nsTableRowGroupFrame*& aPrevRowGroup); 1.72 + 1.73 + /** 1.74 + * Get the nsCellMap for the given row group. If aStartHint is non-null, 1.75 + * will start looking with that cellmap and only fall back to starting at the 1.76 + * beginning of the list if that doesn't find us the right nsCellMap. 1.77 + * Otherwise, just start at the beginning. 1.78 + * 1.79 + * aRowGroup must not be null. 1.80 + */ 1.81 + nsCellMap* GetMapFor(const nsTableRowGroupFrame* aRowGroup, 1.82 + nsCellMap* aStartHint) const; 1.83 + 1.84 + /** synchronize the cellmaps with the rowgroups again **/ 1.85 + void Synchronize(nsTableFrame* aTableFrame); 1.86 + 1.87 + nsTableCellFrame* GetCellFrame(int32_t aRowIndex, 1.88 + int32_t aColIndex, 1.89 + CellData& aData, 1.90 + bool aUseRowIfOverlap) const; 1.91 + 1.92 + /** return the CellData for the cell at (aRowIndex, aColIndex) */ 1.93 + CellData* GetDataAt(int32_t aRowIndex, 1.94 + int32_t aColIndex) const; 1.95 + 1.96 + // this function creates a col if needed 1.97 + nsColInfo* GetColInfoAt(int32_t aColIndex); 1.98 + 1.99 + /** append the cellFrame at the end of the row at aRowIndex and return the col index 1.100 + */ 1.101 + CellData* AppendCell(nsTableCellFrame& aCellFrame, 1.102 + int32_t aRowIndex, 1.103 + bool aRebuildIfNecessary, 1.104 + nsIntRect& aDamageArea); 1.105 + 1.106 + void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, 1.107 + int32_t aRowIndex, 1.108 + int32_t aColIndexBefore, 1.109 + nsIntRect& aDamageArea); 1.110 + 1.111 + void RemoveCell(nsTableCellFrame* aCellFrame, 1.112 + int32_t aRowIndex, 1.113 + nsIntRect& aDamageArea); 1.114 + /** Remove the previously gathered column information */ 1.115 + void ClearCols(); 1.116 + void InsertRows(nsTableRowGroupFrame* aRowGroup, 1.117 + nsTArray<nsTableRowFrame*>& aRows, 1.118 + int32_t aFirstRowIndex, 1.119 + bool aConsiderSpans, 1.120 + nsIntRect& aDamageArea); 1.121 + 1.122 + void RemoveRows(int32_t aFirstRowIndex, 1.123 + int32_t aNumRowsToRemove, 1.124 + bool aConsiderSpans, 1.125 + nsIntRect& aDamageArea); 1.126 + 1.127 + int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const; 1.128 + int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const; 1.129 + 1.130 + /** indicate whether the row has more than one cell that either originates 1.131 + * or is spanned from the rows above 1.132 + */ 1.133 + bool HasMoreThanOneCell(int32_t aRowIndex) const; 1.134 + 1.135 + int32_t GetEffectiveRowSpan(int32_t aRowIndex, 1.136 + int32_t aColIndex) const; 1.137 + int32_t GetEffectiveColSpan(int32_t aRowIndex, 1.138 + int32_t aColIndex) const; 1.139 + 1.140 + /** return the total number of columns in the table represented by this CellMap */ 1.141 + int32_t GetColCount() const; 1.142 + 1.143 + /** return the actual number of rows in the table represented by this CellMap */ 1.144 + int32_t GetRowCount() const; 1.145 + 1.146 + nsTableCellFrame* GetCellInfoAt(int32_t aRowX, 1.147 + int32_t aColX, 1.148 + bool* aOriginates = nullptr, 1.149 + int32_t* aColSpan = nullptr) const; 1.150 + 1.151 + /** 1.152 + * Returns the index at the given row and column coordinates. 1.153 + * 1.154 + * @see nsITableLayout::GetIndexByRowAndColumn() 1.155 + * 1.156 + * @param aRow [in] the row coordinate 1.157 + * @param aColumn [in] the column coordinate 1.158 + * @returns the index for the cell 1.159 + */ 1.160 + int32_t GetIndexByRowAndColumn(int32_t aRow, int32_t aColumn) const; 1.161 + 1.162 + /** 1.163 + * Retrieves the row and column coordinates for the given index. 1.164 + * 1.165 + * @see nsITableLayout::GetRowAndColumnByIndex() 1.166 + * 1.167 + * @param aIndex [in] the index for which coordinates are to be retrieved 1.168 + * @param aRow [out] the row coordinate to be returned 1.169 + * @param aColumn [out] the column coordinate to be returned 1.170 + */ 1.171 + void GetRowAndColumnByIndex(int32_t aIndex, 1.172 + int32_t *aRow, int32_t *aColumn) const; 1.173 + 1.174 + void AddColsAtEnd(uint32_t aNumCols); 1.175 + void RemoveColsAtEnd(); 1.176 + 1.177 + bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols) const; 1.178 + bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) const; 1.179 + void RebuildConsideringCells(nsCellMap* aCellMap, 1.180 + nsTArray<nsTableCellFrame*>* aCellFrames, 1.181 + int32_t aRowIndex, 1.182 + int32_t aColIndex, 1.183 + bool aInsert, 1.184 + nsIntRect& aDamageArea); 1.185 + 1.186 +protected: 1.187 + /** 1.188 + * Rebuild due to rows being inserted or deleted with cells spanning 1.189 + * into or out of the rows. This function can only handle insertion 1.190 + * or deletion but NOT both. So either aRowsToInsert must be null 1.191 + * or aNumRowsToRemove must be 0. 1.192 + * 1.193 + * // XXXbz are both allowed to happen? That'd be a no-op... 1.194 + */ 1.195 + void RebuildConsideringRows(nsCellMap* aCellMap, 1.196 + int32_t aStartRowIndex, 1.197 + nsTArray<nsTableRowFrame*>* aRowsToInsert, 1.198 + int32_t aNumRowsToRemove, 1.199 + nsIntRect& aDamageArea); 1.200 + 1.201 +public: 1.202 + void ExpandZeroColSpans(); 1.203 + 1.204 + void ResetTopStart(uint8_t aSide, 1.205 + nsCellMap& aCellMap, 1.206 + uint32_t aYPos, 1.207 + uint32_t aXPos, 1.208 + bool aIsLowerRight = false); 1.209 + 1.210 + void SetBCBorderEdge(mozilla::css::Side aEdge, 1.211 + nsCellMap& aCellMap, 1.212 + uint32_t aCellMapStart, 1.213 + uint32_t aYPos, 1.214 + uint32_t aXPos, 1.215 + uint32_t aLength, 1.216 + BCBorderOwner aOwner, 1.217 + nscoord aSize, 1.218 + bool aChanged); 1.219 + 1.220 + void SetBCBorderCorner(::Corner aCorner, 1.221 + nsCellMap& aCellMap, 1.222 + uint32_t aCellMapStart, 1.223 + uint32_t aYPos, 1.224 + uint32_t aXPos, 1.225 + mozilla::css::Side aOwner, 1.226 + nscoord aSubSize, 1.227 + bool aBevel, 1.228 + bool aIsBottomRight = false); 1.229 + 1.230 + /** dump a representation of the cell map to stdout for debugging */ 1.231 +#ifdef DEBUG 1.232 + void Dump(char* aString = nullptr) const; 1.233 +#endif 1.234 + 1.235 +protected: 1.236 + BCData* GetRightMostBorder(int32_t aRowIndex); 1.237 + BCData* GetBottomMostBorder(int32_t aColIndex); 1.238 + 1.239 + friend class nsCellMap; 1.240 + friend class BCMapCellIterator; 1.241 + friend class BCPaintBorderIterator; 1.242 + friend class nsCellMapColumnIterator; 1.243 + 1.244 +/** Insert a row group cellmap after aPrevMap, if aPrefMap is null insert it 1.245 + * at the beginning, the ordering of the cellmap corresponds to the ordering of 1.246 + * rowgroups once OrderRowGroups has been called 1.247 + */ 1.248 + void InsertGroupCellMap(nsCellMap* aPrevMap, 1.249 + nsCellMap& aNewMap); 1.250 + void DeleteRightBottomBorders(); 1.251 + 1.252 + nsTableFrame& mTableFrame; 1.253 + nsAutoTArray<nsColInfo, 8> mCols; 1.254 + nsCellMap* mFirstMap; 1.255 + // border collapsing info 1.256 + BCInfo* mBCInfo; 1.257 +}; 1.258 + 1.259 +/** nsCellMap is a support class for nsTablePart. 1.260 + * It maintains an Rows x Columns grid onto which the cells of the table are mapped. 1.261 + * This makes processing of rowspan and colspan attributes much easier. 1.262 + * Each cell is represented by a CellData object. 1.263 + * 1.264 + * @see CellData 1.265 + * @see nsTableFrame::AddCellToMap 1.266 + * @see nsTableFrame::GrowCellMap 1.267 + * @see nsTableFrame::BuildCellIntoMap 1.268 + * 1.269 + * mRows is an array of rows. Each row is an array of cells. a cell 1.270 + * can be null. 1.271 + */ 1.272 +class nsCellMap 1.273 +{ 1.274 +public: 1.275 + /** constructor 1.276 + * @param aRowGroupFrame the row group frame this is a cellmap for 1.277 + * @param aIsBC whether the table is doing border-collapse 1.278 + */ 1.279 + nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, bool aIsBC); 1.280 + 1.281 + /** destructor 1.282 + * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED 1.283 + */ 1.284 + ~nsCellMap(); 1.285 + 1.286 + static void Init(); 1.287 + static void Shutdown(); 1.288 + 1.289 + nsCellMap* GetNextSibling() const; 1.290 + void SetNextSibling(nsCellMap* aSibling); 1.291 + 1.292 + nsTableRowGroupFrame* GetRowGroup() const; 1.293 + 1.294 + nsTableCellFrame* GetCellFrame(int32_t aRowIndex, 1.295 + int32_t aColIndex, 1.296 + CellData& aData, 1.297 + bool aUseRowSpanIfOverlap) const; 1.298 + 1.299 + /** 1.300 + * Returns highest cell index within the cell map. 1.301 + * 1.302 + * @param aColCount [in] the number of columns in the table 1.303 + */ 1.304 + int32_t GetHighestIndex(int32_t aColCount); 1.305 + 1.306 + /** 1.307 + * Returns the index of the given row and column coordinates. 1.308 + * 1.309 + * @see nsITableLayout::GetIndexByRowAndColumn() 1.310 + * 1.311 + * @param aColCount [in] the number of columns in the table 1.312 + * @param aRow [in] the row coordinate 1.313 + * @param aColumn [in] the column coordinate 1.314 + */ 1.315 + int32_t GetIndexByRowAndColumn(int32_t aColCount, 1.316 + int32_t aRow, int32_t aColumn) const; 1.317 + 1.318 + /** 1.319 + * Get the row and column coordinates at the given index. 1.320 + * 1.321 + * @see nsITableLayout::GetRowAndColumnByIndex() 1.322 + * 1.323 + * @param aColCount [in] the number of columns in the table 1.324 + * @param aIndex [in] the index for which coordinates are to be retrieved 1.325 + * @param aRow [out] the row coordinate to be returned 1.326 + * @param aColumn [out] the column coordinate to be returned 1.327 + */ 1.328 + void GetRowAndColumnByIndex(int32_t aColCount, int32_t aIndex, 1.329 + int32_t *aRow, int32_t *aColumn) const; 1.330 + 1.331 + /** append the cellFrame at an empty or dead cell or finally at the end of 1.332 + * the row at aRowIndex and return a pointer to the celldata entry in the 1.333 + * cellmap 1.334 + * 1.335 + * @param aMap - reference to the table cell map 1.336 + * @param aCellFrame - a pointer to the cellframe which will be appended 1.337 + * to the row 1.338 + * @param aRowIndex - to this row the celldata entry will be added 1.339 + * @param aRebuildIfNecessay - if a cell spans into a row below it might be 1.340 + * necesserary to rebuild the cellmap as this rowspan 1.341 + * might overlap another cell. 1.342 + * @param aDamageArea - area in cellmap coordinates which have been updated. 1.343 + * @param aColToBeginSearch - if not null contains the column number where 1.344 + * the search for a empty or dead cell in the 1.345 + * row should start 1.346 + * @return - a pointer to the celldata entry inserted into 1.347 + * the cellmap 1.348 + */ 1.349 + CellData* AppendCell(nsTableCellMap& aMap, 1.350 + nsTableCellFrame* aCellFrame, 1.351 + int32_t aRowIndex, 1.352 + bool aRebuildIfNecessary, 1.353 + int32_t aRgFirstRowIndex, 1.354 + nsIntRect& aDamageArea, 1.355 + int32_t* aBeginSearchAtCol = nullptr); 1.356 + 1.357 + /** Function to be called when a cell is added at a location which is spanned 1.358 + * to by a zero colspan. We handle this situation by collapsing the zero 1.359 + * colspan, since there is really no good way to deal with it (trying to 1.360 + * increase the number of columns to hold the new cell would just mean the 1.361 + * zero colspan needs to expand). 1.362 + 1.363 + * @param aMap - reference to the table cell map 1.364 + * @param aOrigData - zero colspanned cell that will be collapsed 1.365 + * @param aRowIndex - row where the first collision appears 1.366 + * @param aColIndex - column where the first collision appears 1.367 + **/ 1.368 + void CollapseZeroColSpan(nsTableCellMap& aMap, 1.369 + CellData* aOrigData, 1.370 + int32_t aRowIndex, 1.371 + int32_t aColIndex); 1.372 + 1.373 + void InsertCells(nsTableCellMap& aMap, 1.374 + nsTArray<nsTableCellFrame*>& aCellFrames, 1.375 + int32_t aRowIndex, 1.376 + int32_t aColIndexBefore, 1.377 + int32_t aRgFirstRowIndex, 1.378 + nsIntRect& aDamageArea); 1.379 + 1.380 + void RemoveCell(nsTableCellMap& aMap, 1.381 + nsTableCellFrame* aCellFrame, 1.382 + int32_t aRowIndex, 1.383 + int32_t aRgFirstRowIndex, 1.384 + nsIntRect& aDamageArea); 1.385 + 1.386 + void InsertRows(nsTableCellMap& aMap, 1.387 + nsTArray<nsTableRowFrame*>& aRows, 1.388 + int32_t aFirstRowIndex, 1.389 + bool aConsiderSpans, 1.390 + int32_t aRgFirstRowIndex, 1.391 + nsIntRect& aDamageArea); 1.392 + 1.393 + void RemoveRows(nsTableCellMap& aMap, 1.394 + int32_t aFirstRowIndex, 1.395 + int32_t aNumRowsToRemove, 1.396 + bool aConsiderSpans, 1.397 + int32_t aRgFirstRowIndex, 1.398 + nsIntRect& aDamageArea); 1.399 + 1.400 + int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const; 1.401 + int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const; 1.402 + 1.403 + /** return the number of rows in the table represented by this CellMap */ 1.404 + int32_t GetRowCount(bool aConsiderDeadRowSpanRows = false) const; 1.405 + 1.406 + nsTableCellFrame* GetCellInfoAt(const nsTableCellMap& aMap, 1.407 + int32_t aRowX, 1.408 + int32_t aColX, 1.409 + bool* aOriginates = nullptr, 1.410 + int32_t* aColSpan = nullptr) const; 1.411 + 1.412 + bool RowIsSpannedInto(int32_t aRowIndex, 1.413 + int32_t aNumEffCols) const; 1.414 + 1.415 + bool RowHasSpanningCells(int32_t aRowIndex, 1.416 + int32_t aNumEffCols) const; 1.417 + 1.418 + void ExpandZeroColSpans(nsTableCellMap& aMap); 1.419 + 1.420 + /** indicate whether the row has more than one cell that either originates 1.421 + * or is spanned from the rows above 1.422 + */ 1.423 + bool HasMoreThanOneCell(int32_t aRowIndex) const; 1.424 + 1.425 + /* Get the rowspan for a cell starting at aRowIndex and aColIndex. 1.426 + * If aGetEffective is true the size will not exceed the last content based 1.427 + * row. Cells can have a specified rowspan that extends below the last 1.428 + * content based row. This is legitimate considering incr. reflow where the 1.429 + * content rows will arive later. 1.430 + */ 1.431 + int32_t GetRowSpan(int32_t aRowIndex, 1.432 + int32_t aColIndex, 1.433 + bool aGetEffective) const; 1.434 + 1.435 + int32_t GetEffectiveColSpan(const nsTableCellMap& aMap, 1.436 + int32_t aRowIndex, 1.437 + int32_t aColIndex, 1.438 + bool& aIsZeroColSpan) const; 1.439 + 1.440 + typedef nsTArray<CellData*> CellDataArray; 1.441 + 1.442 + /** dump a representation of the cell map to stdout for debugging */ 1.443 +#ifdef DEBUG 1.444 + void Dump(bool aIsBorderCollapse) const; 1.445 +#endif 1.446 + 1.447 +protected: 1.448 + friend class nsTableCellMap; 1.449 + friend class BCMapCellIterator; 1.450 + friend class BCPaintBorderIterator; 1.451 + friend class nsTableFrame; 1.452 + friend class nsCellMapColumnIterator; 1.453 + 1.454 + /** 1.455 + * Increase the number of rows in this cellmap by aNumRows. Put the 1.456 + * new rows at aRowIndex. If aRowIndex is -1, put them at the end. 1.457 + */ 1.458 + bool Grow(nsTableCellMap& aMap, 1.459 + int32_t aNumRows, 1.460 + int32_t aRowIndex = -1); 1.461 + 1.462 + void GrowRow(CellDataArray& aRow, 1.463 + int32_t aNumCols); 1.464 + 1.465 + /** assign aCellData to the cell at (aRow,aColumn) */ 1.466 + void SetDataAt(nsTableCellMap& aMap, 1.467 + CellData& aCellData, 1.468 + int32_t aMapRowIndex, 1.469 + int32_t aColIndex); 1.470 + 1.471 + CellData* GetDataAt(int32_t aMapRowIndex, 1.472 + int32_t aColIndex) const; 1.473 + 1.474 + int32_t GetNumCellsIn(int32_t aColIndex) const; 1.475 + 1.476 + void ExpandWithRows(nsTableCellMap& aMap, 1.477 + nsTArray<nsTableRowFrame*>& aRowFrames, 1.478 + int32_t aStartRowIndex, 1.479 + int32_t aRgFirstRowIndex, 1.480 + nsIntRect& aDamageArea); 1.481 + 1.482 + void ExpandWithCells(nsTableCellMap& aMap, 1.483 + nsTArray<nsTableCellFrame*>& aCellFrames, 1.484 + int32_t aRowIndex, 1.485 + int32_t aColIndex, 1.486 + int32_t aRowSpan, 1.487 + bool aRowSpanIsZero, 1.488 + int32_t aRgFirstRowIndex, 1.489 + nsIntRect& aDamageArea); 1.490 + 1.491 + void ShrinkWithoutRows(nsTableCellMap& aMap, 1.492 + int32_t aFirstRowIndex, 1.493 + int32_t aNumRowsToRemove, 1.494 + int32_t aRgFirstRowIndex, 1.495 + nsIntRect& aDamageArea); 1.496 + 1.497 + void ShrinkWithoutCell(nsTableCellMap& aMap, 1.498 + nsTableCellFrame& aCellFrame, 1.499 + int32_t aRowIndex, 1.500 + int32_t aColIndex, 1.501 + int32_t aRgFirstRowIndex, 1.502 + nsIntRect& aDamageArea); 1.503 + 1.504 + /** 1.505 + * Rebuild due to rows being inserted or deleted with cells spanning 1.506 + * into or out of the rows. This function can only handle insertion 1.507 + * or deletion but NOT both. So either aRowsToInsert must be null 1.508 + * or aNumRowsToRemove must be 0. 1.509 + * 1.510 + * // XXXbz are both allowed to happen? That'd be a no-op... 1.511 + */ 1.512 + void RebuildConsideringRows(nsTableCellMap& aMap, 1.513 + int32_t aStartRowIndex, 1.514 + nsTArray<nsTableRowFrame*>* aRowsToInsert, 1.515 + int32_t aNumRowsToRemove); 1.516 + 1.517 + void RebuildConsideringCells(nsTableCellMap& aMap, 1.518 + int32_t aNumOrigCols, 1.519 + nsTArray<nsTableCellFrame*>* aCellFrames, 1.520 + int32_t aRowIndex, 1.521 + int32_t aColIndex, 1.522 + bool aInsert); 1.523 + 1.524 + bool CellsSpanOut(nsTArray<nsTableRowFrame*>& aNewRows) const; 1.525 + 1.526 + /** If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex 1.527 + * and aStartColIndex, aEndColIndex the cellmap changes are more severe so 1.528 + * the corresponding routines needs to be called. This is also necessary if 1.529 + * cells outside spans into this region. 1.530 + * @aStartRowIndex - y start index 1.531 + * @aEndRowIndex - y end index 1.532 + * @param aStartColIndex - x start index 1.533 + * @param aEndColIndex - x end index 1.534 + * @return - true if a cell span crosses the border of the 1.535 + region 1.536 + */ 1.537 + bool CellsSpanInOrOut(int32_t aStartRowIndex, 1.538 + int32_t aEndRowIndex, 1.539 + int32_t aStartColIndex, 1.540 + int32_t aEndColIndex) const; 1.541 + 1.542 + void ExpandForZeroSpan(nsTableCellFrame* aCellFrame, 1.543 + int32_t aNumColsInTable); 1.544 + 1.545 + bool CreateEmptyRow(int32_t aRowIndex, 1.546 + int32_t aNumCols); 1.547 + 1.548 + int32_t GetRowSpanForNewCell(nsTableCellFrame* aCellFrameToAdd, 1.549 + int32_t aRowIndex, 1.550 + bool& aIsZeroRowSpan) const; 1.551 + 1.552 + int32_t GetColSpanForNewCell(nsTableCellFrame& aCellFrameToAdd, 1.553 + bool& aIsZeroColSpan) const; 1.554 + 1.555 + // Destroy a CellData struct. This will handle the case of aData 1.556 + // actually being a BCCellData properly. 1.557 + void DestroyCellData(CellData* aData); 1.558 + // Allocate a CellData struct. This will handle needing to create a 1.559 + // BCCellData properly. 1.560 + // @param aOrigCell the originating cell to pass to the celldata constructor 1.561 + CellData* AllocCellData(nsTableCellFrame* aOrigCell); 1.562 + 1.563 + /** an array containing, for each row, the CellDatas for the cells 1.564 + * in that row. It can be larger than mContentRowCount due to row spans 1.565 + * extending beyond the table */ 1.566 + // XXXbz once we have auto TArrays, we should probably use them here. 1.567 + nsTArray<CellDataArray> mRows; 1.568 + 1.569 + /** the number of rows in the table (content) which is not indentical to the 1.570 + * number of rows in the cell map due to row spans extending beyond the end 1.571 + * of thetable (dead rows) or empty tr tags 1.572 + */ 1.573 + int32_t mContentRowCount; 1.574 + 1.575 + // the row group that corresponds to this map 1.576 + nsTableRowGroupFrame* mRowGroupFrame; 1.577 + 1.578 + // the next row group cell map 1.579 + nsCellMap* mNextSibling; 1.580 + 1.581 + // Whether this is a BC cellmap or not 1.582 + bool mIsBC; 1.583 + 1.584 + // Prescontext to deallocate and allocate celldata 1.585 + nsRefPtr<nsPresContext> mPresContext; 1.586 +}; 1.587 + 1.588 +/** 1.589 + * A class for iterating the cells in a given column. Must be given a 1.590 + * non-null nsTableCellMap and a column number valid for that cellmap. 1.591 + */ 1.592 +class nsCellMapColumnIterator 1.593 +{ 1.594 +public: 1.595 + nsCellMapColumnIterator(const nsTableCellMap* aMap, int32_t aCol) : 1.596 + mMap(aMap), mCurMap(aMap->mFirstMap), mCurMapStart(0), 1.597 + mCurMapRow(0), mCol(aCol), mFoundCells(0) 1.598 + { 1.599 + NS_PRECONDITION(aMap, "Must have map"); 1.600 + NS_PRECONDITION(mCol < aMap->GetColCount(), "Invalid column"); 1.601 + mOrigCells = aMap->GetNumCellsOriginatingInCol(mCol); 1.602 + if (mCurMap) { 1.603 + mCurMapContentRowCount = mCurMap->GetRowCount(); 1.604 + uint32_t rowArrayLength = mCurMap->mRows.Length(); 1.605 + mCurMapRelevantRowCount = std::min(mCurMapContentRowCount, rowArrayLength); 1.606 + if (mCurMapRelevantRowCount == 0 && mOrigCells > 0) { 1.607 + // This row group is useless; advance! 1.608 + AdvanceRowGroup(); 1.609 + } 1.610 + } 1.611 +#ifdef DEBUG 1.612 + else { 1.613 + NS_ASSERTION(mOrigCells == 0, "Why no rowgroups?"); 1.614 + } 1.615 +#endif 1.616 + } 1.617 + 1.618 + nsTableCellFrame* GetNextFrame(int32_t* aRow, int32_t* aColSpan); 1.619 + 1.620 +private: 1.621 + void AdvanceRowGroup(); 1.622 + 1.623 + // Advance the row; aIncrement is considered to be a cell's rowspan, 1.624 + // so if 0 is passed in we'll advance to the next rowgroup. 1.625 + void IncrementRow(int32_t aIncrement); 1.626 + 1.627 + const nsTableCellMap* mMap; 1.628 + const nsCellMap* mCurMap; 1.629 + 1.630 + // mCurMapStart is the row in the entire nsTableCellMap where 1.631 + // mCurMap starts. This is used to compute row indices to pass to 1.632 + // nsTableCellMap::GetDataAt, so must be a _content_ row index. 1.633 + uint32_t mCurMapStart; 1.634 + 1.635 + // In steady-state mCurMapRow is the row in our current nsCellMap 1.636 + // that we'll use the next time GetNextFrame() is called. Due to 1.637 + // the way we skip over rowspans, the entry in mCurMapRow and mCol 1.638 + // is either null, dead, originating, or a colspan. In particular, 1.639 + // it cannot be a rowspan or overlap entry. 1.640 + uint32_t mCurMapRow; 1.641 + const int32_t mCol; 1.642 + uint32_t mOrigCells; 1.643 + uint32_t mFoundCells; 1.644 + 1.645 + // The number of content rows in mCurMap. This may be bigger than the number 1.646 + // of "relevant" rows, or it might be smaller. 1.647 + uint32_t mCurMapContentRowCount; 1.648 + 1.649 + // The number of "relevant" rows in mCurMap. That is, the number of rows 1.650 + // which might have an originating cell in them. Once mCurMapRow reaches 1.651 + // mCurMapRelevantRowCount, we should move to the next map. 1.652 + uint32_t mCurMapRelevantRowCount; 1.653 +}; 1.654 + 1.655 + 1.656 +/* ----- inline methods ----- */ 1.657 +inline int32_t nsTableCellMap::GetColCount() const 1.658 +{ 1.659 + return mCols.Length(); 1.660 +} 1.661 + 1.662 +inline nsCellMap* nsCellMap::GetNextSibling() const 1.663 +{ 1.664 + return mNextSibling; 1.665 +} 1.666 + 1.667 +inline void nsCellMap::SetNextSibling(nsCellMap* aSibling) 1.668 +{ 1.669 + mNextSibling = aSibling; 1.670 +} 1.671 + 1.672 +inline nsTableRowGroupFrame* nsCellMap::GetRowGroup() const 1.673 +{ 1.674 + return mRowGroupFrame; 1.675 +} 1.676 + 1.677 +inline int32_t nsCellMap::GetRowCount(bool aConsiderDeadRowSpanRows) const 1.678 +{ 1.679 + int32_t rowCount = (aConsiderDeadRowSpanRows) ? mRows.Length() : mContentRowCount; 1.680 + return rowCount; 1.681 +} 1.682 + 1.683 +// nsColInfo 1.684 + 1.685 +inline nsColInfo::nsColInfo() 1.686 + :mNumCellsOrig(0), mNumCellsSpan(0) 1.687 +{} 1.688 + 1.689 +inline nsColInfo::nsColInfo(int32_t aNumCellsOrig, 1.690 + int32_t aNumCellsSpan) 1.691 + :mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan) 1.692 +{} 1.693 + 1.694 + 1.695 +#endif