| 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 |