/src/mozilla-central/layout/tables/nsCellMap.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | #ifndef nsCellMap_h__ |
6 | | #define nsCellMap_h__ |
7 | | |
8 | | #include "nscore.h" |
9 | | #include "celldata.h" |
10 | | #include "nsTArray.h" |
11 | | #include "nsTArray.h" |
12 | | #include "nsCOMPtr.h" |
13 | | #include "nsAlgorithm.h" |
14 | | #include "nsRect.h" |
15 | | #include <algorithm> |
16 | | #include "TableArea.h" |
17 | | |
18 | | #undef DEBUG_TABLE_CELLMAP |
19 | | |
20 | | class nsTableCellFrame; |
21 | | class nsTableRowFrame; |
22 | | class nsTableRowGroupFrame; |
23 | | class nsTableFrame; |
24 | | class nsCellMap; |
25 | | class nsPresContext; |
26 | | class nsCellMapColumnIterator; |
27 | | |
28 | | struct nsColInfo |
29 | | { |
30 | | int32_t mNumCellsOrig; // number of cells originating in the col |
31 | | int32_t mNumCellsSpan; // number of cells spanning into the col via colspans (not rowspans) |
32 | | |
33 | | nsColInfo(); |
34 | | nsColInfo(int32_t aNumCellsOrig, |
35 | | int32_t aNumCellsSpan); |
36 | | }; |
37 | | |
38 | | struct BCInfo |
39 | | { |
40 | | nsTArray<BCData> mIEndBorders; |
41 | | nsTArray<BCData> mBEndBorders; |
42 | | BCData mBEndIEndCorner; |
43 | | }; |
44 | | |
45 | | class nsTableCellMap |
46 | | { |
47 | | typedef mozilla::TableArea TableArea; |
48 | | |
49 | | public: |
50 | | nsTableCellMap(nsTableFrame& aTableFrame, |
51 | | bool aBorderCollapse); |
52 | | |
53 | | /** destructor |
54 | | * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED |
55 | | */ |
56 | | ~nsTableCellMap(); |
57 | | |
58 | | void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup); |
59 | | |
60 | | void InsertGroupCellMap(nsTableRowGroupFrame* aNewRowGroup, |
61 | | nsTableRowGroupFrame*& aPrevRowGroup); |
62 | | |
63 | | /** |
64 | | * Get the nsCellMap for the given row group. If aStartHint is non-null, |
65 | | * will start looking with that cellmap and only fall back to starting at the |
66 | | * beginning of the list if that doesn't find us the right nsCellMap. |
67 | | * Otherwise, just start at the beginning. |
68 | | * |
69 | | * aRowGroup must not be null. |
70 | | */ |
71 | | nsCellMap* GetMapFor(const nsTableRowGroupFrame* aRowGroup, |
72 | | nsCellMap* aStartHint) const; |
73 | | |
74 | | /** synchronize the cellmaps with the rowgroups again **/ |
75 | | void Synchronize(nsTableFrame* aTableFrame); |
76 | | |
77 | | nsTableCellFrame* GetCellFrame(int32_t aRowIndex, |
78 | | int32_t aColIndex, |
79 | | CellData& aData, |
80 | | bool aUseRowIfOverlap) const; |
81 | | |
82 | | /** return the CellData for the cell at (aRowIndex, aColIndex) */ |
83 | | CellData* GetDataAt(int32_t aRowIndex, |
84 | | int32_t aColIndex) const; |
85 | | |
86 | | // this function creates a col if needed |
87 | | nsColInfo* GetColInfoAt(int32_t aColIndex); |
88 | | |
89 | | /** append the cellFrame at the end of the row at aRowIndex and return the col index |
90 | | */ |
91 | | CellData* AppendCell(nsTableCellFrame& aCellFrame, |
92 | | int32_t aRowIndex, |
93 | | bool aRebuildIfNecessary, |
94 | | TableArea& aDamageArea); |
95 | | |
96 | | void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, |
97 | | int32_t aRowIndex, |
98 | | int32_t aColIndexBefore, |
99 | | TableArea& aDamageArea); |
100 | | |
101 | | void RemoveCell(nsTableCellFrame* aCellFrame, |
102 | | int32_t aRowIndex, |
103 | | TableArea& aDamageArea); |
104 | | /** Remove the previously gathered column information */ |
105 | | void ClearCols(); |
106 | | void InsertRows(nsTableRowGroupFrame* aRowGroup, |
107 | | nsTArray<nsTableRowFrame*>& aRows, |
108 | | int32_t aFirstRowIndex, |
109 | | bool aConsiderSpans, |
110 | | TableArea& aDamageArea); |
111 | | |
112 | | void RemoveRows(int32_t aFirstRowIndex, |
113 | | int32_t aNumRowsToRemove, |
114 | | bool aConsiderSpans, |
115 | | TableArea& aDamageArea); |
116 | | |
117 | | int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const; |
118 | | int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const; |
119 | | |
120 | | /** indicate whether the row has more than one cell that either originates |
121 | | * or is spanned from the rows above |
122 | | */ |
123 | | bool HasMoreThanOneCell(int32_t aRowIndex) const; |
124 | | |
125 | | int32_t GetEffectiveRowSpan(int32_t aRowIndex, |
126 | | int32_t aColIndex) const; |
127 | | int32_t GetEffectiveColSpan(int32_t aRowIndex, |
128 | | int32_t aColIndex) const; |
129 | | |
130 | | /** return the total number of columns in the table represented by this CellMap */ |
131 | | int32_t GetColCount() const; |
132 | | |
133 | | /** return the actual number of rows in the table represented by this CellMap */ |
134 | | int32_t GetRowCount() const; |
135 | | |
136 | | nsTableCellFrame* GetCellInfoAt(int32_t aRowX, |
137 | | int32_t aColX, |
138 | | bool* aOriginates = nullptr, |
139 | | int32_t* aColSpan = nullptr) const; |
140 | | |
141 | | /** |
142 | | * Returns the index at the given row and column coordinates. |
143 | | * |
144 | | * @see nsITableLayout::GetIndexByRowAndColumn() |
145 | | * |
146 | | * @param aRow [in] the row coordinate |
147 | | * @param aColumn [in] the column coordinate |
148 | | * @returns the index for the cell |
149 | | */ |
150 | | int32_t GetIndexByRowAndColumn(int32_t aRow, int32_t aColumn) const; |
151 | | |
152 | | /** |
153 | | * Retrieves the row and column coordinates for the given index. |
154 | | * |
155 | | * @see nsITableLayout::GetRowAndColumnByIndex() |
156 | | * |
157 | | * @param aIndex [in] the index for which coordinates are to be retrieved |
158 | | * @param aRow [out] the row coordinate to be returned |
159 | | * @param aColumn [out] the column coordinate to be returned |
160 | | */ |
161 | | void GetRowAndColumnByIndex(int32_t aIndex, |
162 | | int32_t *aRow, int32_t *aColumn) const; |
163 | | |
164 | | void AddColsAtEnd(uint32_t aNumCols); |
165 | | void RemoveColsAtEnd(); |
166 | | |
167 | | bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols) const; |
168 | | bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) const; |
169 | | void RebuildConsideringCells(nsCellMap* aCellMap, |
170 | | nsTArray<nsTableCellFrame*>* aCellFrames, |
171 | | int32_t aRowIndex, |
172 | | int32_t aColIndex, |
173 | | bool aInsert, |
174 | | TableArea& aDamageArea); |
175 | | |
176 | | protected: |
177 | | /** |
178 | | * Rebuild due to rows being inserted or deleted with cells spanning |
179 | | * into or out of the rows. This function can only handle insertion |
180 | | * or deletion but NOT both. So either aRowsToInsert must be null |
181 | | * or aNumRowsToRemove must be 0. |
182 | | * |
183 | | * // XXXbz are both allowed to happen? That'd be a no-op... |
184 | | */ |
185 | | void RebuildConsideringRows(nsCellMap* aCellMap, |
186 | | int32_t aStartRowIndex, |
187 | | nsTArray<nsTableRowFrame*>* aRowsToInsert, |
188 | | int32_t aNumRowsToRemove, |
189 | | TableArea& aDamageArea); |
190 | | |
191 | | public: |
192 | | void ResetBStartStart(mozilla::LogicalSide aSide, |
193 | | nsCellMap& aCellMap, |
194 | | uint32_t aRowGroupStart, |
195 | | uint32_t aYPos, |
196 | | uint32_t aXPos); |
197 | | |
198 | | void SetBCBorderEdge(mozilla::LogicalSide aEdge, |
199 | | nsCellMap& aCellMap, |
200 | | uint32_t aCellMapStart, |
201 | | uint32_t aYPos, |
202 | | uint32_t aXPos, |
203 | | uint32_t aLength, |
204 | | BCBorderOwner aOwner, |
205 | | nscoord aSize, |
206 | | bool aChanged); |
207 | | |
208 | | void SetBCBorderCorner(mozilla::LogicalCorner aCorner, |
209 | | nsCellMap& aCellMap, |
210 | | uint32_t aCellMapStart, |
211 | | uint32_t aYPos, |
212 | | uint32_t aXPos, |
213 | | mozilla::LogicalSide aOwner, |
214 | | nscoord aSubSize, |
215 | | bool aBevel, |
216 | | bool aIsBottomRight = false); |
217 | | |
218 | | /** dump a representation of the cell map to stdout for debugging */ |
219 | | #ifdef DEBUG |
220 | | void Dump(char* aString = nullptr) const; |
221 | | #endif |
222 | | |
223 | | protected: |
224 | | BCData* GetIEndMostBorder(int32_t aRowIndex); |
225 | | BCData* GetBEndMostBorder(int32_t aColIndex); |
226 | | |
227 | | friend class nsCellMap; |
228 | | friend class BCMapCellIterator; |
229 | | friend class BCPaintBorderIterator; |
230 | | friend class nsCellMapColumnIterator; |
231 | | |
232 | | /** Insert a row group cellmap after aPrevMap, if aPrefMap is null insert it |
233 | | * at the beginning, the ordering of the cellmap corresponds to the ordering of |
234 | | * rowgroups once OrderRowGroups has been called |
235 | | */ |
236 | | void InsertGroupCellMap(nsCellMap* aPrevMap, |
237 | | nsCellMap& aNewMap); |
238 | | void DeleteIEndBEndBorders(); |
239 | | |
240 | | nsTableFrame& mTableFrame; |
241 | | AutoTArray<nsColInfo, 8> mCols; |
242 | | nsCellMap* mFirstMap; |
243 | | // border collapsing info |
244 | | BCInfo* mBCInfo; |
245 | | }; |
246 | | |
247 | | /** nsCellMap is a support class for nsTablePart. |
248 | | * It maintains an Rows x Columns grid onto which the cells of the table are mapped. |
249 | | * This makes processing of rowspan and colspan attributes much easier. |
250 | | * Each cell is represented by a CellData object. |
251 | | * |
252 | | * @see CellData |
253 | | * @see nsTableFrame::AddCellToMap |
254 | | * @see nsTableFrame::GrowCellMap |
255 | | * @see nsTableFrame::BuildCellIntoMap |
256 | | * |
257 | | * mRows is an array of rows. Each row is an array of cells. a cell |
258 | | * can be null. |
259 | | */ |
260 | | class nsCellMap |
261 | | { |
262 | | typedef mozilla::TableArea TableArea; |
263 | | |
264 | | public: |
265 | | /** constructor |
266 | | * @param aRowGroupFrame the row group frame this is a cellmap for |
267 | | * @param aIsBC whether the table is doing border-collapse |
268 | | */ |
269 | | nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, bool aIsBC); |
270 | | |
271 | | /** destructor |
272 | | * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED |
273 | | */ |
274 | | ~nsCellMap(); |
275 | | |
276 | | static void Init(); |
277 | | static void Shutdown(); |
278 | | |
279 | | nsCellMap* GetNextSibling() const; |
280 | | void SetNextSibling(nsCellMap* aSibling); |
281 | | |
282 | | nsTableRowGroupFrame* GetRowGroup() const; |
283 | | |
284 | | nsTableCellFrame* GetCellFrame(int32_t aRowIndex, |
285 | | int32_t aColIndex, |
286 | | CellData& aData, |
287 | | bool aUseRowSpanIfOverlap) const; |
288 | | |
289 | | /** |
290 | | * Returns highest cell index within the cell map. |
291 | | * |
292 | | * @param aColCount [in] the number of columns in the table |
293 | | */ |
294 | | int32_t GetHighestIndex(int32_t aColCount); |
295 | | |
296 | | /** |
297 | | * Returns the index of the given row and column coordinates. |
298 | | * |
299 | | * @see nsITableLayout::GetIndexByRowAndColumn() |
300 | | * |
301 | | * @param aColCount [in] the number of columns in the table |
302 | | * @param aRow [in] the row coordinate |
303 | | * @param aColumn [in] the column coordinate |
304 | | */ |
305 | | int32_t GetIndexByRowAndColumn(int32_t aColCount, |
306 | | int32_t aRow, int32_t aColumn) const; |
307 | | |
308 | | /** |
309 | | * Get the row and column coordinates at the given index. |
310 | | * |
311 | | * @see nsITableLayout::GetRowAndColumnByIndex() |
312 | | * |
313 | | * @param aColCount [in] the number of columns in the table |
314 | | * @param aIndex [in] the index for which coordinates are to be retrieved |
315 | | * @param aRow [out] the row coordinate to be returned |
316 | | * @param aColumn [out] the column coordinate to be returned |
317 | | */ |
318 | | void GetRowAndColumnByIndex(int32_t aColCount, int32_t aIndex, |
319 | | int32_t *aRow, int32_t *aColumn) const; |
320 | | |
321 | | /** append the cellFrame at an empty or dead cell or finally at the end of |
322 | | * the row at aRowIndex and return a pointer to the celldata entry in the |
323 | | * cellmap |
324 | | * |
325 | | * @param aMap - reference to the table cell map |
326 | | * @param aCellFrame - a pointer to the cellframe which will be appended |
327 | | * to the row |
328 | | * @param aRowIndex - to this row the celldata entry will be added |
329 | | * @param aRebuildIfNecessay - if a cell spans into a row below it might be |
330 | | * necesserary to rebuild the cellmap as this rowspan |
331 | | * might overlap another cell. |
332 | | * @param aDamageArea - area in cellmap coordinates which have been updated. |
333 | | * @param aColToBeginSearch - if not null contains the column number where |
334 | | * the search for a empty or dead cell in the |
335 | | * row should start |
336 | | * @return - a pointer to the celldata entry inserted into |
337 | | * the cellmap |
338 | | */ |
339 | | CellData* AppendCell(nsTableCellMap& aMap, |
340 | | nsTableCellFrame* aCellFrame, |
341 | | int32_t aRowIndex, |
342 | | bool aRebuildIfNecessary, |
343 | | int32_t aRgFirstRowIndex, |
344 | | TableArea& aDamageArea, |
345 | | int32_t* aBeginSearchAtCol = nullptr); |
346 | | |
347 | | void InsertCells(nsTableCellMap& aMap, |
348 | | nsTArray<nsTableCellFrame*>& aCellFrames, |
349 | | int32_t aRowIndex, |
350 | | int32_t aColIndexBefore, |
351 | | int32_t aRgFirstRowIndex, |
352 | | TableArea& aDamageArea); |
353 | | |
354 | | void RemoveCell(nsTableCellMap& aMap, |
355 | | nsTableCellFrame* aCellFrame, |
356 | | int32_t aRowIndex, |
357 | | int32_t aRgFirstRowIndex, |
358 | | TableArea& aDamageArea); |
359 | | |
360 | | void InsertRows(nsTableCellMap& aMap, |
361 | | nsTArray<nsTableRowFrame*>& aRows, |
362 | | int32_t aFirstRowIndex, |
363 | | bool aConsiderSpans, |
364 | | int32_t aRgFirstRowIndex, |
365 | | TableArea& aDamageArea); |
366 | | |
367 | | void RemoveRows(nsTableCellMap& aMap, |
368 | | int32_t aFirstRowIndex, |
369 | | int32_t aNumRowsToRemove, |
370 | | bool aConsiderSpans, |
371 | | int32_t aRgFirstRowIndex, |
372 | | TableArea& aDamageArea); |
373 | | |
374 | | int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const; |
375 | | int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const; |
376 | | |
377 | | /** return the number of rows in the table represented by this CellMap */ |
378 | | int32_t GetRowCount(bool aConsiderDeadRowSpanRows = false) const; |
379 | | |
380 | | nsTableCellFrame* GetCellInfoAt(const nsTableCellMap& aMap, |
381 | | int32_t aRowX, |
382 | | int32_t aColX, |
383 | | bool* aOriginates = nullptr, |
384 | | int32_t* aColSpan = nullptr) const; |
385 | | |
386 | | bool RowIsSpannedInto(int32_t aRowIndex, |
387 | | int32_t aNumEffCols) const; |
388 | | |
389 | | bool RowHasSpanningCells(int32_t aRowIndex, |
390 | | int32_t aNumEffCols) const; |
391 | | |
392 | | /** indicate whether the row has more than one cell that either originates |
393 | | * or is spanned from the rows above |
394 | | */ |
395 | | bool HasMoreThanOneCell(int32_t aRowIndex) const; |
396 | | |
397 | | /* Get the rowspan for a cell starting at aRowIndex and aColIndex. |
398 | | * If aGetEffective is true the size will not exceed the last content based |
399 | | * row. Cells can have a specified rowspan that extends below the last |
400 | | * content based row. This is legitimate considering incr. reflow where the |
401 | | * content rows will arive later. |
402 | | */ |
403 | | int32_t GetRowSpan(int32_t aRowIndex, |
404 | | int32_t aColIndex, |
405 | | bool aGetEffective) const; |
406 | | |
407 | | int32_t GetEffectiveColSpan(const nsTableCellMap& aMap, |
408 | | int32_t aRowIndex, |
409 | | int32_t aColIndex) const; |
410 | | |
411 | | typedef nsTArray<CellData*> CellDataArray; |
412 | | |
413 | | /** dump a representation of the cell map to stdout for debugging */ |
414 | | #ifdef DEBUG |
415 | | void Dump(bool aIsBorderCollapse) const; |
416 | | #endif |
417 | | |
418 | | protected: |
419 | | friend class nsTableCellMap; |
420 | | friend class BCMapCellIterator; |
421 | | friend class BCPaintBorderIterator; |
422 | | friend class nsTableFrame; |
423 | | friend class nsCellMapColumnIterator; |
424 | | |
425 | | /** |
426 | | * Increase the number of rows in this cellmap by aNumRows. Put the |
427 | | * new rows at aRowIndex. If aRowIndex is -1, put them at the end. |
428 | | */ |
429 | | bool Grow(nsTableCellMap& aMap, |
430 | | int32_t aNumRows, |
431 | | int32_t aRowIndex = -1); |
432 | | |
433 | | void GrowRow(CellDataArray& aRow, |
434 | | int32_t aNumCols); |
435 | | |
436 | | /** assign aCellData to the cell at (aRow,aColumn) */ |
437 | | void SetDataAt(nsTableCellMap& aMap, |
438 | | CellData& aCellData, |
439 | | int32_t aMapRowIndex, |
440 | | int32_t aColIndex); |
441 | | |
442 | | CellData* GetDataAt(int32_t aMapRowIndex, |
443 | | int32_t aColIndex) const; |
444 | | |
445 | | int32_t GetNumCellsIn(int32_t aColIndex) const; |
446 | | |
447 | | void ExpandWithRows(nsTableCellMap& aMap, |
448 | | nsTArray<nsTableRowFrame*>& aRowFrames, |
449 | | int32_t aStartRowIndex, |
450 | | int32_t aRgFirstRowIndex, |
451 | | TableArea& aDamageArea); |
452 | | |
453 | | void ExpandWithCells(nsTableCellMap& aMap, |
454 | | nsTArray<nsTableCellFrame*>& aCellFrames, |
455 | | int32_t aRowIndex, |
456 | | int32_t aColIndex, |
457 | | int32_t aRowSpan, |
458 | | bool aRowSpanIsZero, |
459 | | int32_t aRgFirstRowIndex, |
460 | | TableArea& aDamageArea); |
461 | | |
462 | | void ShrinkWithoutRows(nsTableCellMap& aMap, |
463 | | int32_t aFirstRowIndex, |
464 | | int32_t aNumRowsToRemove, |
465 | | int32_t aRgFirstRowIndex, |
466 | | TableArea& aDamageArea); |
467 | | |
468 | | void ShrinkWithoutCell(nsTableCellMap& aMap, |
469 | | nsTableCellFrame& aCellFrame, |
470 | | int32_t aRowIndex, |
471 | | int32_t aColIndex, |
472 | | int32_t aRgFirstRowIndex, |
473 | | TableArea& aDamageArea); |
474 | | |
475 | | /** |
476 | | * Rebuild due to rows being inserted or deleted with cells spanning |
477 | | * into or out of the rows. This function can only handle insertion |
478 | | * or deletion but NOT both. So either aRowsToInsert must be null |
479 | | * or aNumRowsToRemove must be 0. |
480 | | * |
481 | | * // XXXbz are both allowed to happen? That'd be a no-op... |
482 | | */ |
483 | | void RebuildConsideringRows(nsTableCellMap& aMap, |
484 | | int32_t aStartRowIndex, |
485 | | nsTArray<nsTableRowFrame*>* aRowsToInsert, |
486 | | int32_t aNumRowsToRemove); |
487 | | |
488 | | void RebuildConsideringCells(nsTableCellMap& aMap, |
489 | | int32_t aNumOrigCols, |
490 | | nsTArray<nsTableCellFrame*>* aCellFrames, |
491 | | int32_t aRowIndex, |
492 | | int32_t aColIndex, |
493 | | bool aInsert); |
494 | | |
495 | | bool CellsSpanOut(nsTArray<nsTableRowFrame*>& aNewRows) const; |
496 | | |
497 | | /** If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex |
498 | | * and aStartColIndex, aEndColIndex the cellmap changes are more severe so |
499 | | * the corresponding routines needs to be called. This is also necessary if |
500 | | * cells outside spans into this region. |
501 | | * @aStartRowIndex - y start index |
502 | | * @aEndRowIndex - y end index |
503 | | * @param aStartColIndex - x start index |
504 | | * @param aEndColIndex - x end index |
505 | | * @return - true if a cell span crosses the border of the |
506 | | region |
507 | | */ |
508 | | bool CellsSpanInOrOut(int32_t aStartRowIndex, |
509 | | int32_t aEndRowIndex, |
510 | | int32_t aStartColIndex, |
511 | | int32_t aEndColIndex) const; |
512 | | |
513 | | bool CreateEmptyRow(int32_t aRowIndex, |
514 | | int32_t aNumCols); |
515 | | |
516 | | int32_t GetRowSpanForNewCell(nsTableCellFrame* aCellFrameToAdd, |
517 | | int32_t aRowIndex, |
518 | | bool& aIsZeroRowSpan) const; |
519 | | |
520 | | // Destroy a CellData struct. This will handle the case of aData |
521 | | // actually being a BCCellData properly. |
522 | | void DestroyCellData(CellData* aData); |
523 | | // Allocate a CellData struct. This will handle needing to create a |
524 | | // BCCellData properly. |
525 | | // @param aOrigCell the originating cell to pass to the celldata constructor |
526 | | CellData* AllocCellData(nsTableCellFrame* aOrigCell); |
527 | | |
528 | | /** an array containing, for each row, the CellDatas for the cells |
529 | | * in that row. It can be larger than mContentRowCount due to row spans |
530 | | * extending beyond the table */ |
531 | | // XXXbz once we have auto TArrays, we should probably use them here. |
532 | | nsTArray<CellDataArray> mRows; |
533 | | |
534 | | /** the number of rows in the table (content) which is not indentical to the |
535 | | * number of rows in the cell map due to row spans extending beyond the end |
536 | | * of thetable (dead rows) or empty tr tags |
537 | | */ |
538 | | int32_t mContentRowCount; |
539 | | |
540 | | // the row group that corresponds to this map |
541 | | nsTableRowGroupFrame* mRowGroupFrame; |
542 | | |
543 | | // the next row group cell map |
544 | | nsCellMap* mNextSibling; |
545 | | |
546 | | // Whether this is a BC cellmap or not |
547 | | bool mIsBC; |
548 | | |
549 | | // Prescontext to deallocate and allocate celldata |
550 | | RefPtr<nsPresContext> mPresContext; |
551 | | }; |
552 | | |
553 | | /** |
554 | | * A class for iterating the cells in a given column. Must be given a |
555 | | * non-null nsTableCellMap and a column number valid for that cellmap. |
556 | | */ |
557 | | class nsCellMapColumnIterator |
558 | | { |
559 | | public: |
560 | | nsCellMapColumnIterator(const nsTableCellMap* aMap, int32_t aCol) : |
561 | | mMap(aMap), mCurMap(aMap->mFirstMap), mCurMapStart(0), |
562 | | mCurMapRow(0), mCol(aCol), mFoundCells(0), |
563 | | mCurMapContentRowCount(0), mCurMapRelevantRowCount(0) |
564 | 0 | { |
565 | 0 | MOZ_ASSERT(aMap, "Must have map"); |
566 | 0 | MOZ_ASSERT(mCol < aMap->GetColCount(), "Invalid column"); |
567 | 0 | mOrigCells = aMap->GetNumCellsOriginatingInCol(mCol); |
568 | 0 | if (mCurMap) { |
569 | 0 | mCurMapContentRowCount = mCurMap->GetRowCount(); |
570 | 0 | uint32_t rowArrayLength = mCurMap->mRows.Length(); |
571 | 0 | mCurMapRelevantRowCount = std::min(mCurMapContentRowCount, rowArrayLength); |
572 | 0 | if (mCurMapRelevantRowCount == 0 && mOrigCells > 0) { |
573 | 0 | // This row group is useless; advance! |
574 | 0 | AdvanceRowGroup(); |
575 | 0 | } |
576 | 0 | } |
577 | | #ifdef DEBUG |
578 | | else { |
579 | | NS_ASSERTION(mOrigCells == 0, "Why no rowgroups?"); |
580 | | } |
581 | | #endif |
582 | | } |
583 | | |
584 | | nsTableCellFrame* GetNextFrame(int32_t* aRow, int32_t* aColSpan); |
585 | | |
586 | | private: |
587 | | void AdvanceRowGroup(); |
588 | | |
589 | | // Advance the row; aIncrement is considered to be a cell's rowspan, |
590 | | // so if 0 is passed in we'll advance to the next rowgroup. |
591 | | void IncrementRow(int32_t aIncrement); |
592 | | |
593 | | const nsTableCellMap* mMap; |
594 | | const nsCellMap* mCurMap; |
595 | | |
596 | | // mCurMapStart is the row in the entire nsTableCellMap where |
597 | | // mCurMap starts. This is used to compute row indices to pass to |
598 | | // nsTableCellMap::GetDataAt, so must be a _content_ row index. |
599 | | uint32_t mCurMapStart; |
600 | | |
601 | | // In steady-state mCurMapRow is the row in our current nsCellMap |
602 | | // that we'll use the next time GetNextFrame() is called. Due to |
603 | | // the way we skip over rowspans, the entry in mCurMapRow and mCol |
604 | | // is either null, dead, originating, or a colspan. In particular, |
605 | | // it cannot be a rowspan or overlap entry. |
606 | | uint32_t mCurMapRow; |
607 | | const int32_t mCol; |
608 | | uint32_t mOrigCells; |
609 | | uint32_t mFoundCells; |
610 | | |
611 | | // The number of content rows in mCurMap. This may be bigger than the number |
612 | | // of "relevant" rows, or it might be smaller. |
613 | | uint32_t mCurMapContentRowCount; |
614 | | |
615 | | // The number of "relevant" rows in mCurMap. That is, the number of rows |
616 | | // which might have an originating cell in them. Once mCurMapRow reaches |
617 | | // mCurMapRelevantRowCount, we should move to the next map. |
618 | | uint32_t mCurMapRelevantRowCount; |
619 | | }; |
620 | | |
621 | | |
622 | | /* ----- inline methods ----- */ |
623 | | inline int32_t nsTableCellMap::GetColCount() const |
624 | 0 | { |
625 | 0 | return mCols.Length(); |
626 | 0 | } |
627 | | |
628 | | inline nsCellMap* nsCellMap::GetNextSibling() const |
629 | 0 | { |
630 | 0 | return mNextSibling; |
631 | 0 | } |
632 | | |
633 | | inline void nsCellMap::SetNextSibling(nsCellMap* aSibling) |
634 | 0 | { |
635 | 0 | mNextSibling = aSibling; |
636 | 0 | } |
637 | | |
638 | | inline nsTableRowGroupFrame* nsCellMap::GetRowGroup() const |
639 | 0 | { |
640 | 0 | return mRowGroupFrame; |
641 | 0 | } |
642 | | |
643 | | inline int32_t nsCellMap::GetRowCount(bool aConsiderDeadRowSpanRows) const |
644 | 0 | { |
645 | 0 | int32_t rowCount = (aConsiderDeadRowSpanRows) ? mRows.Length() : mContentRowCount; |
646 | 0 | return rowCount; |
647 | 0 | } |
648 | | |
649 | | // nsColInfo |
650 | | |
651 | | inline nsColInfo::nsColInfo() |
652 | | :mNumCellsOrig(0), mNumCellsSpan(0) |
653 | 0 | {} |
654 | | |
655 | | inline nsColInfo::nsColInfo(int32_t aNumCellsOrig, |
656 | | int32_t aNumCellsSpan) |
657 | | :mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan) |
658 | | {} |
659 | | |
660 | | |
661 | | #endif |