OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2002 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2002 Lars Knoll (knoll@kde.org) |
3 * (C) 2002 Dirk Mueller (mueller@kde.org) | 3 * (C) 2002 Dirk Mueller (mueller@kde.org) |
4 * Copyright (C) 2003, 2006, 2008, 2010 Apple Inc. All rights reserved. | 4 * Copyright (C) 2003, 2006, 2008, 2010 Apple Inc. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License. | 9 * version 2 of the License. |
10 * | 10 * |
11 * This library is distributed in the hope that it will be useful, | 11 * This library is distributed in the hope that it will be useful, |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 * Library General Public License for more details. | 14 * Library General Public License for more details. |
15 * | 15 * |
16 * You should have received a copy of the GNU Library General Public License | 16 * You should have received a copy of the GNU Library General Public License |
17 * along with this library; see the file COPYING.LIB. If not, write to | 17 * along with this library; see the file COPYING.LIB. If not, write to |
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 * Boston, MA 02110-1301, USA. | 19 * Boston, MA 02110-1301, USA. |
20 */ | 20 */ |
21 | 21 |
22 #include "config.h" | 22 #include "config.h" |
23 #include "core/layout/TableLayoutAlgorithmAuto.h" | 23 #include "core/layout/TableLayoutAlgorithmAuto.h" |
24 | 24 |
25 #include "core/layout/LayoutTable.h" | 25 #include "core/layout/LayoutTable.h" |
26 #include "core/layout/LayoutTableCell.h" | 26 #include "core/layout/LayoutTableCell.h" |
27 #include "core/layout/LayoutTableCol.h" | 27 #include "core/layout/LayoutTableCol.h" |
28 #include "core/layout/LayoutTableSection.h" | 28 #include "core/layout/LayoutTableSection.h" |
29 #include "core/layout/LayoutText.h" | |
29 #include "core/layout/TextAutosizer.h" | 30 #include "core/layout/TextAutosizer.h" |
30 | 31 |
31 namespace blink { | 32 namespace blink { |
32 | 33 |
33 TableLayoutAlgorithmAuto::TableLayoutAlgorithmAuto(LayoutTable* table) | 34 TableLayoutAlgorithmAuto::TableLayoutAlgorithmAuto(LayoutTable* table) |
34 : TableLayoutAlgorithm(table) | 35 : TableLayoutAlgorithm(table) |
35 , m_hasPercent(false) | 36 , m_hasPercent(false) |
36 , m_effectiveLogicalWidthDirty(true) | 37 , m_effectiveLogicalWidthDirty(true) |
37 { | 38 { |
38 } | 39 } |
39 | 40 |
40 TableLayoutAlgorithmAuto::~TableLayoutAlgorithmAuto() | 41 TableLayoutAlgorithmAuto::~TableLayoutAlgorithmAuto() |
41 { | 42 { |
42 } | 43 } |
43 | 44 |
45 static bool isEmptyCell(LayoutObject* object) | |
46 { | |
47 for (LayoutObject* curr = object; curr; curr = curr->nextSibling()) { | |
48 if (curr->isText() && toLayoutText(curr)->isAllCollapsibleWhitespace()) | |
49 continue; | |
50 return false; | |
51 } | |
52 return true; | |
53 } | |
54 | |
44 void TableLayoutAlgorithmAuto::recalcColumn(unsigned effCol) | 55 void TableLayoutAlgorithmAuto::recalcColumn(unsigned effCol) |
45 { | 56 { |
46 Layout& columnLayout = m_layoutStruct[effCol]; | 57 Layout& columnLayout = m_layoutStruct[effCol]; |
47 | 58 |
48 LayoutTableCell* fixedContributor = 0; | 59 LayoutTableCell* fixedContributor = 0; |
49 LayoutTableCell* maxContributor = 0; | 60 LayoutTableCell* maxContributor = 0; |
50 | 61 |
51 for (LayoutObject* child = m_table->children()->firstChild(); child; child = child->nextSibling()) { | 62 for (LayoutObject* child = m_table->children()->firstChild(); child; child = child->nextSibling()) { |
52 if (child->isLayoutTableCol()) { | 63 if (child->isLayoutTableCol()) { |
53 // LayoutTableCols don't have the concept of preferred logical width , but we need to clear their dirty bits | 64 // LayoutTableCols don't have the concept of preferred logical width , but we need to clear their dirty bits |
54 // so that if we call setPreferredWidthsDirty(true) on a col or one of its descendants, we'll mark it's | 65 // so that if we call setPreferredWidthsDirty(true) on a col or one of its descendants, we'll mark it's |
55 // ancestors as dirty. | 66 // ancestors as dirty. |
56 toLayoutTableCol(child)->clearPreferredLogicalWidthsDirtyBits(); | 67 toLayoutTableCol(child)->clearPreferredLogicalWidthsDirtyBits(); |
57 } else if (child->isTableSection()) { | 68 } else if (child->isTableSection()) { |
58 LayoutTableSection* section = toLayoutTableSection(child); | 69 LayoutTableSection* section = toLayoutTableSection(child); |
59 unsigned numRows = section->numRows(); | 70 unsigned numRows = section->numRows(); |
60 for (unsigned i = 0; i < numRows; i++) { | 71 for (unsigned i = 0; i < numRows; i++) { |
61 LayoutTableSection::CellStruct current = section->cellAt(i, effC ol); | 72 LayoutTableSection::CellStruct current = section->cellAt(i, effC ol); |
62 LayoutTableCell* cell = current.primaryCell(); | 73 LayoutTableCell* cell = current.primaryCell(); |
63 | 74 |
64 if (current.inColSpan || !cell) | 75 if (current.inColSpan || !cell) |
65 continue; | 76 continue; |
66 | 77 |
67 bool cellHasContent = cell->children()->firstChild() || cell->st yle()->hasBorder() || cell->style()->hasPadding() || cell->style()->hasBackgroun d(); | 78 bool cellHasContent = !isEmptyCell(cell->firstChild()) || cell-> style()->hasBorder() || cell->style()->hasPadding() || cell->style()->hasBackgro und(); |
68 if (cellHasContent) | 79 if (cellHasContent) |
69 columnLayout.emptyCellsOnly = false; | 80 columnLayout.emptyCellsOnly = false; |
70 | 81 |
71 // A cell originates in this column. Ensure we have | 82 // A cell originates in this column. Ensure we have |
72 // a min/max width of at least 1px for this column now. | 83 // a min/max width of at least 1px for this column now. |
73 columnLayout.minLogicalWidth = std::max<int>(columnLayout.minLog icalWidth, cellHasContent ? 1 : 0); | 84 columnLayout.minLogicalWidth = std::max<int>(columnLayout.minLog icalWidth, cellHasContent ? 1 : 0); |
74 columnLayout.maxLogicalWidth = std::max<int>(columnLayout.maxLog icalWidth, 1); | |
75 | 85 |
76 if (cell->colSpan() == 1) { | 86 if (cell->colSpan() == 1) { |
77 columnLayout.minLogicalWidth = std::max<int>(cell->minPrefer redLogicalWidth(), columnLayout.minLogicalWidth); | 87 columnLayout.minLogicalWidth = std::max<int>(cell->minPrefer redLogicalWidth(), columnLayout.minLogicalWidth); |
78 if (cell->maxPreferredLogicalWidth() > columnLayout.maxLogic alWidth) { | 88 if (cell->maxPreferredLogicalWidth() > columnLayout.maxLogic alWidth) { |
79 columnLayout.maxLogicalWidth = cell->maxPreferredLogical Width(); | 89 columnLayout.maxLogicalWidth = cell->maxPreferredLogical Width(); |
80 maxContributor = cell; | 90 maxContributor = cell; |
81 } | 91 } |
82 | 92 |
83 // All browsers implement a size limit on the cell's max wid th. | 93 // All browsers implement a size limit on the cell's max wid th. |
84 // Our limit is based on KHTML's representation that used 16 bits widths. | 94 // Our limit is based on KHTML's representation that used 16 bits widths. |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 // all non percent columns in the span get percent values to sum up correctly. | 377 // all non percent columns in the span get percent values to sum up correctly. |
368 float percentMissing = cellLogicalWidth.percent() - totalPercent ; | 378 float percentMissing = cellLogicalWidth.percent() - totalPercent ; |
369 int totalWidth = 0; | 379 int totalWidth = 0; |
370 for (unsigned pos = effCol; pos < lastCol; ++pos) { | 380 for (unsigned pos = effCol; pos < lastCol; ++pos) { |
371 if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) | 381 if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) |
372 totalWidth += m_layoutStruct[pos].effectiveMaxLogicalWid th; | 382 totalWidth += m_layoutStruct[pos].effectiveMaxLogicalWid th; |
373 } | 383 } |
374 | 384 |
375 for (unsigned pos = effCol; pos < lastCol && totalWidth > 0; ++p os) { | 385 for (unsigned pos = effCol; pos < lastCol && totalWidth > 0; ++p os) { |
376 if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) { | 386 if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) { |
377 float percent = percentMissing * static_cast<float>(m_la youtStruct[pos].effectiveMaxLogicalWidth) / totalWidth; | 387 float percent = percentMissing * static_cast<float>(std: :max<int>(1, m_layoutStruct[pos].effectiveMaxLogicalWidth)) / totalWidth; |
378 totalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWid th; | 388 totalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWid th; |
379 percentMissing -= percent; | 389 percentMissing -= percent; |
380 if (percent > 0) | 390 if (percent > 0) |
381 m_layoutStruct[pos].effectiveLogicalWidth.setValue(P ercent, percent); | 391 m_layoutStruct[pos].effectiveLogicalWidth.setValue(P ercent, percent); |
382 else | 392 else |
383 m_layoutStruct[pos].effectiveLogicalWidth = Length() ; | 393 m_layoutStruct[pos].effectiveLogicalWidth = Length() ; |
384 } | 394 } |
385 } | 395 } |
386 } | 396 } |
387 } | 397 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
526 m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; | 536 m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; |
527 available -= cellLogicalWidth; | 537 available -= cellLogicalWidth; |
528 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; | 538 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; |
529 switch (logicalWidth.type()) { | 539 switch (logicalWidth.type()) { |
530 case Percent: | 540 case Percent: |
531 havePercent = true; | 541 havePercent = true; |
532 totalPercent += logicalWidth.percent(); | 542 totalPercent += logicalWidth.percent(); |
533 break; | 543 break; |
534 case Fixed: | 544 case Fixed: |
535 numFixed++; | 545 numFixed++; |
536 totalFixed += m_layoutStruct[i].effectiveMaxLogicalWidth; | 546 totalFixed += std::max<int>(1, m_layoutStruct[i].effectiveMaxLogical Width); |
dsinclair
2015/03/24 00:03:48
We do this a bunch of times, would it be better to
mstensho (USE GERRIT)
2015/03/24 08:36:37
I don't think I understand why it's still necessar
rhogan
2015/03/24 20:06:11
It uses the clamped value when deciding what propo
mstensho (USE GERRIT)
2015/03/25 10:10:52
I think that it's the width distribution algorithm
| |
537 // fall through | 547 // fall through |
538 break; | 548 break; |
539 case Auto: | 549 case Auto: |
540 if (m_layoutStruct[i].emptyCellsOnly) { | 550 if (m_layoutStruct[i].emptyCellsOnly) { |
541 numAutoEmptyCellsOnly++; | 551 numAutoEmptyCellsOnly++; |
542 } else { | 552 } else { |
543 numAuto++; | 553 numAuto++; |
544 totalAuto += m_layoutStruct[i].effectiveMaxLogicalWidth; | 554 totalAuto += std::max<int>(1, m_layoutStruct[i].effectiveMaxLogi calWidth); |
545 allocAuto += cellLogicalWidth; | 555 allocAuto += cellLogicalWidth; |
546 } | 556 } |
547 break; | 557 break; |
548 default: | 558 default: |
549 break; | 559 break; |
550 } | 560 } |
551 } | 561 } |
552 | 562 |
553 // allocate width to percent cols | 563 // allocate width to percent cols |
554 if (available > 0 && havePercent) { | 564 if (available > 0 && havePercent) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 } | 598 } |
589 } | 599 } |
590 } | 600 } |
591 | 601 |
592 // now satisfy variable | 602 // now satisfy variable |
593 if (available > 0 && numAuto) { | 603 if (available > 0 && numAuto) { |
594 available += allocAuto; // this gets redistributed | 604 available += allocAuto; // this gets redistributed |
595 for (size_t i = 0; i < nEffCols; ++i) { | 605 for (size_t i = 0; i < nEffCols; ++i) { |
596 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; | 606 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; |
597 if (logicalWidth.isAuto() && totalAuto && !m_layoutStruct[i].emptyCe llsOnly) { | 607 if (logicalWidth.isAuto() && totalAuto && !m_layoutStruct[i].emptyCe llsOnly) { |
598 int cellLogicalWidth = std::max<int>(m_layoutStruct[i].computedL ogicalWidth, static_cast<int>(available * static_cast<float>(m_layoutStruct[i].e ffectiveMaxLogicalWidth) / totalAuto)); | 608 int cellLogicalWidth = std::max<int>(m_layoutStruct[i].computedL ogicalWidth, static_cast<int>(available * static_cast<float>(std::max<int>(1, m_ layoutStruct[i].effectiveMaxLogicalWidth)) / totalAuto)); |
599 available -= cellLogicalWidth; | 609 available -= cellLogicalWidth; |
600 totalAuto -= m_layoutStruct[i].effectiveMaxLogicalWidth; | 610 totalAuto -= std::max<int>(1, m_layoutStruct[i].effectiveMaxLogi calWidth); |
601 m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; | 611 m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; |
602 } | 612 } |
603 } | 613 } |
604 } | 614 } |
605 | 615 |
606 // spread over fixed columns | 616 // spread over fixed columns |
607 if (available > 0 && numFixed) { | 617 if (available > 0 && numFixed) { |
608 for (size_t i = 0; i < nEffCols; ++i) { | 618 for (size_t i = 0; i < nEffCols; ++i) { |
609 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; | 619 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; |
610 if (logicalWidth.isFixed()) { | 620 if (logicalWidth.isFixed()) { |
611 int cellLogicalWidth = static_cast<int>(available * static_cast< float>(m_layoutStruct[i].effectiveMaxLogicalWidth) / totalFixed); | 621 int cellLogicalWidth = static_cast<int>(available * static_cast< float>(std::max<int>(1, m_layoutStruct[i].effectiveMaxLogicalWidth)) / totalFixe d); |
612 available -= cellLogicalWidth; | 622 available -= cellLogicalWidth; |
613 totalFixed -= m_layoutStruct[i].effectiveMaxLogicalWidth; | 623 totalFixed -= std::max<int>(1, m_layoutStruct[i].effectiveMaxLog icalWidth); |
614 m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth; | 624 m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth; |
615 } | 625 } |
616 } | 626 } |
617 } | 627 } |
618 | 628 |
619 // spread over percent colums | 629 // spread over percent colums |
620 if (available > 0 && m_hasPercent && totalPercent < 100) { | 630 if (available > 0 && m_hasPercent && totalPercent < 100) { |
621 for (size_t i = 0; i < nEffCols; ++i) { | 631 for (size_t i = 0; i < nEffCols; ++i) { |
622 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; | 632 Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; |
623 if (logicalWidth.isPercent()) { | 633 if (logicalWidth.isPercent()) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
730 | 740 |
731 int pos = 0; | 741 int pos = 0; |
732 for (size_t i = 0; i < nEffCols; ++i) { | 742 for (size_t i = 0; i < nEffCols; ++i) { |
733 m_table->setColumnPosition(i, pos); | 743 m_table->setColumnPosition(i, pos); |
734 pos += m_layoutStruct[i].computedLogicalWidth + m_table->hBorderSpacing( ); | 744 pos += m_layoutStruct[i].computedLogicalWidth + m_table->hBorderSpacing( ); |
735 } | 745 } |
736 m_table->setColumnPosition(m_table->columnPositions().size() - 1, pos); | 746 m_table->setColumnPosition(m_table->columnPositions().size() - 1, pos); |
737 } | 747 } |
738 | 748 |
739 } | 749 } |
OLD | NEW |