OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) |
3 * (C) 1997 Torben Weis (weis@kde.org) | 3 * (C) 1997 Torben Weis (weis@kde.org) |
4 * (C) 1998 Waldo Bastian (bastian@kde.org) | 4 * (C) 1998 Waldo Bastian (bastian@kde.org) |
5 * (C) 1999 Lars Knoll (knoll@kde.org) | 5 * (C) 1999 Lars Knoll (knoll@kde.org) |
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. All r
ights reserved. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. |
| 8 * All rights reserved. |
8 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
9 * | 10 * |
10 * This library is free software; you can redistribute it and/or | 11 * This library is free software; you can redistribute it and/or |
11 * modify it under the terms of the GNU Library General Public | 12 * modify it under the terms of the GNU Library General Public |
12 * License as published by the Free Software Foundation; either | 13 * License as published by the Free Software Foundation; either |
13 * version 2 of the License, or (at your option) any later version. | 14 * version 2 of the License, or (at your option) any later version. |
14 * | 15 * |
15 * This library is distributed in the hope that it will be useful, | 16 * This library is distributed in the hope that it will be useful, |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
(...skipping 16 matching lines...) Expand all Loading... |
34 #include "core/layout/SubtreeLayoutScope.h" | 35 #include "core/layout/SubtreeLayoutScope.h" |
35 #include "core/paint/TableSectionPainter.h" | 36 #include "core/paint/TableSectionPainter.h" |
36 #include "wtf/HashSet.h" | 37 #include "wtf/HashSet.h" |
37 #include <algorithm> | 38 #include <algorithm> |
38 #include <limits> | 39 #include <limits> |
39 | 40 |
40 namespace blink { | 41 namespace blink { |
41 | 42 |
42 using namespace HTMLNames; | 43 using namespace HTMLNames; |
43 | 44 |
44 // This variable is used to balance the memory consumption vs the paint invalida
tion time on big tables. | 45 // This variable is used to balance the memory consumption vs the paint |
| 46 // invalidation time on big tables. |
45 static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75; | 47 static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75; |
46 | 48 |
47 static inline void setRowLogicalHeightToRowStyleLogicalHeight( | 49 static inline void setRowLogicalHeightToRowStyleLogicalHeight( |
48 LayoutTableSection::RowStruct& row) { | 50 LayoutTableSection::RowStruct& row) { |
49 ASSERT(row.rowLayoutObject); | 51 ASSERT(row.rowLayoutObject); |
50 row.logicalHeight = row.rowLayoutObject->style()->logicalHeight(); | 52 row.logicalHeight = row.rowLayoutObject->style()->logicalHeight(); |
51 } | 53 } |
52 | 54 |
53 static inline void updateLogicalHeightForCell( | 55 static inline void updateLogicalHeightForCell( |
54 LayoutTableSection::RowStruct& row, | 56 LayoutTableSection::RowStruct& row, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 | 163 |
162 if (beforeChild && !beforeChild->isAnonymous() && | 164 if (beforeChild && !beforeChild->isAnonymous() && |
163 beforeChild->parent() == this) { | 165 beforeChild->parent() == this) { |
164 LayoutObject* row = beforeChild->previousSibling(); | 166 LayoutObject* row = beforeChild->previousSibling(); |
165 if (row && row->isTableRow() && row->isAnonymous()) { | 167 if (row && row->isTableRow() && row->isAnonymous()) { |
166 row->addChild(child); | 168 row->addChild(child); |
167 return; | 169 return; |
168 } | 170 } |
169 } | 171 } |
170 | 172 |
171 // If beforeChild is inside an anonymous cell/row, insert into the cell or i
nto | 173 // If beforeChild is inside an anonymous cell/row, insert into the cell or |
172 // the anonymous row containing it, if there is one. | 174 // into the anonymous row containing it, if there is one. |
173 LayoutObject* lastBox = last; | 175 LayoutObject* lastBox = last; |
174 while (lastBox && lastBox->parent()->isAnonymous() && | 176 while (lastBox && lastBox->parent()->isAnonymous() && |
175 !lastBox->isTableRow()) | 177 !lastBox->isTableRow()) |
176 lastBox = lastBox->parent(); | 178 lastBox = lastBox->parent(); |
177 if (lastBox && lastBox->isAnonymous() && | 179 if (lastBox && lastBox->isAnonymous() && |
178 !lastBox->isBeforeOrAfterContent()) { | 180 !lastBox->isBeforeOrAfterContent()) { |
179 lastBox->addChild(child, beforeChild); | 181 lastBox->addChild(child, beforeChild); |
180 return; | 182 return; |
181 } | 183 } |
182 | 184 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 for (; row && row != previousCell->row(); row = row->previousRow()) { | 244 for (; row && row != previousCell->row(); row = row->previousRow()) { |
243 } | 245 } |
244 ASSERT(row == previousCell->row()); | 246 ASSERT(row == previousCell->row()); |
245 | 247 |
246 previousCell = currentCell; | 248 previousCell = currentCell; |
247 } | 249 } |
248 #endif // NDEBUG | 250 #endif // NDEBUG |
249 } | 251 } |
250 | 252 |
251 void LayoutTableSection::addCell(LayoutTableCell* cell, LayoutTableRow* row) { | 253 void LayoutTableSection::addCell(LayoutTableCell* cell, LayoutTableRow* row) { |
252 // We don't insert the cell if we need cell recalc as our internal columns' re
presentation | 254 // We don't insert the cell if we need cell recalc as our internal columns' |
253 // will have drifted from the table's representation. Also recalcCells will ca
ll addCell | 255 // representation will have drifted from the table's representation. Also |
254 // at a later time after sync'ing our columns' with the table's. | 256 // recalcCells will call addCell at a later time after sync'ing our columns' |
| 257 // with the table's. |
255 if (needsCellRecalc()) | 258 if (needsCellRecalc()) |
256 return; | 259 return; |
257 | 260 |
258 unsigned rSpan = cell->rowSpan(); | 261 unsigned rSpan = cell->rowSpan(); |
259 unsigned cSpan = cell->colSpan(); | 262 unsigned cSpan = cell->colSpan(); |
260 const Vector<LayoutTable::ColumnStruct>& columns = | 263 const Vector<LayoutTable::ColumnStruct>& columns = |
261 table()->effectiveColumns(); | 264 table()->effectiveColumns(); |
262 unsigned nCols = columns.size(); | 265 unsigned nCols = columns.size(); |
263 unsigned insertionRow = row->rowIndex(); | 266 unsigned insertionRow = row->rowIndex(); |
264 | 267 |
265 // ### mozilla still seems to do the old HTML way, even for strict DTD | 268 // ### mozilla still seems to do the old HTML way, even for strict DTD |
266 // (see the annotation on table cell layouting in the CSS specs and the testca
se below: | 269 // (see the annotation on table cell layouting in the CSS specs and the |
| 270 // testcase below: |
267 // <TABLE border> | 271 // <TABLE border> |
268 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4 | 272 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4 |
269 // <TR><TD colspan="2">5 | 273 // <TR><TD colspan="2">5 |
270 // </TABLE> | 274 // </TABLE> |
271 while (m_cCol < nCols && (cellAt(insertionRow, m_cCol).hasCells() || | 275 while (m_cCol < nCols && (cellAt(insertionRow, m_cCol).hasCells() || |
272 cellAt(insertionRow, m_cCol).inColSpan)) | 276 cellAt(insertionRow, m_cCol).inColSpan)) |
273 m_cCol++; | 277 m_cCol++; |
274 | 278 |
275 updateLogicalHeightForCell(m_grid[insertionRow], cell); | 279 updateLogicalHeightForCell(m_grid[insertionRow], cell); |
276 | 280 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 m_rowPos[actualRow] - | 351 m_rowPos[actualRow] - |
348 borderSpacingForRow(actualRow); | 352 borderSpacingForRow(actualRow); |
349 if (!spanningRowsHeight.rowHeight[row]) | 353 if (!spanningRowsHeight.rowHeight[row]) |
350 spanningRowsHeight.isAnyRowWithOnlySpanningCells |= | 354 spanningRowsHeight.isAnyRowWithOnlySpanningCells |= |
351 rowHasOnlySpanningCells(actualRow); | 355 rowHasOnlySpanningCells(actualRow); |
352 | 356 |
353 spanningRowsHeight.totalRowsHeight += spanningRowsHeight.rowHeight[row]; | 357 spanningRowsHeight.totalRowsHeight += spanningRowsHeight.rowHeight[row]; |
354 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing -= | 358 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing -= |
355 borderSpacingForRow(actualRow); | 359 borderSpacingForRow(actualRow); |
356 } | 360 } |
357 // We don't span the following row so its border-spacing (if any) should be in
cluded. | 361 // We don't span the following row so its border-spacing (if any) should be |
| 362 // included. |
358 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing += | 363 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing += |
359 borderSpacingForRow(rowIndex + rowSpan - 1); | 364 borderSpacingForRow(rowIndex + rowSpan - 1); |
360 } | 365 } |
361 | 366 |
362 void LayoutTableSection::distributeExtraRowSpanHeightToPercentRows( | 367 void LayoutTableSection::distributeExtraRowSpanHeightToPercentRows( |
363 LayoutTableCell* cell, | 368 LayoutTableCell* cell, |
364 float totalPercent, | 369 float totalPercent, |
365 int& extraRowSpanningHeight, | 370 int& extraRowSpanningHeight, |
366 Vector<int>& rowsHeight) { | 371 Vector<int>& rowsHeight) { |
367 if (!extraRowSpanningHeight || !totalPercent) | 372 if (!extraRowSpanningHeight || !totalPercent) |
368 return; | 373 return; |
369 | 374 |
370 const unsigned rowSpan = cell->rowSpan(); | 375 const unsigned rowSpan = cell->rowSpan(); |
371 const unsigned rowIndex = cell->rowIndex(); | 376 const unsigned rowIndex = cell->rowIndex(); |
372 float percent = std::min(totalPercent, 100.0f); | 377 float percent = std::min(totalPercent, 100.0f); |
373 const int tableHeight = m_rowPos[m_grid.size()] + extraRowSpanningHeight; | 378 const int tableHeight = m_rowPos[m_grid.size()] + extraRowSpanningHeight; |
374 | 379 |
375 // Our algorithm matches Firefox. Extra spanning height would be distributed O
nly in first percent height rows | 380 // Our algorithm matches Firefox. Extra spanning height would be distributed |
376 // those total percent is 100. Other percent rows would be uneffected even ext
ra spanning height is remain. | 381 // Only in first percent height rows those total percent is 100. Other percent |
| 382 // rows would be uneffected even extra spanning height is remain. |
377 int accumulatedPositionIncrease = 0; | 383 int accumulatedPositionIncrease = 0; |
378 for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 384 for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { |
379 if (percent > 0 && extraRowSpanningHeight > 0) { | 385 if (percent > 0 && extraRowSpanningHeight > 0) { |
380 // TODO(alancutter): Make this work correctly for calc lengths. | 386 // TODO(alancutter): Make this work correctly for calc lengths. |
381 if (m_grid[row].logicalHeight.isPercent()) { | 387 if (m_grid[row].logicalHeight.isPercent()) { |
382 int toAdd = | 388 int toAdd = |
383 (tableHeight * | 389 (tableHeight * |
384 std::min(m_grid[row].logicalHeight.percent(), percent) / 100) - | 390 std::min(m_grid[row].logicalHeight.percent(), percent) / 100) - |
385 rowsHeight[row - rowIndex]; | 391 rowsHeight[row - rowIndex]; |
386 | 392 |
(...skipping 10 matching lines...) Expand all Loading... |
397 static void updatePositionIncreasedWithRowHeight( | 403 static void updatePositionIncreasedWithRowHeight( |
398 int extraHeight, | 404 int extraHeight, |
399 float rowHeight, | 405 float rowHeight, |
400 float totalHeight, | 406 float totalHeight, |
401 int& accumulatedPositionIncrease, | 407 int& accumulatedPositionIncrease, |
402 double& remainder) { | 408 double& remainder) { |
403 // Without the cast we lose enough precision to cause heights to miss pixels | 409 // Without the cast we lose enough precision to cause heights to miss pixels |
404 // (and trigger asserts) in some layout tests. | 410 // (and trigger asserts) in some layout tests. |
405 double proportionalPositionIncrease = | 411 double proportionalPositionIncrease = |
406 remainder + (extraHeight * double(rowHeight)) / totalHeight; | 412 remainder + (extraHeight * double(rowHeight)) / totalHeight; |
407 // The epsilon is to push any values that are close to a whole number but aren
't due to floating point imprecision. | 413 // The epsilon is to push any values that are close to a whole number but |
408 // The epsilons are not accumulated, any that aren't necessary are lost in the
cast to int. | 414 // aren't due to floating point imprecision. The epsilons are not accumulated, |
| 415 // any that aren't necessary are lost in the cast to int. |
409 int positionIncreaseInt = proportionalPositionIncrease + 0.000001; | 416 int positionIncreaseInt = proportionalPositionIncrease + 0.000001; |
410 accumulatedPositionIncrease += positionIncreaseInt; | 417 accumulatedPositionIncrease += positionIncreaseInt; |
411 remainder = proportionalPositionIncrease - positionIncreaseInt; | 418 remainder = proportionalPositionIncrease - positionIncreaseInt; |
412 } | 419 } |
413 | 420 |
414 // This is mainly used to distribute whole extra rowspanning height in percent r
ows when all spanning rows are | 421 // This is mainly used to distribute whole extra rowspanning height in percent |
415 // percent rows. | 422 // rows when all spanning rows are percent rows. |
416 // Distributing whole extra rowspanning height in percent rows based on the rati
os of percent because this method works | 423 // Distributing whole extra rowspanning height in percent rows based on the |
417 // same as percent distribution when only percent rows are present and percent i
s 100. Also works perfectly fine when | 424 // ratios of percent because this method works same as percent distribution when |
418 // percent is not equal to 100. | 425 // only percent rows are present and percent is 100. Also works perfectly fine |
| 426 // when percent is not equal to 100. |
419 void LayoutTableSection::distributeWholeExtraRowSpanHeightToPercentRows( | 427 void LayoutTableSection::distributeWholeExtraRowSpanHeightToPercentRows( |
420 LayoutTableCell* cell, | 428 LayoutTableCell* cell, |
421 float totalPercent, | 429 float totalPercent, |
422 int& extraRowSpanningHeight, | 430 int& extraRowSpanningHeight, |
423 Vector<int>& rowsHeight) { | 431 Vector<int>& rowsHeight) { |
424 if (!extraRowSpanningHeight || !totalPercent) | 432 if (!extraRowSpanningHeight || !totalPercent) |
425 return; | 433 return; |
426 | 434 |
427 const unsigned rowSpan = cell->rowSpan(); | 435 const unsigned rowSpan = cell->rowSpan(); |
428 const unsigned rowIndex = cell->rowIndex(); | 436 const unsigned rowIndex = cell->rowIndex(); |
(...skipping 21 matching lines...) Expand all Loading... |
450 int& extraRowSpanningHeight, | 458 int& extraRowSpanningHeight, |
451 Vector<int>& rowsHeight) { | 459 Vector<int>& rowsHeight) { |
452 if (!extraRowSpanningHeight || !totalAutoRowsHeight) | 460 if (!extraRowSpanningHeight || !totalAutoRowsHeight) |
453 return; | 461 return; |
454 | 462 |
455 const unsigned rowSpan = cell->rowSpan(); | 463 const unsigned rowSpan = cell->rowSpan(); |
456 const unsigned rowIndex = cell->rowIndex(); | 464 const unsigned rowIndex = cell->rowIndex(); |
457 int accumulatedPositionIncrease = 0; | 465 int accumulatedPositionIncrease = 0; |
458 double remainder = 0; | 466 double remainder = 0; |
459 | 467 |
460 // Aspect ratios of auto rows should not change otherwise table may look diffe
rent than user expected. | 468 // Aspect ratios of auto rows should not change otherwise table may look |
461 // So extra height distributed in auto spanning rows based on their weight in
spanning cell. | 469 // different than user expected. So extra height distributed in auto spanning |
| 470 // rows based on their weight in spanning cell. |
462 for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 471 for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { |
463 if (m_grid[row].logicalHeight.isAuto()) { | 472 if (m_grid[row].logicalHeight.isAuto()) { |
464 updatePositionIncreasedWithRowHeight( | 473 updatePositionIncreasedWithRowHeight( |
465 extraRowSpanningHeight, rowsHeight[row - rowIndex], | 474 extraRowSpanningHeight, rowsHeight[row - rowIndex], |
466 totalAutoRowsHeight, accumulatedPositionIncrease, remainder); | 475 totalAutoRowsHeight, accumulatedPositionIncrease, remainder); |
467 } | 476 } |
468 m_rowPos[row + 1] += accumulatedPositionIncrease; | 477 m_rowPos[row + 1] += accumulatedPositionIncrease; |
469 } | 478 } |
470 | 479 |
471 DCHECK(!round(remainder)) << "remainder was " << remainder; | 480 DCHECK(!round(remainder)) << "remainder was " << remainder; |
472 | 481 |
473 extraRowSpanningHeight -= accumulatedPositionIncrease; | 482 extraRowSpanningHeight -= accumulatedPositionIncrease; |
474 } | 483 } |
475 | 484 |
476 void LayoutTableSection::distributeExtraRowSpanHeightToRemainingRows( | 485 void LayoutTableSection::distributeExtraRowSpanHeightToRemainingRows( |
477 LayoutTableCell* cell, | 486 LayoutTableCell* cell, |
478 int totalRemainingRowsHeight, | 487 int totalRemainingRowsHeight, |
479 int& extraRowSpanningHeight, | 488 int& extraRowSpanningHeight, |
480 Vector<int>& rowsHeight) { | 489 Vector<int>& rowsHeight) { |
481 if (!extraRowSpanningHeight || !totalRemainingRowsHeight) | 490 if (!extraRowSpanningHeight || !totalRemainingRowsHeight) |
482 return; | 491 return; |
483 | 492 |
484 const unsigned rowSpan = cell->rowSpan(); | 493 const unsigned rowSpan = cell->rowSpan(); |
485 const unsigned rowIndex = cell->rowIndex(); | 494 const unsigned rowIndex = cell->rowIndex(); |
486 int accumulatedPositionIncrease = 0; | 495 int accumulatedPositionIncrease = 0; |
487 double remainder = 0; | 496 double remainder = 0; |
488 | 497 |
489 // Aspect ratios of the rows should not change otherwise table may look differ
ent than user expected. | 498 // Aspect ratios of the rows should not change otherwise table may look |
490 // So extra height distribution in remaining spanning rows based on their weig
ht in spanning cell. | 499 // different than user expected. So extra height distribution in remaining |
| 500 // spanning rows based on their weight in spanning cell. |
491 for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 501 for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { |
492 if (!m_grid[row].logicalHeight.isPercentOrCalc()) { | 502 if (!m_grid[row].logicalHeight.isPercentOrCalc()) { |
493 updatePositionIncreasedWithRowHeight( | 503 updatePositionIncreasedWithRowHeight( |
494 extraRowSpanningHeight, rowsHeight[row - rowIndex], | 504 extraRowSpanningHeight, rowsHeight[row - rowIndex], |
495 totalRemainingRowsHeight, accumulatedPositionIncrease, remainder); | 505 totalRemainingRowsHeight, accumulatedPositionIncrease, remainder); |
496 } | 506 } |
497 m_rowPos[row + 1] += accumulatedPositionIncrease; | 507 m_rowPos[row + 1] += accumulatedPositionIncrease; |
498 } | 508 } |
499 | 509 |
500 DCHECK(!round(remainder)) << "remainder was " << remainder; | 510 DCHECK(!round(remainder)) << "remainder was " << remainder; |
501 | 511 |
502 extraRowSpanningHeight -= accumulatedPositionIncrease; | 512 extraRowSpanningHeight -= accumulatedPositionIncrease; |
503 } | 513 } |
504 | 514 |
505 static bool cellIsFullyIncludedInOtherCell(const LayoutTableCell* cell1, | 515 static bool cellIsFullyIncludedInOtherCell(const LayoutTableCell* cell1, |
506 const LayoutTableCell* cell2) { | 516 const LayoutTableCell* cell2) { |
507 return (cell1->rowIndex() >= cell2->rowIndex() && | 517 return (cell1->rowIndex() >= cell2->rowIndex() && |
508 (cell1->rowIndex() + cell1->rowSpan()) <= | 518 (cell1->rowIndex() + cell1->rowSpan()) <= |
509 (cell2->rowIndex() + cell2->rowSpan())); | 519 (cell2->rowIndex() + cell2->rowSpan())); |
510 } | 520 } |
511 | 521 |
512 // To avoid unneeded extra height distributions, we apply the following sorting
algorithm: | 522 // To avoid unneeded extra height distributions, we apply the following sorting |
| 523 // algorithm: |
513 static bool compareRowSpanCellsInHeightDistributionOrder( | 524 static bool compareRowSpanCellsInHeightDistributionOrder( |
514 const LayoutTableCell* cell1, | 525 const LayoutTableCell* cell1, |
515 const LayoutTableCell* cell2) { | 526 const LayoutTableCell* cell2) { |
516 // Sorting bigger height cell first if cells are at same index with same span
because we will skip smaller | 527 // Sorting bigger height cell first if cells are at same index with same span |
517 // height cell to distribute it's extra height. | 528 // because we will skip smaller height cell to distribute it's extra height. |
518 if (cell1->rowIndex() == cell2->rowIndex() && | 529 if (cell1->rowIndex() == cell2->rowIndex() && |
519 cell1->rowSpan() == cell2->rowSpan()) | 530 cell1->rowSpan() == cell2->rowSpan()) |
520 return (cell1->logicalHeightForRowSizing() > | 531 return (cell1->logicalHeightForRowSizing() > |
521 cell2->logicalHeightForRowSizing()); | 532 cell2->logicalHeightForRowSizing()); |
522 // Sorting inner most cell first because if inner spanning cell'e extra height
is distributed then outer | 533 // Sorting inner most cell first because if inner spanning cell'e extra height |
523 // spanning cell's extra height will adjust accordingly. In reverse order, the
re is more chances that outer | 534 // is distributed then outer spanning cell's extra height will adjust |
524 // spanning cell's height will exceed than defined by user. | 535 // accordingly. In reverse order, there is more chances that outer spanning |
| 536 // cell's height will exceed than defined by user. |
525 if (cellIsFullyIncludedInOtherCell(cell1, cell2)) | 537 if (cellIsFullyIncludedInOtherCell(cell1, cell2)) |
526 return true; | 538 return true; |
527 // Sorting lower row index first because first we need to apply the extra heig
ht of spanning cell which | 539 // Sorting lower row index first because first we need to apply the extra |
528 // comes first in the table so lower rows's position would increment in sequen
ce. | 540 // height of spanning cell which comes first in the table so lower rows's |
| 541 // position would increment in sequence. |
529 if (!cellIsFullyIncludedInOtherCell(cell2, cell1)) | 542 if (!cellIsFullyIncludedInOtherCell(cell2, cell1)) |
530 return (cell1->rowIndex() < cell2->rowIndex()); | 543 return (cell1->rowIndex() < cell2->rowIndex()); |
531 | 544 |
532 return false; | 545 return false; |
533 } | 546 } |
534 | 547 |
535 unsigned LayoutTableSection::calcRowHeightHavingOnlySpanningCells( | 548 unsigned LayoutTableSection::calcRowHeightHavingOnlySpanningCells( |
536 unsigned row, | 549 unsigned row, |
537 int& accumulatedCellPositionIncrease, | 550 int& accumulatedCellPositionIncrease, |
538 unsigned rowToApplyExtraHeight, | 551 unsigned rowToApplyExtraHeight, |
(...skipping 15 matching lines...) Expand all Loading... |
554 continue; | 567 continue; |
555 | 568 |
556 LayoutTableCell* cell = rowSpanCell.cells[0]; | 569 LayoutTableCell* cell = rowSpanCell.cells[0]; |
557 | 570 |
558 if (cell->rowSpan() < 2) | 571 if (cell->rowSpan() < 2) |
559 continue; | 572 continue; |
560 | 573 |
561 const unsigned cellRowIndex = cell->rowIndex(); | 574 const unsigned cellRowIndex = cell->rowIndex(); |
562 const unsigned cellRowSpan = cell->rowSpan(); | 575 const unsigned cellRowSpan = cell->rowSpan(); |
563 | 576 |
564 // As we are going from the top of the table to the bottom to calculate the
row | 577 // As we are going from the top of the table to the bottom to calculate the |
565 // heights for rows that only contain spanning cells and all previous rows a
re | 578 // row heights for rows that only contain spanning cells and all previous |
566 // processed we only need to find the number of rows with spanning cells fro
m the | 579 // rows are processed we only need to find the number of rows with spanning |
567 // current cell to the end of the current cells spanning height. | 580 // cells from the current cell to the end of the current cells spanning |
| 581 // height. |
568 unsigned startRowForSpanningCellCount = std::max(cellRowIndex, row); | 582 unsigned startRowForSpanningCellCount = std::max(cellRowIndex, row); |
569 unsigned endRow = cellRowIndex + cellRowSpan; | 583 unsigned endRow = cellRowIndex + cellRowSpan; |
570 unsigned spanningCellsRowsCountHavingZeroHeight = | 584 unsigned spanningCellsRowsCountHavingZeroHeight = |
571 rowsCountWithOnlySpanningCells[endRow - 1]; | 585 rowsCountWithOnlySpanningCells[endRow - 1]; |
572 | 586 |
573 if (startRowForSpanningCellCount) | 587 if (startRowForSpanningCellCount) |
574 spanningCellsRowsCountHavingZeroHeight -= | 588 spanningCellsRowsCountHavingZeroHeight -= |
575 rowsCountWithOnlySpanningCells[startRowForSpanningCellCount - 1]; | 589 rowsCountWithOnlySpanningCells[startRowForSpanningCellCount - 1]; |
576 | 590 |
577 int totalRowspanCellHeight = (m_rowPos[endRow] - m_rowPos[cellRowIndex]) - | 591 int totalRowspanCellHeight = (m_rowPos[endRow] - m_rowPos[cellRowIndex]) - |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 actualRow, accumulatedPositionIncrease, rowIndex + rowSpan, | 629 actualRow, accumulatedPositionIncrease, rowIndex + rowSpan, |
616 extraHeightToPropagate, rowsCountWithOnlySpanningCells); | 630 extraHeightToPropagate, rowsCountWithOnlySpanningCells); |
617 accumulatedPositionIncrease += spanningRowsHeight.rowHeight[row]; | 631 accumulatedPositionIncrease += spanningRowsHeight.rowHeight[row]; |
618 } | 632 } |
619 m_rowPos[actualRow + 1] += accumulatedPositionIncrease; | 633 m_rowPos[actualRow + 1] += accumulatedPositionIncrease; |
620 } | 634 } |
621 | 635 |
622 spanningRowsHeight.totalRowsHeight += accumulatedPositionIncrease; | 636 spanningRowsHeight.totalRowsHeight += accumulatedPositionIncrease; |
623 } | 637 } |
624 | 638 |
625 // Distribute rowSpan cell height in rows those comes in rowSpan cell based on t
he ratio of row's height if | 639 // Distribute rowSpan cell height in rows those comes in rowSpan cell based on |
626 // 1. RowSpan cell height is greater than the total height of rows in rowSpan ce
ll | 640 // the ratio of row's height if 1 RowSpan cell height is greater than the total |
| 641 // height of rows in rowSpan cell. |
627 void LayoutTableSection::distributeRowSpanHeightToRows( | 642 void LayoutTableSection::distributeRowSpanHeightToRows( |
628 SpanningLayoutTableCells& rowSpanCells) { | 643 SpanningLayoutTableCells& rowSpanCells) { |
629 ASSERT(rowSpanCells.size()); | 644 ASSERT(rowSpanCells.size()); |
630 | 645 |
631 // 'rowSpanCells' list is already sorted based on the cells rowIndex in ascend
ing order | 646 // 'rowSpanCells' list is already sorted based on the cells rowIndex in |
| 647 // ascending order |
632 // Arrange row spanning cell in the order in which we need to process first. | 648 // Arrange row spanning cell in the order in which we need to process first. |
633 std::sort(rowSpanCells.begin(), rowSpanCells.end(), | 649 std::sort(rowSpanCells.begin(), rowSpanCells.end(), |
634 compareRowSpanCellsInHeightDistributionOrder); | 650 compareRowSpanCellsInHeightDistributionOrder); |
635 | 651 |
636 unsigned extraHeightToPropagate = 0; | 652 unsigned extraHeightToPropagate = 0; |
637 unsigned lastRowIndex = 0; | 653 unsigned lastRowIndex = 0; |
638 unsigned lastRowSpan = 0; | 654 unsigned lastRowSpan = 0; |
639 | 655 |
640 Vector<int> rowsCountWithOnlySpanningCells; | 656 Vector<int> rowsCountWithOnlySpanningCells; |
641 | 657 |
642 // At this stage, Height of the rows are zero for the one containing only span
ning cells. | 658 // At this stage, Height of the rows are zero for the one containing only |
| 659 // spanning cells. |
643 int count = 0; | 660 int count = 0; |
644 for (unsigned row = 0; row < m_grid.size(); row++) { | 661 for (unsigned row = 0; row < m_grid.size(); row++) { |
645 if (rowHasOnlySpanningCells(row)) | 662 if (rowHasOnlySpanningCells(row)) |
646 count++; | 663 count++; |
647 rowsCountWithOnlySpanningCells.append(count); | 664 rowsCountWithOnlySpanningCells.append(count); |
648 } | 665 } |
649 | 666 |
650 for (unsigned i = 0; i < rowSpanCells.size(); i++) { | 667 for (unsigned i = 0; i < rowSpanCells.size(); i++) { |
651 LayoutTableCell* cell = rowSpanCells[i]; | 668 LayoutTableCell* cell = rowSpanCells[i]; |
652 | 669 |
653 unsigned rowIndex = cell->rowIndex(); | 670 unsigned rowIndex = cell->rowIndex(); |
654 | 671 |
655 unsigned rowSpan = cell->rowSpan(); | 672 unsigned rowSpan = cell->rowSpan(); |
656 | 673 |
657 unsigned spanningCellEndIndex = rowIndex + rowSpan; | 674 unsigned spanningCellEndIndex = rowIndex + rowSpan; |
658 unsigned lastSpanningCellEndIndex = lastRowIndex + lastRowSpan; | 675 unsigned lastSpanningCellEndIndex = lastRowIndex + lastRowSpan; |
659 | 676 |
660 // Only the highest spanning cell will distribute its extra height in a row
if more than one spanning cell | 677 // Only the highest spanning cell will distribute its extra height in a row |
661 // is present at the same level. | 678 // if more than one spanning cell is present at the same level. |
662 if (rowIndex == lastRowIndex && rowSpan == lastRowSpan) | 679 if (rowIndex == lastRowIndex && rowSpan == lastRowSpan) |
663 continue; | 680 continue; |
664 | 681 |
665 int originalBeforePosition = m_rowPos[spanningCellEndIndex]; | 682 int originalBeforePosition = m_rowPos[spanningCellEndIndex]; |
666 | 683 |
667 // When 2 spanning cells are ending at same row index then while extra heigh
t distribution of first spanning | 684 // When 2 spanning cells are ending at same row index then while extra |
668 // cell updates position of the last row so getting the original position of
the last row in second spanning | 685 // height distribution of first spanning cell updates position of the last |
| 686 // row so getting the original position of the last row in second spanning |
669 // cell need to reduce the height changed by first spanning cell. | 687 // cell need to reduce the height changed by first spanning cell. |
670 if (spanningCellEndIndex == lastSpanningCellEndIndex) | 688 if (spanningCellEndIndex == lastSpanningCellEndIndex) |
671 originalBeforePosition -= extraHeightToPropagate; | 689 originalBeforePosition -= extraHeightToPropagate; |
672 | 690 |
673 if (extraHeightToPropagate) { | 691 if (extraHeightToPropagate) { |
674 for (unsigned row = lastSpanningCellEndIndex + 1; | 692 for (unsigned row = lastSpanningCellEndIndex + 1; |
675 row <= spanningCellEndIndex; row++) | 693 row <= spanningCellEndIndex; row++) |
676 m_rowPos[row] += extraHeightToPropagate; | 694 m_rowPos[row] += extraHeightToPropagate; |
677 } | 695 } |
678 | 696 |
679 lastRowIndex = rowIndex; | 697 lastRowIndex = rowIndex; |
680 lastRowSpan = rowSpan; | 698 lastRowSpan = rowSpan; |
681 | 699 |
682 struct SpanningRowsHeight spanningRowsHeight; | 700 struct SpanningRowsHeight spanningRowsHeight; |
683 | 701 |
684 populateSpanningRowsHeightFromCell(cell, spanningRowsHeight); | 702 populateSpanningRowsHeightFromCell(cell, spanningRowsHeight); |
685 | 703 |
686 // Here we are handling only row(s) who have only rowspanning cells and do n
ot have any empty cell. | 704 // Here we are handling only row(s) who have only rowspanning cells and do |
| 705 // not have any empty cell. |
687 if (spanningRowsHeight.isAnyRowWithOnlySpanningCells) | 706 if (spanningRowsHeight.isAnyRowWithOnlySpanningCells) |
688 updateRowsHeightHavingOnlySpanningCells(cell, spanningRowsHeight, | 707 updateRowsHeightHavingOnlySpanningCells(cell, spanningRowsHeight, |
689 extraHeightToPropagate, | 708 extraHeightToPropagate, |
690 rowsCountWithOnlySpanningCells); | 709 rowsCountWithOnlySpanningCells); |
691 | 710 |
692 // This code handle row(s) that have rowspanning cell(s) and at least one em
pty cell. | 711 // This code handle row(s) that have rowspanning cell(s) and at least one |
693 // Such rows are not handled below and end up having a height of 0. That wou
ld mean | 712 // empty cell. Such rows are not handled below and end up having a height of |
694 // content overlapping if one of their cells has any content. To avoid the p
roblem, we | 713 // 0. That would mean content overlapping if one of their cells has any |
695 // add all the remaining spanning cells' height to the last spanned row. | 714 // content. To avoid the problem, we add all the remaining spanning cells' |
696 // This means that we could grow a row past its 'height' or break percentage
spreading | 715 // height to the last spanned row. This means that we could grow a row past |
697 // however this is better than overlapping content. | 716 // its 'height' or break percentage spreading however this is better than |
| 717 // overlapping content. |
698 // FIXME: Is there a better algorithm? | 718 // FIXME: Is there a better algorithm? |
699 if (!spanningRowsHeight.totalRowsHeight) { | 719 if (!spanningRowsHeight.totalRowsHeight) { |
700 if (spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing) | 720 if (spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing) |
701 m_rowPos[spanningCellEndIndex] += | 721 m_rowPos[spanningCellEndIndex] += |
702 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing + | 722 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing + |
703 borderSpacingForRow(spanningCellEndIndex - 1); | 723 borderSpacingForRow(spanningCellEndIndex - 1); |
704 | 724 |
705 extraHeightToPropagate = | 725 extraHeightToPropagate = |
706 m_rowPos[spanningCellEndIndex] - originalBeforePosition; | 726 m_rowPos[spanningCellEndIndex] - originalBeforePosition; |
707 continue; | 727 continue; |
708 } | 728 } |
709 | 729 |
710 if (spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing <= | 730 if (spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing <= |
711 spanningRowsHeight.totalRowsHeight) { | 731 spanningRowsHeight.totalRowsHeight) { |
712 extraHeightToPropagate = | 732 extraHeightToPropagate = |
713 m_rowPos[rowIndex + rowSpan] - originalBeforePosition; | 733 m_rowPos[rowIndex + rowSpan] - originalBeforePosition; |
714 continue; | 734 continue; |
715 } | 735 } |
716 | 736 |
717 // Below we are handling only row(s) who have at least one visible cell with
out rowspan value. | 737 // Below we are handling only row(s) who have at least one visible cell |
| 738 // without rowspan value. |
718 float totalPercent = 0; | 739 float totalPercent = 0; |
719 int totalAutoRowsHeight = 0; | 740 int totalAutoRowsHeight = 0; |
720 int totalRemainingRowsHeight = spanningRowsHeight.totalRowsHeight; | 741 int totalRemainingRowsHeight = spanningRowsHeight.totalRowsHeight; |
721 | 742 |
722 // FIXME: Inner spanning cell height should not change if it have fixed heig
ht when it's parent spanning cell | 743 // FIXME: Inner spanning cell height should not change if it have fixed |
723 // is distributing it's extra height in rows. | 744 // height when it's parent spanning cell is distributing it's extra height |
| 745 //in rows. |
724 | 746 |
725 // Calculate total percentage, total auto rows height and total rows height
except percent rows. | 747 // Calculate total percentage, total auto rows height and total rows height |
| 748 // except percent rows. |
726 for (unsigned row = rowIndex; row < spanningCellEndIndex; row++) { | 749 for (unsigned row = rowIndex; row < spanningCellEndIndex; row++) { |
727 // TODO(alancutter): Make this work correctly for calc lengths. | 750 // TODO(alancutter): Make this work correctly for calc lengths. |
728 if (m_grid[row].logicalHeight.isPercent()) { | 751 if (m_grid[row].logicalHeight.isPercent()) { |
729 totalPercent += m_grid[row].logicalHeight.percent(); | 752 totalPercent += m_grid[row].logicalHeight.percent(); |
730 totalRemainingRowsHeight -= | 753 totalRemainingRowsHeight -= |
731 spanningRowsHeight.rowHeight[row - rowIndex]; | 754 spanningRowsHeight.rowHeight[row - rowIndex]; |
732 } else if (m_grid[row].logicalHeight.isAuto()) { | 755 } else if (m_grid[row].logicalHeight.isAuto()) { |
733 totalAutoRowsHeight += spanningRowsHeight.rowHeight[row - rowIndex]; | 756 totalAutoRowsHeight += spanningRowsHeight.rowHeight[row - rowIndex]; |
734 } | 757 } |
735 } | 758 } |
736 | 759 |
737 int extraRowSpanningHeight = | 760 int extraRowSpanningHeight = |
738 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing - | 761 spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing - |
739 spanningRowsHeight.totalRowsHeight; | 762 spanningRowsHeight.totalRowsHeight; |
740 | 763 |
741 if (totalPercent < 100 && !totalAutoRowsHeight && | 764 if (totalPercent < 100 && !totalAutoRowsHeight && |
742 !totalRemainingRowsHeight) { | 765 !totalRemainingRowsHeight) { |
743 // Distributing whole extra rowspanning height in percent row when only no
n-percent rows height is 0. | 766 // Distributing whole extra rowspanning height in percent row when only |
| 767 // non-percent rows height is 0. |
744 distributeWholeExtraRowSpanHeightToPercentRows( | 768 distributeWholeExtraRowSpanHeightToPercentRows( |
745 cell, totalPercent, extraRowSpanningHeight, | 769 cell, totalPercent, extraRowSpanningHeight, |
746 spanningRowsHeight.rowHeight); | 770 spanningRowsHeight.rowHeight); |
747 } else { | 771 } else { |
748 distributeExtraRowSpanHeightToPercentRows(cell, totalPercent, | 772 distributeExtraRowSpanHeightToPercentRows(cell, totalPercent, |
749 extraRowSpanningHeight, | 773 extraRowSpanningHeight, |
750 spanningRowsHeight.rowHeight); | 774 spanningRowsHeight.rowHeight); |
751 distributeExtraRowSpanHeightToAutoRows(cell, totalAutoRowsHeight, | 775 distributeExtraRowSpanHeightToAutoRows(cell, totalAutoRowsHeight, |
752 extraRowSpanningHeight, | 776 extraRowSpanningHeight, |
753 spanningRowsHeight.rowHeight); | 777 spanningRowsHeight.rowHeight); |
754 distributeExtraRowSpanHeightToRemainingRows( | 778 distributeExtraRowSpanHeightToRemainingRows( |
755 cell, totalRemainingRowsHeight, extraRowSpanningHeight, | 779 cell, totalRemainingRowsHeight, extraRowSpanningHeight, |
756 spanningRowsHeight.rowHeight); | 780 spanningRowsHeight.rowHeight); |
757 } | 781 } |
758 | 782 |
759 ASSERT(!extraRowSpanningHeight); | 783 ASSERT(!extraRowSpanningHeight); |
760 | 784 |
761 // Getting total changed height in the table | 785 // Getting total changed height in the table |
762 extraHeightToPropagate = | 786 extraHeightToPropagate = |
763 m_rowPos[spanningCellEndIndex] - originalBeforePosition; | 787 m_rowPos[spanningCellEndIndex] - originalBeforePosition; |
764 } | 788 } |
765 | 789 |
766 if (extraHeightToPropagate) { | 790 if (extraHeightToPropagate) { |
767 // Apply changed height by rowSpan cells to rows present at the end of the t
able | 791 // Apply changed height by rowSpan cells to rows present at the end of the |
| 792 // table |
768 for (unsigned row = lastRowIndex + lastRowSpan + 1; row <= m_grid.size(); | 793 for (unsigned row = lastRowIndex + lastRowSpan + 1; row <= m_grid.size(); |
769 row++) | 794 row++) |
770 m_rowPos[row] += extraHeightToPropagate; | 795 m_rowPos[row] += extraHeightToPropagate; |
771 } | 796 } |
772 } | 797 } |
773 | 798 |
774 // Find out the baseline of the cell | 799 // Find out the baseline of the cell |
775 // If the cell's baseline is more than the row's baseline then the cell's baseli
ne become the row's baseline | 800 // If the cell's baseline is more than the row's baseline then the cell's |
776 // and if the row's baseline goes out of the row's boundaries then adjust row he
ight accordingly. | 801 // baseline become the row's baseline and if the row's baseline goes out of the |
| 802 // row's boundaries then adjust row height accordingly. |
777 void LayoutTableSection::updateBaselineForCell(LayoutTableCell* cell, | 803 void LayoutTableSection::updateBaselineForCell(LayoutTableCell* cell, |
778 unsigned row, | 804 unsigned row, |
779 int& baselineDescent) { | 805 int& baselineDescent) { |
780 if (!cell->isBaselineAligned()) | 806 if (!cell->isBaselineAligned()) |
781 return; | 807 return; |
782 | 808 |
783 // Ignoring the intrinsic padding as it depends on knowing the row's baseline,
which won't be accurate | 809 // Ignoring the intrinsic padding as it depends on knowing the row's baseline, |
784 // until the end of this function. | 810 // which won't be accurate until the end of this function. |
785 int baselinePosition = | 811 int baselinePosition = |
786 cell->cellBaselinePosition() - cell->intrinsicPaddingBefore(); | 812 cell->cellBaselinePosition() - cell->intrinsicPaddingBefore(); |
787 if (baselinePosition > | 813 if (baselinePosition > |
788 cell->borderBefore() + | 814 cell->borderBefore() + |
789 (cell->paddingBefore() - cell->intrinsicPaddingBefore())) { | 815 (cell->paddingBefore() - cell->intrinsicPaddingBefore())) { |
790 m_grid[row].baseline = std::max(m_grid[row].baseline, baselinePosition); | 816 m_grid[row].baseline = std::max(m_grid[row].baseline, baselinePosition); |
791 | 817 |
792 int cellStartRowBaselineDescent = 0; | 818 int cellStartRowBaselineDescent = 0; |
793 if (cell->rowSpan() == 1) { | 819 if (cell->rowSpan() == 1) { |
794 baselineDescent = | 820 baselineDescent = |
795 std::max(baselineDescent, | 821 std::max(baselineDescent, |
796 cell->logicalHeightForRowSizing() - baselinePosition); | 822 cell->logicalHeightForRowSizing() - baselinePosition); |
797 cellStartRowBaselineDescent = baselineDescent; | 823 cellStartRowBaselineDescent = baselineDescent; |
798 } | 824 } |
799 m_rowPos[row + 1] = | 825 m_rowPos[row + 1] = |
800 std::max<int>(m_rowPos[row + 1], m_rowPos[row] + m_grid[row].baseline + | 826 std::max<int>(m_rowPos[row + 1], m_rowPos[row] + m_grid[row].baseline + |
801 cellStartRowBaselineDescent); | 827 cellStartRowBaselineDescent); |
802 } | 828 } |
803 } | 829 } |
804 | 830 |
805 int LayoutTableSection::calcRowLogicalHeight() { | 831 int LayoutTableSection::calcRowLogicalHeight() { |
806 #if ENABLE(ASSERT) | 832 #if ENABLE(ASSERT) |
807 SetLayoutNeededForbiddenScope layoutForbiddenScope(*this); | 833 SetLayoutNeededForbiddenScope layoutForbiddenScope(*this); |
808 #endif | 834 #endif |
809 | 835 |
810 ASSERT(!needsLayout()); | 836 ASSERT(!needsLayout()); |
811 | 837 |
812 LayoutTableCell* cell; | 838 LayoutTableCell* cell; |
813 | 839 |
814 // We may have to forcefully lay out cells here, in which case we need a layou
t | 840 // We may have to forcefully lay out cells here, in which case we need a |
815 // state. Technically, we should also push state for the row, but since rows d
on't push a | 841 // layout state. Technically, we should also push state for the row, but since |
816 // coordinate transform, that's not necessary. | 842 // rows don't push a coordinate transform, that's not necessary. |
817 LayoutState state(*this, locationOffset()); | 843 LayoutState state(*this, locationOffset()); |
818 | 844 |
819 m_rowPos.resize(m_grid.size() + 1); | 845 m_rowPos.resize(m_grid.size() + 1); |
820 | 846 |
821 // We ignore the border-spacing on any non-top section as it is already includ
ed in the previous section's last row position. | 847 // We ignore the border-spacing on any non-top section as it is already |
| 848 // included in the previous section's last row position. |
822 if (this == table()->topSection()) | 849 if (this == table()->topSection()) |
823 m_rowPos[0] = table()->vBorderSpacing(); | 850 m_rowPos[0] = table()->vBorderSpacing(); |
824 else | 851 else |
825 m_rowPos[0] = 0; | 852 m_rowPos[0] = 0; |
826 | 853 |
827 SpanningLayoutTableCells rowSpanCells; | 854 SpanningLayoutTableCells rowSpanCells; |
828 #if ENABLE(ASSERT) | 855 #if ENABLE(ASSERT) |
829 HashSet<const LayoutTableCell*> uniqueCells; | 856 HashSet<const LayoutTableCell*> uniqueCells; |
830 #endif | 857 #endif |
831 | 858 |
832 for (unsigned r = 0; r < m_grid.size(); r++) { | 859 for (unsigned r = 0; r < m_grid.size(); r++) { |
833 m_grid[r].baseline = -1; | 860 m_grid[r].baseline = -1; |
834 int baselineDescent = 0; | 861 int baselineDescent = 0; |
835 | 862 |
836 if (m_grid[r].logicalHeight.isSpecified()) { | 863 if (m_grid[r].logicalHeight.isSpecified()) { |
837 // Our base size is the biggest logical height from our cells' styles (exc
luding row spanning cells). | 864 // Our base size is the biggest logical height from our cells' styles |
| 865 // (excluding row spanning cells). |
838 m_rowPos[r + 1] = std::max( | 866 m_rowPos[r + 1] = std::max( |
839 m_rowPos[r] + | 867 m_rowPos[r] + |
840 minimumValueForLength(m_grid[r].logicalHeight, LayoutUnit()) | 868 minimumValueForLength(m_grid[r].logicalHeight, LayoutUnit()) |
841 .round(), | 869 .round(), |
842 0); | 870 0); |
843 } else { | 871 } else { |
844 // Non-specified lengths are ignored because the row already accounts for
the cells | 872 // Non-specified lengths are ignored because the row already accounts for |
845 // intrinsic logical height. | 873 // the cells intrinsic logical height. |
846 m_rowPos[r + 1] = std::max(m_rowPos[r], 0); | 874 m_rowPos[r + 1] = std::max(m_rowPos[r], 0); |
847 } | 875 } |
848 | 876 |
849 Row& row = m_grid[r].row; | 877 Row& row = m_grid[r].row; |
850 unsigned totalCols = row.size(); | 878 unsigned totalCols = row.size(); |
851 LayoutTableCell* lastRowSpanCell = nullptr; | 879 LayoutTableCell* lastRowSpanCell = nullptr; |
852 | 880 |
853 for (unsigned c = 0; c < totalCols; c++) { | 881 for (unsigned c = 0; c < totalCols; c++) { |
854 CellStruct& current = cellAt(r, c); | 882 CellStruct& current = cellAt(r, c); |
855 for (unsigned i = 0; i < current.cells.size(); i++) { | 883 for (unsigned i = 0; i < current.cells.size(); i++) { |
856 cell = current.cells[i]; | 884 cell = current.cells[i]; |
857 if (current.inColSpan && cell->rowSpan() == 1) | 885 if (current.inColSpan && cell->rowSpan() == 1) |
858 continue; | 886 continue; |
859 | 887 |
860 if (cell->rowSpan() > 1) { | 888 if (cell->rowSpan() > 1) { |
861 // For row spanning cells, we only handle them for the first row they
span. This ensures we take their baseline into account. | 889 // For row spanning cells, we only handle them for the first row they |
| 890 // span. This ensures we take their baseline into account. |
862 if (lastRowSpanCell != cell && cell->rowIndex() == r) { | 891 if (lastRowSpanCell != cell && cell->rowIndex() == r) { |
863 #if ENABLE(ASSERT) | 892 #if ENABLE(ASSERT) |
864 ASSERT(!uniqueCells.contains(cell)); | 893 ASSERT(!uniqueCells.contains(cell)); |
865 uniqueCells.add(cell); | 894 uniqueCells.add(cell); |
866 #endif | 895 #endif |
867 | 896 |
868 rowSpanCells.append(cell); | 897 rowSpanCells.append(cell); |
869 lastRowSpanCell = cell; | 898 lastRowSpanCell = cell; |
870 } | 899 } |
871 } | 900 } |
872 | 901 |
873 if (cell->rowIndex() == r && cell->hasOverrideLogicalContentHeight()) { | 902 if (cell->rowIndex() == r && cell->hasOverrideLogicalContentHeight()) { |
874 cell->clearIntrinsicPadding(); | 903 cell->clearIntrinsicPadding(); |
875 cell->clearOverrideSize(); | 904 cell->clearOverrideSize(); |
876 cell->forceChildLayout(); | 905 cell->forceChildLayout(); |
877 } | 906 } |
878 | 907 |
879 if (cell->rowSpan() == 1) | 908 if (cell->rowSpan() == 1) |
880 m_rowPos[r + 1] = std::max( | 909 m_rowPos[r + 1] = std::max( |
881 m_rowPos[r + 1], m_rowPos[r] + cell->logicalHeightForRowSizing()); | 910 m_rowPos[r + 1], m_rowPos[r] + cell->logicalHeightForRowSizing()); |
882 | 911 |
883 // Find out the baseline. The baseline is set on the first row in a rowS
pan. | 912 // Find out the baseline. The baseline is set on the first row in a |
| 913 // rowSpan. |
884 if (cell->rowIndex() == r) | 914 if (cell->rowIndex() == r) |
885 updateBaselineForCell(cell, r, baselineDescent); | 915 updateBaselineForCell(cell, r, baselineDescent); |
886 } | 916 } |
887 } | 917 } |
888 | 918 |
889 // Add the border-spacing to our final position. | 919 // Add the border-spacing to our final position. |
890 m_rowPos[r + 1] += borderSpacingForRow(r); | 920 m_rowPos[r + 1] += borderSpacingForRow(r); |
891 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[r]); | 921 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[r]); |
892 } | 922 } |
893 | 923 |
894 if (!rowSpanCells.isEmpty()) | 924 if (!rowSpanCells.isEmpty()) |
895 distributeRowSpanHeightToRows(rowSpanCells); | 925 distributeRowSpanHeightToRows(rowSpanCells); |
896 | 926 |
897 ASSERT(!needsLayout()); | 927 ASSERT(!needsLayout()); |
898 | 928 |
899 return m_rowPos[m_grid.size()]; | 929 return m_rowPos[m_grid.size()]; |
900 } | 930 } |
901 | 931 |
902 void LayoutTableSection::layout() { | 932 void LayoutTableSection::layout() { |
903 ASSERT(needsLayout()); | 933 ASSERT(needsLayout()); |
904 LayoutAnalyzer::Scope analyzer(*this); | 934 LayoutAnalyzer::Scope analyzer(*this); |
905 RELEASE_ASSERT(!needsCellRecalc()); | 935 RELEASE_ASSERT(!needsCellRecalc()); |
906 ASSERT(!table()->needsSectionRecalc()); | 936 ASSERT(!table()->needsSectionRecalc()); |
907 | 937 |
908 // addChild may over-grow m_grid but we don't want to throw away the memory to
o early as addChild | 938 // addChild may over-grow m_grid but we don't want to throw away the memory |
909 // can be called in a loop (e.g during parsing). Doing it now ensures we have
a stable-enough structure. | 939 // too early as addChild can be called in a loop (e.g during parsing). Doing |
| 940 // it now ensures we have a stable-enough structure. |
910 m_grid.shrinkToFit(); | 941 m_grid.shrinkToFit(); |
911 | 942 |
912 LayoutState state(*this, locationOffset()); | 943 LayoutState state(*this, locationOffset()); |
913 | 944 |
914 const Vector<int>& columnPos = table()->effectiveColumnPositions(); | 945 const Vector<int>& columnPos = table()->effectiveColumnPositions(); |
915 | 946 |
916 SubtreeLayoutScope layouter(*this); | 947 SubtreeLayoutScope layouter(*this); |
917 for (unsigned r = 0; r < m_grid.size(); ++r) { | 948 for (unsigned r = 0; r < m_grid.size(); ++r) { |
918 Row& row = m_grid[r].row; | 949 Row& row = m_grid[r].row; |
919 unsigned cols = row.size(); | 950 unsigned cols = row.size(); |
920 // First, propagate our table layout's information to the cells. This will m
ark the row as needing layout | 951 // First, propagate our table layout's information to the cells. This will |
921 // if there was a column logical width change. | 952 // mark the row as needing layout if there was a column logical width |
| 953 // change. |
922 for (unsigned startColumn = 0; startColumn < cols; ++startColumn) { | 954 for (unsigned startColumn = 0; startColumn < cols; ++startColumn) { |
923 CellStruct& current = row[startColumn]; | 955 CellStruct& current = row[startColumn]; |
924 LayoutTableCell* cell = current.primaryCell(); | 956 LayoutTableCell* cell = current.primaryCell(); |
925 if (!cell || current.inColSpan) | 957 if (!cell || current.inColSpan) |
926 continue; | 958 continue; |
927 | 959 |
928 unsigned endCol = startColumn; | 960 unsigned endCol = startColumn; |
929 unsigned cspan = cell->colSpan(); | 961 unsigned cspan = cell->colSpan(); |
930 while (cspan && endCol < cols) { | 962 while (cspan && endCol < cols) { |
931 ASSERT(endCol < table()->effectiveColumns().size()); | 963 ASSERT(endCol < table()->effectiveColumns().size()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 | 1012 |
981 void LayoutTableSection::distributeExtraLogicalHeightToAutoRows( | 1013 void LayoutTableSection::distributeExtraLogicalHeightToAutoRows( |
982 int& extraLogicalHeight, | 1014 int& extraLogicalHeight, |
983 unsigned autoRowsCount) { | 1015 unsigned autoRowsCount) { |
984 if (!autoRowsCount) | 1016 if (!autoRowsCount) |
985 return; | 1017 return; |
986 | 1018 |
987 int totalLogicalHeightAdded = 0; | 1019 int totalLogicalHeightAdded = 0; |
988 for (unsigned r = 0; r < m_grid.size(); ++r) { | 1020 for (unsigned r = 0; r < m_grid.size(); ++r) { |
989 if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) { | 1021 if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) { |
990 // Recomputing |extraLogicalHeightForRow| guarantees that we properly ditr
ibute round |extraLogicalHeight|. | 1022 // Recomputing |extraLogicalHeightForRow| guarantees that we properly |
| 1023 // ditribute round |extraLogicalHeight|. |
991 int extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount; | 1024 int extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount; |
992 totalLogicalHeightAdded += extraLogicalHeightForRow; | 1025 totalLogicalHeightAdded += extraLogicalHeightForRow; |
993 extraLogicalHeight -= extraLogicalHeightForRow; | 1026 extraLogicalHeight -= extraLogicalHeightForRow; |
994 --autoRowsCount; | 1027 --autoRowsCount; |
995 } | 1028 } |
996 m_rowPos[r + 1] += totalLogicalHeightAdded; | 1029 m_rowPos[r + 1] += totalLogicalHeightAdded; |
997 } | 1030 } |
998 } | 1031 } |
999 | 1032 |
1000 void LayoutTableSection::distributeRemainingExtraLogicalHeight( | 1033 void LayoutTableSection::distributeRemainingExtraLogicalHeight( |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 | 1091 |
1059 void LayoutTableSection::layoutRows() { | 1092 void LayoutTableSection::layoutRows() { |
1060 #if ENABLE(ASSERT) | 1093 #if ENABLE(ASSERT) |
1061 SetLayoutNeededForbiddenScope layoutForbiddenScope(*this); | 1094 SetLayoutNeededForbiddenScope layoutForbiddenScope(*this); |
1062 #endif | 1095 #endif |
1063 | 1096 |
1064 ASSERT(!needsLayout()); | 1097 ASSERT(!needsLayout()); |
1065 | 1098 |
1066 LayoutAnalyzer::Scope analyzer(*this); | 1099 LayoutAnalyzer::Scope analyzer(*this); |
1067 | 1100 |
1068 // FIXME: Changing the height without a layout can change the overflow so it s
eems wrong. | 1101 // FIXME: Changing the height without a layout can change the overflow so it |
| 1102 // seems wrong. |
1069 | 1103 |
1070 unsigned totalRows = m_grid.size(); | 1104 unsigned totalRows = m_grid.size(); |
1071 | 1105 |
1072 // Set the width of our section now. The rows will also be this width. | 1106 // Set the width of our section now. The rows will also be this width. |
1073 setLogicalWidth(table()->contentLogicalWidth()); | 1107 setLogicalWidth(table()->contentLogicalWidth()); |
1074 | 1108 |
1075 int vspacing = table()->vBorderSpacing(); | 1109 int vspacing = table()->vBorderSpacing(); |
1076 unsigned nEffCols = table()->numEffectiveColumns(); | 1110 unsigned nEffCols = table()->numEffectiveColumns(); |
1077 bool isPaginated = view()->layoutState()->isPaginated(); | 1111 bool isPaginated = view()->layoutState()->isPaginated(); |
1078 | 1112 |
1079 if (isPaginated) { | 1113 if (isPaginated) { |
1080 LayoutTableSection* header = table()->header(); | 1114 LayoutTableSection* header = table()->header(); |
1081 // If we're a table header nested inside a table cell then we want to repeat
on each | 1115 // If we're a table header nested inside a table cell then we want to repeat |
1082 // page, but below the header we're nested inside. Note we don't try to matc
h the padding | 1116 // on each page, but below the header we're nested inside. Note we don't try |
1083 // on the cell on each repeated header. | 1117 // to match the padding on the cell on each repeated header. |
1084 if (header && header == this) | 1118 if (header && header == this) |
1085 setOffsetForRepeatingHeader( | 1119 setOffsetForRepeatingHeader( |
1086 view()->layoutState()->heightOffsetForTableHeaders()); | 1120 view()->layoutState()->heightOffsetForTableHeaders()); |
1087 } | 1121 } |
1088 | 1122 |
1089 LayoutState state(*this, locationOffset()); | 1123 LayoutState state(*this, locationOffset()); |
1090 | 1124 |
1091 for (unsigned r = 0; r < totalRows; r++) { | 1125 for (unsigned r = 0; r < totalRows; r++) { |
1092 // Set the row's x/y position and width/height. | 1126 // Set the row's x/y position and width/height. |
1093 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; | 1127 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; |
1094 int paginationStrutOnRow = 0; | 1128 int paginationStrutOnRow = 0; |
1095 if (rowLayoutObject) { | 1129 if (rowLayoutObject) { |
1096 rowLayoutObject->setLogicalLocation(LayoutPoint(0, m_rowPos[r])); | 1130 rowLayoutObject->setLogicalLocation(LayoutPoint(0, m_rowPos[r])); |
1097 rowLayoutObject->setLogicalWidth(logicalWidth()); | 1131 rowLayoutObject->setLogicalWidth(logicalWidth()); |
1098 rowLayoutObject->setLogicalHeight( | 1132 rowLayoutObject->setLogicalHeight( |
1099 LayoutUnit(m_rowPos[r + 1] - m_rowPos[r] - vspacing)); | 1133 LayoutUnit(m_rowPos[r + 1] - m_rowPos[r] - vspacing)); |
1100 rowLayoutObject->updateLayerTransformAfterLayout(); | 1134 rowLayoutObject->updateLayerTransformAfterLayout(); |
1101 if (isPaginated) { | 1135 if (isPaginated) { |
1102 paginationStrutOnRow = | 1136 paginationStrutOnRow = |
1103 paginationStrutForRow(rowLayoutObject, LayoutUnit(m_rowPos[r])); | 1137 paginationStrutForRow(rowLayoutObject, LayoutUnit(m_rowPos[r])); |
1104 rowLayoutObject->setPaginationStrut(LayoutUnit(paginationStrutOnRow)); | 1138 rowLayoutObject->setPaginationStrut(LayoutUnit(paginationStrutOnRow)); |
1105 bool rowIsAtTopOfColumn = | 1139 bool rowIsAtTopOfColumn = |
1106 state.heightOffsetForTableHeaders() && | 1140 state.heightOffsetForTableHeaders() && |
1107 pageRemainingLogicalHeightForOffset(LayoutUnit(m_rowPos[r]), | 1141 pageRemainingLogicalHeightForOffset(LayoutUnit(m_rowPos[r]), |
1108 AssociateWithLatterPage) == | 1142 AssociateWithLatterPage) == |
1109 pageLogicalHeightForOffset(LayoutUnit(m_rowPos[r])); | 1143 pageLogicalHeightForOffset(LayoutUnit(m_rowPos[r])); |
1110 if (paginationStrutOnRow || rowIsAtTopOfColumn) { | 1144 if (paginationStrutOnRow || rowIsAtTopOfColumn) { |
1111 // If there isn't room for at least one content row on a page with a h
eader group, then | 1145 // If there isn't room for at least one content row on a page with a |
1112 // we won't repeat the header on each page. | 1146 // header group, then we won't repeat the header on each page. |
1113 if (!r && table()->header() && | 1147 if (!r && table()->header() && |
1114 table()->sectionAbove(this) == table()->header() && | 1148 table()->sectionAbove(this) == table()->header() && |
1115 table()->header()->getPaginationBreakability() != AllowAnyBreaks) | 1149 table()->header()->getPaginationBreakability() != AllowAnyBreaks) |
1116 state.setHeightOffsetForTableHeaders( | 1150 state.setHeightOffsetForTableHeaders( |
1117 state.heightOffsetForTableHeaders() - | 1151 state.heightOffsetForTableHeaders() - |
1118 table()->header()->logicalHeight()); | 1152 table()->header()->logicalHeight()); |
1119 // If we have a header group we will paint it at the top of each page,
move the rows | 1153 // If we have a header group we will paint it at the top of each page, |
1120 // down to accomodate it. | 1154 // move the rows down to accomodate it. |
1121 paginationStrutOnRow += state.heightOffsetForTableHeaders().toInt(); | 1155 paginationStrutOnRow += state.heightOffsetForTableHeaders().toInt(); |
1122 for (unsigned rowIndex = r; rowIndex <= totalRows; rowIndex++) | 1156 for (unsigned rowIndex = r; rowIndex <= totalRows; rowIndex++) |
1123 m_rowPos[rowIndex] += paginationStrutOnRow; | 1157 m_rowPos[rowIndex] += paginationStrutOnRow; |
1124 } | 1158 } |
1125 } | 1159 } |
1126 } | 1160 } |
1127 | 1161 |
1128 int rowHeightIncreaseForPagination = INT_MIN; | 1162 int rowHeightIncreaseForPagination = INT_MIN; |
1129 | 1163 |
1130 for (unsigned c = 0; c < nEffCols; c++) { | 1164 for (unsigned c = 0; c < nEffCols; c++) { |
(...skipping 17 matching lines...) Expand all Loading... |
1148 setLogicalPositionForCell(cell, c); | 1182 setLogicalPositionForCell(cell, c); |
1149 | 1183 |
1150 if (!cell->needsLayout()) | 1184 if (!cell->needsLayout()) |
1151 markChildForPaginationRelayoutIfNeeded(*cell, layouter); | 1185 markChildForPaginationRelayoutIfNeeded(*cell, layouter); |
1152 | 1186 |
1153 cell->layoutIfNeeded(); | 1187 cell->layoutIfNeeded(); |
1154 | 1188 |
1155 // FIXME: Make pagination work with vertical tables. | 1189 // FIXME: Make pagination work with vertical tables. |
1156 if (view()->layoutState()->pageLogicalHeight() && | 1190 if (view()->layoutState()->pageLogicalHeight() && |
1157 cell->logicalHeight() != rHeight) { | 1191 cell->logicalHeight() != rHeight) { |
1158 // FIXME: Pagination might have made us change size. For now just shrink
or grow the cell to fit without doing a relayout. | 1192 // FIXME: Pagination might have made us change size. For now just shrink |
1159 // We'll also do a basic increase of the row height to accommodate the c
ell if it's bigger, but this isn't quite right | 1193 // or grow the cell to fit without doing a relayout. |
1160 // either. It's at least stable though and won't result in an infinite #
of relayouts that may never stabilize. | 1194 // We'll also do a basic increase of the row height to accommodate the |
| 1195 // cell if it's bigger, but this isn't quite right either. It's at least |
| 1196 // stable though and won't result in an infinite # of relayouts that may |
| 1197 // never stabilize. |
1161 LayoutUnit oldLogicalHeight = cell->logicalHeight(); | 1198 LayoutUnit oldLogicalHeight = cell->logicalHeight(); |
1162 rowHeightIncreaseForPagination = | 1199 rowHeightIncreaseForPagination = |
1163 std::max<int>(rowHeightIncreaseForPagination, | 1200 std::max<int>(rowHeightIncreaseForPagination, |
1164 (oldLogicalHeight - rHeight).toInt()); | 1201 (oldLogicalHeight - rHeight).toInt()); |
1165 cell->setLogicalHeight(LayoutUnit(rHeight)); | 1202 cell->setLogicalHeight(LayoutUnit(rHeight)); |
1166 cell->computeOverflow(oldLogicalHeight, false); | 1203 cell->computeOverflow(oldLogicalHeight, false); |
1167 } | 1204 } |
1168 | 1205 |
1169 LayoutSize childOffset(cell->location() - oldCellRect.location()); | 1206 LayoutSize childOffset(cell->location() - oldCellRect.location()); |
1170 if (childOffset.width() || childOffset.height()) { | 1207 if (childOffset.width() || childOffset.height()) { |
1171 // If the child moved, we have to issue paint invalidations to it as wel
l as any floating/positioned | 1208 // If the child moved, we have to issue paint invalidations to it as |
1172 // descendants. An exception is if we need a layout. In this case, we kn
ow we're going to | 1209 // well as any floating/positioned descendants. An exception is if we |
1173 // issue paint invalidations ourselves (and the child) anyway. | 1210 // need a layout. In this case, we know we're going to issue paint |
| 1211 // invalidations ourselves (and the child) anyway. |
1174 if (!table()->selfNeedsLayout()) | 1212 if (!table()->selfNeedsLayout()) |
1175 cell->setMayNeedPaintInvalidation(); | 1213 cell->setMayNeedPaintInvalidation(); |
1176 } | 1214 } |
1177 } | 1215 } |
1178 if (rowHeightIncreaseForPagination > INT_MIN) { | 1216 if (rowHeightIncreaseForPagination > INT_MIN) { |
1179 for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++) | 1217 for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++) |
1180 m_rowPos[rowIndex] += rowHeightIncreaseForPagination; | 1218 m_rowPos[rowIndex] += rowHeightIncreaseForPagination; |
1181 for (unsigned c = 0; c < nEffCols; ++c) { | 1219 for (unsigned c = 0; c < nEffCols; ++c) { |
1182 Vector<LayoutTableCell*, 1>& cells = cellAt(r, c).cells; | 1220 Vector<LayoutTableCell*, 1>& cells = cellAt(r, c).cells; |
1183 for (size_t i = 0; i < cells.size(); ++i) { | 1221 for (size_t i = 0; i < cells.size(); ++i) { |
(...skipping 11 matching lines...) Expand all Loading... |
1195 ASSERT(!needsLayout()); | 1233 ASSERT(!needsLayout()); |
1196 | 1234 |
1197 setLogicalHeight(LayoutUnit(m_rowPos[totalRows])); | 1235 setLogicalHeight(LayoutUnit(m_rowPos[totalRows])); |
1198 | 1236 |
1199 computeOverflowFromCells(totalRows, nEffCols); | 1237 computeOverflowFromCells(totalRows, nEffCols); |
1200 } | 1238 } |
1201 | 1239 |
1202 int LayoutTableSection::paginationStrutForRow(LayoutTableRow* row, | 1240 int LayoutTableSection::paginationStrutForRow(LayoutTableRow* row, |
1203 LayoutUnit logicalOffset) const { | 1241 LayoutUnit logicalOffset) const { |
1204 DCHECK(row); | 1242 DCHECK(row); |
1205 // Even if the row allows us to break-inside, we will want to put a strut on t
he row if we have a header | 1243 // Even if the row allows us to break-inside, we will want to put a strut on |
1206 // group that wants to appear at the top of each page. | 1244 // the row if we have a header group that wants to appear at the top of each |
| 1245 // page. |
1207 bool tableHeaderForcesStrut = | 1246 bool tableHeaderForcesStrut = |
1208 table()->header() | 1247 table()->header() |
1209 ? table()->header()->getPaginationBreakability() != AllowAnyBreaks | 1248 ? table()->header()->getPaginationBreakability() != AllowAnyBreaks |
1210 : false; | 1249 : false; |
1211 if (row->getPaginationBreakability() == AllowAnyBreaks && | 1250 if (row->getPaginationBreakability() == AllowAnyBreaks && |
1212 !tableHeaderForcesStrut) | 1251 !tableHeaderForcesStrut) |
1213 return 0; | 1252 return 0; |
1214 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 1253 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
1215 if (!pageLogicalHeight) | 1254 if (!pageLogicalHeight) |
1216 return 0; | 1255 return 0; |
(...skipping 11 matching lines...) Expand all Loading... |
1228 // repeating header. | 1267 // repeating header. |
1229 if (offsetForBorderSpacing < 0) | 1268 if (offsetForBorderSpacing < 0) |
1230 return offsetForBorderSpacing.toInt(); | 1269 return offsetForBorderSpacing.toInt(); |
1231 | 1270 |
1232 if (remainingLogicalHeight >= rowLogicalHeight) | 1271 if (remainingLogicalHeight >= rowLogicalHeight) |
1233 return 0; // It fits fine where it is. No need to break. | 1272 return 0; // It fits fine where it is. No need to break. |
1234 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( | 1273 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( |
1235 logicalOffset, remainingLogicalHeight, rowLogicalHeight); | 1274 logicalOffset, remainingLogicalHeight, rowLogicalHeight); |
1236 if (paginationStrut == remainingLogicalHeight && | 1275 if (paginationStrut == remainingLogicalHeight && |
1237 remainingLogicalHeight == pageLogicalHeight) { | 1276 remainingLogicalHeight == pageLogicalHeight) { |
1238 // Don't break if we were at the top of a page, and we failed to fit the con
tent | 1277 // Don't break if we were at the top of a page, and we failed to fit the |
1239 // completely. No point in leaving a page completely blank. | 1278 // content completely. No point in leaving a page completely blank. |
1240 return 0; | 1279 return 0; |
1241 } | 1280 } |
1242 // Table layout parts only work on integers, so we have to round. Round up, to | 1281 // Table layout parts only work on integers, so we have to round. Round up, to |
1243 // make sure that no fraction ever gets left behind in the previous | 1282 // make sure that no fraction ever gets left behind in the previous |
1244 // fragmentainer. | 1283 // fragmentainer. |
1245 return paginationStrut.ceil(); | 1284 return paginationStrut.ceil(); |
1246 } | 1285 } |
1247 | 1286 |
1248 void LayoutTableSection::computeOverflowFromCells() { | 1287 void LayoutTableSection::computeOverflowFromCells() { |
1249 unsigned totalRows = m_grid.size(); | 1288 unsigned totalRows = m_grid.size(); |
(...skipping 25 matching lines...) Expand all Loading... |
1275 if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c)) | 1314 if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c)) |
1276 continue; | 1315 continue; |
1277 addOverflowFromChild(cell); | 1316 addOverflowFromChild(cell); |
1278 #if ENABLE(ASSERT) | 1317 #if ENABLE(ASSERT) |
1279 hasOverflowingCell |= cell->hasVisualOverflow(); | 1318 hasOverflowingCell |= cell->hasVisualOverflow(); |
1280 #endif | 1319 #endif |
1281 if (cell->hasVisualOverflow() && | 1320 if (cell->hasVisualOverflow() && |
1282 !m_forceSlowPaintPathWithOverflowingCell) { | 1321 !m_forceSlowPaintPathWithOverflowingCell) { |
1283 m_overflowingCells.add(cell); | 1322 m_overflowingCells.add(cell); |
1284 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) { | 1323 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) { |
1285 // We need to set m_forcesSlowPaintPath only if there is a least one o
verflowing cells as the hit testing code rely on this information. | 1324 // We need to set m_forcesSlowPaintPath only if there is a least one |
| 1325 // overflowing cells as the hit testing code rely on this information. |
1286 m_forceSlowPaintPathWithOverflowingCell = true; | 1326 m_forceSlowPaintPathWithOverflowingCell = true; |
1287 // The slow path does not make any use of the overflowing cells info,
don't hold on to the memory. | 1327 // The slow path does not make any use of the overflowing cells info, |
| 1328 // don't hold on to the memory. |
1288 m_overflowingCells.clear(); | 1329 m_overflowingCells.clear(); |
1289 } | 1330 } |
1290 } | 1331 } |
1291 } | 1332 } |
1292 } | 1333 } |
1293 | 1334 |
1294 ASSERT(hasOverflowingCell == this->hasOverflowingCell()); | 1335 ASSERT(hasOverflowingCell == this->hasOverflowingCell()); |
1295 } | 1336 } |
1296 | 1337 |
1297 bool LayoutTableSection::recalcChildOverflowAfterStyleChange() { | 1338 bool LayoutTableSection::recalcChildOverflowAfterStyleChange() { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 if (rb.style() > BorderStyleHidden && rb.width() > borderWidth) | 1400 if (rb.style() > BorderStyleHidden && rb.width() > borderWidth) |
1360 borderWidth = rb.width(); | 1401 borderWidth = rb.width(); |
1361 | 1402 |
1362 bool allHidden = true; | 1403 bool allHidden = true; |
1363 for (unsigned c = 0; c < totalCols; c++) { | 1404 for (unsigned c = 0; c < totalCols; c++) { |
1364 const CellStruct& current = | 1405 const CellStruct& current = |
1365 cellAt(side == BorderBefore ? 0 : m_grid.size() - 1, c); | 1406 cellAt(side == BorderBefore ? 0 : m_grid.size() - 1, c); |
1366 if (current.inColSpan || !current.hasCells()) | 1407 if (current.inColSpan || !current.hasCells()) |
1367 continue; | 1408 continue; |
1368 const ComputedStyle& primaryCellStyle = current.primaryCell()->styleRef(); | 1409 const ComputedStyle& primaryCellStyle = current.primaryCell()->styleRef(); |
1369 const BorderValue& cb = | 1410 // FIXME: Make this work with perpendicular and flipped cells. |
1370 side == BorderBefore | 1411 const BorderValue& cb = side == BorderBefore |
1371 ? primaryCellStyle.borderBefore() | 1412 ? primaryCellStyle.borderBefore() |
1372 : primaryCellStyle | 1413 : primaryCellStyle.borderAfter(); |
1373 .borderAfter(); // FIXME: Make this work with perpendicular a
nd flipped cells. | |
1374 // FIXME: Don't repeat for the same col group | 1414 // FIXME: Don't repeat for the same col group |
1375 LayoutTableCol* col = | 1415 LayoutTableCol* col = |
1376 table()->colElementAtAbsoluteColumn(c).innermostColOrColGroup(); | 1416 table()->colElementAtAbsoluteColumn(c).innermostColOrColGroup(); |
1377 if (col) { | 1417 if (col) { |
1378 const BorderValue& gb = side == BorderBefore | 1418 const BorderValue& gb = side == BorderBefore |
1379 ? col->style()->borderBefore() | 1419 ? col->style()->borderBefore() |
1380 : col->style()->borderAfter(); | 1420 : col->style()->borderAfter(); |
1381 if (gb.style() == BorderStyleHidden || cb.style() == BorderStyleHidden) | 1421 if (gb.style() == BorderStyleHidden || cb.style() == BorderStyleHidden) |
1382 continue; | 1422 continue; |
1383 allHidden = false; | 1423 allHidden = false; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1430 | 1470 |
1431 bool allHidden = true; | 1471 bool allHidden = true; |
1432 for (unsigned r = 0; r < m_grid.size(); r++) { | 1472 for (unsigned r = 0; r < m_grid.size(); r++) { |
1433 const CellStruct& current = cellAt(r, colIndex); | 1473 const CellStruct& current = cellAt(r, colIndex); |
1434 if (!current.hasCells()) | 1474 if (!current.hasCells()) |
1435 continue; | 1475 continue; |
1436 // FIXME: Don't repeat for the same cell | 1476 // FIXME: Don't repeat for the same cell |
1437 const ComputedStyle& primaryCellStyle = current.primaryCell()->styleRef(); | 1477 const ComputedStyle& primaryCellStyle = current.primaryCell()->styleRef(); |
1438 const ComputedStyle& primaryCellParentStyle = | 1478 const ComputedStyle& primaryCellParentStyle = |
1439 current.primaryCell()->parent()->styleRef(); | 1479 current.primaryCell()->parent()->styleRef(); |
1440 const BorderValue& cb = | 1480 // FIXME: Make this work with perpendicular and flipped cells. |
1441 side == BorderStart | 1481 const BorderValue& cb = side == BorderStart ? primaryCellStyle.borderStart() |
1442 ? primaryCellStyle.borderStart() | 1482 : primaryCellStyle.borderEnd(); |
1443 : primaryCellStyle | |
1444 .borderEnd(); // FIXME: Make this work with perpendicular and
flipped cells. | |
1445 const BorderValue& rb = side == BorderStart | 1483 const BorderValue& rb = side == BorderStart |
1446 ? primaryCellParentStyle.borderStart() | 1484 ? primaryCellParentStyle.borderStart() |
1447 : primaryCellParentStyle.borderEnd(); | 1485 : primaryCellParentStyle.borderEnd(); |
1448 if (cb.style() == BorderStyleHidden || rb.style() == BorderStyleHidden) | 1486 if (cb.style() == BorderStyleHidden || rb.style() == BorderStyleHidden) |
1449 continue; | 1487 continue; |
1450 allHidden = false; | 1488 allHidden = false; |
1451 if (cb.style() > BorderStyleHidden && cb.width() > borderWidth) | 1489 if (cb.style() > BorderStyleHidden && cb.width() > borderWidth) |
1452 borderWidth = cb.width(); | 1490 borderWidth = cb.width(); |
1453 if (rb.style() > BorderStyleHidden && rb.width() > borderWidth) | 1491 if (rb.style() > BorderStyleHidden && rb.width() > borderWidth) |
1454 borderWidth = rb.width(); | 1492 borderWidth = rb.width(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 LayoutRect LayoutTableSection::logicalRectForWritingModeAndDirection( | 1537 LayoutRect LayoutTableSection::logicalRectForWritingModeAndDirection( |
1500 const LayoutRect& rect) const { | 1538 const LayoutRect& rect) const { |
1501 LayoutRect tableAlignedRect(rect); | 1539 LayoutRect tableAlignedRect(rect); |
1502 | 1540 |
1503 flipForWritingMode(tableAlignedRect); | 1541 flipForWritingMode(tableAlignedRect); |
1504 | 1542 |
1505 if (!style()->isHorizontalWritingMode()) | 1543 if (!style()->isHorizontalWritingMode()) |
1506 tableAlignedRect = tableAlignedRect.transposedRect(); | 1544 tableAlignedRect = tableAlignedRect.transposedRect(); |
1507 | 1545 |
1508 const Vector<int>& columnPos = table()->effectiveColumnPositions(); | 1546 const Vector<int>& columnPos = table()->effectiveColumnPositions(); |
1509 // FIXME: The table's direction should determine our row's direction, not the
section's (see bug 96691). | 1547 // FIXME: The table's direction should determine our row's direction, not the |
| 1548 // section's (see bug 96691). |
1510 if (!style()->isLeftToRightDirection()) | 1549 if (!style()->isLeftToRightDirection()) |
1511 tableAlignedRect.setX(columnPos[columnPos.size() - 1] - | 1550 tableAlignedRect.setX(columnPos[columnPos.size() - 1] - |
1512 tableAlignedRect.maxX()); | 1551 tableAlignedRect.maxX()); |
1513 | 1552 |
1514 return tableAlignedRect; | 1553 return tableAlignedRect; |
1515 } | 1554 } |
1516 | 1555 |
1517 CellSpan LayoutTableSection::dirtiedRows(const LayoutRect& damageRect) const { | 1556 CellSpan LayoutTableSection::dirtiedRows(const LayoutRect& damageRect) const { |
1518 if (m_forceSlowPaintPathWithOverflowingCell) | 1557 if (m_forceSlowPaintPathWithOverflowingCell) |
1519 return fullTableRowSpan(); | 1558 return fullTableRowSpan(); |
1520 | 1559 |
1521 if (!m_grid.size()) | 1560 if (!m_grid.size()) |
1522 return CellSpan(0, 0); | 1561 return CellSpan(0, 0); |
1523 | 1562 |
1524 CellSpan coveredRows = spannedRows(damageRect); | 1563 CellSpan coveredRows = spannedRows(damageRect); |
1525 | 1564 |
1526 // To issue paint invalidations for the border we might need to paint invalida
te the first | 1565 // To issue paint invalidations for the border we might need to paint |
1527 // or last row even if they are not spanned themselves. | 1566 // invalidate the first or last row even if they are not spanned themselves. |
1528 RELEASE_ASSERT(coveredRows.start() < m_rowPos.size()); | 1567 RELEASE_ASSERT(coveredRows.start() < m_rowPos.size()); |
1529 if (coveredRows.start() == m_rowPos.size() - 1 && | 1568 if (coveredRows.start() == m_rowPos.size() - 1 && |
1530 m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= | 1569 m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= |
1531 damageRect.y()) | 1570 damageRect.y()) |
1532 coveredRows.decreaseStart(); | 1571 coveredRows.decreaseStart(); |
1533 | 1572 |
1534 if (!coveredRows.end() && | 1573 if (!coveredRows.end() && |
1535 m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY()) | 1574 m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY()) |
1536 coveredRows.increaseEnd(); | 1575 coveredRows.increaseEnd(); |
1537 | 1576 |
1538 coveredRows.ensureConsistency(m_grid.size()); | 1577 coveredRows.ensureConsistency(m_grid.size()); |
1539 | 1578 |
1540 return coveredRows; | 1579 return coveredRows; |
1541 } | 1580 } |
1542 | 1581 |
1543 CellSpan LayoutTableSection::dirtiedEffectiveColumns( | 1582 CellSpan LayoutTableSection::dirtiedEffectiveColumns( |
1544 const LayoutRect& damageRect) const { | 1583 const LayoutRect& damageRect) const { |
1545 if (m_forceSlowPaintPathWithOverflowingCell) | 1584 if (m_forceSlowPaintPathWithOverflowingCell) |
1546 return fullTableEffectiveColumnSpan(); | 1585 return fullTableEffectiveColumnSpan(); |
1547 | 1586 |
1548 RELEASE_ASSERT(table()->numEffectiveColumns()); | 1587 RELEASE_ASSERT(table()->numEffectiveColumns()); |
1549 CellSpan coveredColumns = spannedEffectiveColumns(damageRect); | 1588 CellSpan coveredColumns = spannedEffectiveColumns(damageRect); |
1550 | 1589 |
1551 const Vector<int>& columnPos = table()->effectiveColumnPositions(); | 1590 const Vector<int>& columnPos = table()->effectiveColumnPositions(); |
1552 // To issue paint invalidations for the border we might need to paint invalida
te the first | 1591 // To issue paint invalidations for the border we might need to paint |
1553 // or last column even if they are not spanned themselves. | 1592 // invalidate the first or last column even if they are not spanned |
| 1593 // themselves. |
1554 RELEASE_ASSERT(coveredColumns.start() < columnPos.size()); | 1594 RELEASE_ASSERT(coveredColumns.start() < columnPos.size()); |
1555 if (coveredColumns.start() == columnPos.size() - 1 && | 1595 if (coveredColumns.start() == columnPos.size() - 1 && |
1556 columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= | 1596 columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= |
1557 damageRect.x()) | 1597 damageRect.x()) |
1558 coveredColumns.decreaseStart(); | 1598 coveredColumns.decreaseStart(); |
1559 | 1599 |
1560 if (!coveredColumns.end() && | 1600 if (!coveredColumns.end() && |
1561 columnPos[0] - table()->outerBorderStart() <= damageRect.maxX()) | 1601 columnPos[0] - table()->outerBorderStart() <= damageRect.maxX()) |
1562 coveredColumns.increaseEnd(); | 1602 coveredColumns.increaseEnd(); |
1563 | 1603 |
1564 coveredColumns.ensureConsistency(table()->numEffectiveColumns()); | 1604 coveredColumns.ensureConsistency(table()->numEffectiveColumns()); |
1565 | 1605 |
1566 return coveredColumns; | 1606 return coveredColumns; |
1567 } | 1607 } |
1568 | 1608 |
1569 CellSpan LayoutTableSection::spannedRows(const LayoutRect& flippedRect) const { | 1609 CellSpan LayoutTableSection::spannedRows(const LayoutRect& flippedRect) const { |
1570 // Find the first row that starts after rect top. | 1610 // Find the first row that starts after rect top. |
1571 unsigned nextRow = | 1611 unsigned nextRow = |
1572 std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - | 1612 std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - |
1573 m_rowPos.begin(); | 1613 m_rowPos.begin(); |
1574 | 1614 |
| 1615 // After all rows. |
1575 if (nextRow == m_rowPos.size()) | 1616 if (nextRow == m_rowPos.size()) |
1576 return CellSpan(m_rowPos.size() - 1, | 1617 return CellSpan(m_rowPos.size() - 1, m_rowPos.size() - 1); |
1577 m_rowPos.size() - 1); // After all rows. | |
1578 | 1618 |
1579 unsigned startRow = nextRow > 0 ? nextRow - 1 : 0; | 1619 unsigned startRow = nextRow > 0 ? nextRow - 1 : 0; |
1580 | 1620 |
1581 // Find the first row that starts after rect bottom. | 1621 // Find the first row that starts after rect bottom. |
1582 unsigned endRow; | 1622 unsigned endRow; |
1583 if (m_rowPos[nextRow] >= flippedRect.maxY()) { | 1623 if (m_rowPos[nextRow] >= flippedRect.maxY()) { |
1584 endRow = nextRow; | 1624 endRow = nextRow; |
1585 } else { | 1625 } else { |
1586 endRow = std::upper_bound(m_rowPos.begin() + nextRow, m_rowPos.end(), | 1626 endRow = std::upper_bound(m_rowPos.begin() + nextRow, m_rowPos.end(), |
1587 flippedRect.maxY()) - | 1627 flippedRect.maxY()) - |
1588 m_rowPos.begin(); | 1628 m_rowPos.begin(); |
1589 if (endRow == m_rowPos.size()) | 1629 if (endRow == m_rowPos.size()) |
1590 endRow = m_rowPos.size() - 1; | 1630 endRow = m_rowPos.size() - 1; |
1591 } | 1631 } |
1592 | 1632 |
1593 return CellSpan(startRow, endRow); | 1633 return CellSpan(startRow, endRow); |
1594 } | 1634 } |
1595 | 1635 |
1596 CellSpan LayoutTableSection::spannedEffectiveColumns( | 1636 CellSpan LayoutTableSection::spannedEffectiveColumns( |
1597 const LayoutRect& flippedRect) const { | 1637 const LayoutRect& flippedRect) const { |
1598 const Vector<int>& columnPos = table()->effectiveColumnPositions(); | 1638 const Vector<int>& columnPos = table()->effectiveColumnPositions(); |
1599 | 1639 |
1600 // Find the first column that starts after rect left. | 1640 // Find the first column that starts after rect left. |
1601 // lower_bound doesn't handle the edge between two cells properly as it would
wrongly return the | 1641 // lower_bound doesn't handle the edge between two cells properly as it would |
1602 // cell on the logical top/left. | 1642 // wrongly return the cell on the logical top/left. |
1603 // upper_bound on the other hand properly returns the cell on the logical bott
om/right, which also | 1643 // upper_bound on the other hand properly returns the cell on the logical |
1604 // matches the behavior of other browsers. | 1644 // bottom/right, which also matches the behavior of other browsers. |
1605 unsigned nextColumn = | 1645 unsigned nextColumn = |
1606 std::upper_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - | 1646 std::upper_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - |
1607 columnPos.begin(); | 1647 columnPos.begin(); |
1608 | 1648 |
1609 if (nextColumn == columnPos.size()) | 1649 if (nextColumn == columnPos.size()) |
1610 return CellSpan(columnPos.size() - 1, | 1650 return CellSpan(columnPos.size() - 1, |
1611 columnPos.size() - 1); // After all columns. | 1651 columnPos.size() - 1); // After all columns. |
1612 | 1652 |
1613 unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0; | 1653 unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0; |
1614 | 1654 |
1615 // Find the first column that starts after rect right. | 1655 // Find the first column that starts after rect right. |
1616 unsigned endColumn; | 1656 unsigned endColumn; |
1617 if (columnPos[nextColumn] >= flippedRect.maxX()) { | 1657 if (columnPos[nextColumn] >= flippedRect.maxX()) { |
1618 endColumn = nextColumn; | 1658 endColumn = nextColumn; |
1619 } else { | 1659 } else { |
1620 endColumn = std::upper_bound(columnPos.begin() + nextColumn, | 1660 endColumn = std::upper_bound(columnPos.begin() + nextColumn, |
1621 columnPos.end(), flippedRect.maxX()) - | 1661 columnPos.end(), flippedRect.maxX()) - |
1622 columnPos.begin(); | 1662 columnPos.begin(); |
1623 if (endColumn == columnPos.size()) | 1663 if (endColumn == columnPos.size()) |
1624 endColumn = columnPos.size() - 1; | 1664 endColumn = columnPos.size() - 1; |
1625 } | 1665 } |
1626 | 1666 |
1627 return CellSpan(startColumn, endColumn); | 1667 return CellSpan(startColumn, endColumn); |
1628 } | 1668 } |
1629 | 1669 |
1630 void LayoutTableSection::recalcCells() { | 1670 void LayoutTableSection::recalcCells() { |
1631 ASSERT(m_needsCellRecalc); | 1671 ASSERT(m_needsCellRecalc); |
1632 // We reset the flag here to ensure that |addCell| works. This is safe to do a
s | 1672 // We reset the flag here to ensure that |addCell| works. This is safe to do |
1633 // fillRowsWithDefaultStartingAtPosition makes sure we match the table's colum
ns | 1673 // as fillRowsWithDefaultStartingAtPosition makes sure we match the table's |
1634 // representation. | 1674 // columns representation. |
1635 m_needsCellRecalc = false; | 1675 m_needsCellRecalc = false; |
1636 | 1676 |
1637 m_cCol = 0; | 1677 m_cCol = 0; |
1638 m_cRow = 0; | 1678 m_cRow = 0; |
1639 m_grid.clear(); | 1679 m_grid.clear(); |
1640 | 1680 |
1641 for (LayoutTableRow* row = firstRow(); row; row = row->nextRow()) { | 1681 for (LayoutTableRow* row = firstRow(); row; row = row->nextRow()) { |
1642 unsigned insertionRow = m_cRow; | 1682 unsigned insertionRow = m_cRow; |
1643 ++m_cRow; | 1683 ++m_cRow; |
1644 m_cCol = 0; | 1684 m_cCol = 0; |
1645 ensureRows(m_cRow); | 1685 ensureRows(m_cRow); |
1646 | 1686 |
1647 m_grid[insertionRow].rowLayoutObject = row; | 1687 m_grid[insertionRow].rowLayoutObject = row; |
1648 row->setRowIndex(insertionRow); | 1688 row->setRowIndex(insertionRow); |
1649 setRowLogicalHeightToRowStyleLogicalHeight(m_grid[insertionRow]); | 1689 setRowLogicalHeightToRowStyleLogicalHeight(m_grid[insertionRow]); |
1650 | 1690 |
1651 for (LayoutTableCell* cell = row->firstCell(); cell; | 1691 for (LayoutTableCell* cell = row->firstCell(); cell; |
1652 cell = cell->nextCell()) | 1692 cell = cell->nextCell()) |
1653 addCell(cell, row); | 1693 addCell(cell, row); |
1654 } | 1694 } |
1655 | 1695 |
1656 m_grid.shrinkToFit(); | 1696 m_grid.shrinkToFit(); |
1657 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::Unknown); | 1697 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::Unknown); |
1658 } | 1698 } |
1659 | 1699 |
1660 // FIXME: This function could be made O(1) in certain cases (like for the non-mo
st-constrainive cells' case). | 1700 // FIXME: This function could be made O(1) in certain cases (like for the |
| 1701 // non-most-constrainive cells' case). |
1661 void LayoutTableSection::rowLogicalHeightChanged(LayoutTableRow* row) { | 1702 void LayoutTableSection::rowLogicalHeightChanged(LayoutTableRow* row) { |
1662 if (needsCellRecalc()) | 1703 if (needsCellRecalc()) |
1663 return; | 1704 return; |
1664 | 1705 |
1665 unsigned rowIndex = row->rowIndex(); | 1706 unsigned rowIndex = row->rowIndex(); |
1666 setRowLogicalHeightToRowStyleLogicalHeight(m_grid[rowIndex]); | 1707 setRowLogicalHeightToRowStyleLogicalHeight(m_grid[rowIndex]); |
1667 | 1708 |
1668 for (LayoutTableCell* cell = m_grid[rowIndex].rowLayoutObject->firstCell(); | 1709 for (LayoutTableCell* cell = m_grid[rowIndex].rowLayoutObject->firstCell(); |
1669 cell; cell = cell->nextCell()) | 1710 cell; cell = cell->nextCell()) |
1670 updateLogicalHeightForCell(m_grid[rowIndex], cell); | 1711 updateLogicalHeightForCell(m_grid[rowIndex], cell); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1761 // Table sections cannot ever be hit tested. Effectively they do not exist. | 1802 // Table sections cannot ever be hit tested. Effectively they do not exist. |
1762 // Just forward to our children always. | 1803 // Just forward to our children always. |
1763 LayoutPoint adjustedLocation = accumulatedOffset + location(); | 1804 LayoutPoint adjustedLocation = accumulatedOffset + location(); |
1764 | 1805 |
1765 if (hasOverflowClip() && | 1806 if (hasOverflowClip() && |
1766 !locationInContainer.intersects(overflowClipRect(adjustedLocation))) | 1807 !locationInContainer.intersects(overflowClipRect(adjustedLocation))) |
1767 return false; | 1808 return false; |
1768 | 1809 |
1769 if (hasOverflowingCell()) { | 1810 if (hasOverflowingCell()) { |
1770 for (LayoutTableRow* row = lastRow(); row; row = row->previousRow()) { | 1811 for (LayoutTableRow* row = lastRow(); row; row = row->previousRow()) { |
1771 // FIXME: We have to skip over inline flows, since they can show up inside
table rows | 1812 // FIXME: We have to skip over inline flows, since they can show up inside |
1772 // at the moment (a demoted inline <form> for example). If we ever impleme
nt a | 1813 // table rows at the moment (a demoted inline <form> for example). If we |
1773 // table-specific hit-test method (which we should do for performance reas
ons anyway), | 1814 // ever implement a table-specific hit-test method (which we should do for |
1774 // then we can remove this check. | 1815 // performance reasons anyway), then we can remove this check. |
1775 if (!row->hasSelfPaintingLayer()) { | 1816 if (!row->hasSelfPaintingLayer()) { |
1776 LayoutPoint childPoint = | 1817 LayoutPoint childPoint = |
1777 flipForWritingModeForChild(row, adjustedLocation); | 1818 flipForWritingModeForChild(row, adjustedLocation); |
1778 if (row->nodeAtPoint(result, locationInContainer, childPoint, action)) { | 1819 if (row->nodeAtPoint(result, locationInContainer, childPoint, action)) { |
1779 updateHitTestResult( | 1820 updateHitTestResult( |
1780 result, toLayoutPoint(locationInContainer.point() - childPoint)); | 1821 result, toLayoutPoint(locationInContainer.point() - childPoint)); |
1781 return true; | 1822 return true; |
1782 } | 1823 } |
1783 } | 1824 } |
1784 } | 1825 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1837 newSection->setStyle(newStyle.release()); | 1878 newSection->setStyle(newStyle.release()); |
1838 return newSection; | 1879 return newSection; |
1839 } | 1880 } |
1840 | 1881 |
1841 void LayoutTableSection::setLogicalPositionForCell( | 1882 void LayoutTableSection::setLogicalPositionForCell( |
1842 LayoutTableCell* cell, | 1883 LayoutTableCell* cell, |
1843 unsigned effectiveColumn) const { | 1884 unsigned effectiveColumn) const { |
1844 LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]); | 1885 LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]); |
1845 int horizontalBorderSpacing = table()->hBorderSpacing(); | 1886 int horizontalBorderSpacing = table()->hBorderSpacing(); |
1846 | 1887 |
1847 // FIXME: The table's direction should determine our row's direction, not the
section's (see bug 96691). | 1888 // FIXME: The table's direction should determine our row's direction, not the |
| 1889 // section's (see bug 96691). |
1848 if (!style()->isLeftToRightDirection()) | 1890 if (!style()->isLeftToRightDirection()) |
1849 cellLocation.setX(LayoutUnit( | 1891 cellLocation.setX(LayoutUnit( |
1850 table()->effectiveColumnPositions()[table()->numEffectiveColumns()] - | 1892 table()->effectiveColumnPositions()[table()->numEffectiveColumns()] - |
1851 table()->effectiveColumnPositions() | 1893 table()->effectiveColumnPositions() |
1852 [table()->absoluteColumnToEffectiveColumn( | 1894 [table()->absoluteColumnToEffectiveColumn( |
1853 cell->absoluteColumnIndex() + cell->colSpan())] + | 1895 cell->absoluteColumnIndex() + cell->colSpan())] + |
1854 horizontalBorderSpacing)); | 1896 horizontalBorderSpacing)); |
1855 else | 1897 else |
1856 cellLocation.setX( | 1898 cellLocation.setX( |
1857 LayoutUnit(table()->effectiveColumnPositions()[effectiveColumn] + | 1899 LayoutUnit(table()->effectiveColumnPositions()[effectiveColumn] + |
1858 horizontalBorderSpacing)); | 1900 horizontalBorderSpacing)); |
1859 | 1901 |
1860 cell->setLogicalLocation(cellLocation); | 1902 cell->setLogicalLocation(cellLocation); |
1861 } | 1903 } |
1862 | 1904 |
1863 void LayoutTableSection::relayoutCellIfFlexed(LayoutTableCell& cell, | 1905 void LayoutTableSection::relayoutCellIfFlexed(LayoutTableCell& cell, |
1864 int rowIndex, | 1906 int rowIndex, |
1865 int rowHeight) { | 1907 int rowHeight) { |
1866 // Force percent height children to lay themselves out again. | 1908 // Force percent height children to lay themselves out again. |
1867 // This will cause these children to grow to fill the cell. | 1909 // This will cause these children to grow to fill the cell. |
1868 // FIXME: There is still more work to do here to fully match WinIE (should | 1910 // FIXME: There is still more work to do here to fully match WinIE (should |
1869 // it become necessary to do so). In quirks mode, WinIE behaves like we | 1911 // it become necessary to do so). In quirks mode, WinIE behaves like we |
1870 // do, but it will clip the cells that spill out of the table section. In | 1912 // do, but it will clip the cells that spill out of the table section. |
1871 // strict mode, Mozilla and WinIE both regrow the table to accommodate the | 1913 // strict mode, Mozilla and WinIE both regrow the table to accommodate the |
1872 // new height of the cell (thus letting the percentages cause growth one | 1914 // new height of the cell (thus letting the percentages cause growth one |
1873 // time only). We may also not be handling row-spanning cells correctly. | 1915 // time only). We may also not be handling row-spanning cells correctly. |
1874 // | 1916 // |
1875 // Note also the oddity where replaced elements always flex, and yet | 1917 // Note also the oddity where replaced elements always flex, and yet blocks/ |
1876 // blocks/tables do not necessarily flex. WinIE is crazy and inconsistent, | 1918 // tables do not necessarily flex. WinIE is crazy and inconsistent, and we |
1877 // and we can't hope to match the behavior perfectly, but we'll continue to | 1919 // can't hope to match the behavior perfectly, but we'll continue to refine it |
1878 // refine it as we discover new bugs. :) | 1920 // as we discover new bugs. :) |
1879 bool cellChildrenFlex = false; | 1921 bool cellChildrenFlex = false; |
1880 bool flexAllChildren = cell.style()->logicalHeight().isFixed() || | 1922 bool flexAllChildren = cell.style()->logicalHeight().isFixed() || |
1881 (!table()->style()->logicalHeight().isAuto() && | 1923 (!table()->style()->logicalHeight().isAuto() && |
1882 rowHeight != cell.logicalHeight()); | 1924 rowHeight != cell.logicalHeight()); |
1883 | 1925 |
1884 for (LayoutObject* child = cell.firstChild(); child; | 1926 for (LayoutObject* child = cell.firstChild(); child; |
1885 child = child->nextSibling()) { | 1927 child = child->nextSibling()) { |
1886 if (!child->isText() && child->style()->logicalHeight().isPercentOrCalc() && | 1928 if (!child->isText() && child->style()->logicalHeight().isPercentOrCalc() && |
1887 (flexAllChildren || shouldFlexCellChild(child)) && | 1929 (flexAllChildren || shouldFlexCellChild(child)) && |
1888 (!child->isTable() || toLayoutTable(child)->hasSections())) { | 1930 (!child->isTable() || toLayoutTable(child)->hasSections())) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? | 1968 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? |
1927 if (hasSelfPaintingLayer()) | 1969 if (hasSelfPaintingLayer()) |
1928 return false; | 1970 return false; |
1929 LayoutUnit pageHeight = table()->pageLogicalHeightForOffset(LayoutUnit()); | 1971 LayoutUnit pageHeight = table()->pageLogicalHeightForOffset(LayoutUnit()); |
1930 if (!pageHeight) | 1972 if (!pageHeight) |
1931 return false; | 1973 return false; |
1932 | 1974 |
1933 if (logicalHeight() > pageHeight) | 1975 if (logicalHeight() > pageHeight) |
1934 return false; | 1976 return false; |
1935 | 1977 |
1936 // If the first row of the section after the header group doesn't fit on the p
age, then | 1978 // If the first row of the section after the header group doesn't fit on the |
1937 // don't repeat the header on each page. See https://drafts.csswg.org/css-tabl
es-3/#repeated-headers | 1979 // page, then don't repeat the header on each page. |
| 1980 // See https://drafts.csswg.org/css-tables-3/#repeated-headers |
1938 LayoutTableSection* sectionBelow = table()->sectionBelow(this); | 1981 LayoutTableSection* sectionBelow = table()->sectionBelow(this); |
1939 if (sectionBelow && sectionBelow->firstRow() && | 1982 if (sectionBelow && sectionBelow->firstRow() && |
1940 sectionBelow->firstRow()->paginationStrut()) | 1983 sectionBelow->firstRow()->paginationStrut()) |
1941 return false; | 1984 return false; |
1942 | 1985 |
1943 return true; | 1986 return true; |
1944 } | 1987 } |
1945 | 1988 |
1946 bool LayoutTableSection::mapToVisualRectInAncestorSpace( | 1989 bool LayoutTableSection::mapToVisualRectInAncestorSpace( |
1947 const LayoutBoxModelObject* ancestor, | 1990 const LayoutBoxModelObject* ancestor, |
1948 LayoutRect& rect, | 1991 LayoutRect& rect, |
1949 VisualRectFlags flags) const { | 1992 VisualRectFlags flags) const { |
1950 if (ancestor == this) | 1993 if (ancestor == this) |
1951 return true; | 1994 return true; |
1952 // Repeating table headers are painted once per fragmentation page/column. Thi
s does not go through the regular fragmentation machinery, | 1995 // Repeating table headers are painted once per fragmentation page/column. |
1953 // so we need special code to expand the invalidation rect to contain all posi
tions of the header in all columns. | 1996 // This does not go through the regular fragmentation machinery, so we need |
1954 // Note that this is in flow thread coordinates, not visual coordinates. The e
nclosing LayoutFlowThread will convert to visual coordinates. | 1997 // special code to expand the invalidation rect to contain all positions of |
| 1998 // the header in all columns. |
| 1999 // Note that this is in flow thread coordinates, not visual coordinates. The |
| 2000 // enclosing LayoutFlowThread will convert to visual coordinates. |
1955 if (table()->header() == this && isRepeatingHeaderGroup()) | 2001 if (table()->header() == this && isRepeatingHeaderGroup()) |
1956 rect.setHeight(table()->logicalHeight()); | 2002 rect.setHeight(table()->logicalHeight()); |
1957 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpace(ancestor, rect, | 2003 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpace(ancestor, rect, |
1958 flags); | 2004 flags); |
1959 } | 2005 } |
1960 | 2006 |
1961 } // namespace blink | 2007 } // namespace blink |
OLD | NEW |