diff options
Diffstat (limited to 'Source/WebCore/rendering/AutoTableLayout.cpp')
-rw-r--r-- | Source/WebCore/rendering/AutoTableLayout.cpp | 245 |
1 files changed, 134 insertions, 111 deletions
diff --git a/Source/WebCore/rendering/AutoTableLayout.cpp b/Source/WebCore/rendering/AutoTableLayout.cpp index 4cd8f8764..b0cf6bd71 100644 --- a/Source/WebCore/rendering/AutoTableLayout.cpp +++ b/Source/WebCore/rendering/AutoTableLayout.cpp @@ -22,10 +22,12 @@ #include "config.h" #include "AutoTableLayout.h" +#include "RenderChildIterator.h" #include "RenderTable.h" #include "RenderTableCell.h" #include "RenderTableCol.h" #include "RenderTableSection.h" +#include "RenderView.h" namespace WebCore { @@ -44,20 +46,20 @@ void AutoTableLayout::recalcColumn(unsigned effCol) { Layout& columnLayout = m_layoutStruct[effCol]; - RenderTableCell* fixedContributor = 0; - RenderTableCell* maxContributor = 0; + RenderTableCell* fixedContributor = nullptr; + RenderTableCell* maxContributor = nullptr; - for (RenderObject* child = m_table->firstChild(); child; child = child->nextSibling()) { - if (child->isRenderTableCol()){ + for (auto& child : childrenOfType<RenderObject>(*m_table)) { + if (is<RenderTableCol>(child)) { // RenderTableCols don't have the concept of preferred logical width, but we need to clear their dirty bits // so that if we call setPreferredWidthsDirty(true) on a col or one of its descendants, we'll mark it's // ancestors as dirty. - toRenderTableCol(child)->clearPreferredLogicalWidthsDirtyBits(); - } else if (child->isTableSection()) { - RenderTableSection* section = toRenderTableSection(child); - unsigned numRows = section->numRows(); - for (unsigned i = 0; i < numRows; i++) { - RenderTableSection::CellStruct current = section->cellAt(i, effCol); + downcast<RenderTableCol>(child).clearPreferredLogicalWidthsDirtyBits(); + } else if (is<RenderTableSection>(child)) { + auto& section = downcast<RenderTableSection>(child); + unsigned numRows = section.numRows(); + for (unsigned i = 0; i < numRows; ++i) { + RenderTableSection::CellStruct current = section.cellAt(i, effCol); RenderTableCell* cell = current.primaryCell(); if (current.inColSpan || !cell) @@ -69,30 +71,31 @@ void AutoTableLayout::recalcColumn(unsigned effCol) // A cell originates in this column. Ensure we have // a min/max width of at least 1px for this column now. - columnLayout.minLogicalWidth = std::max<int>(columnLayout.minLogicalWidth, cellHasContent ? 1 : 0); - columnLayout.maxLogicalWidth = std::max<int>(columnLayout.maxLogicalWidth, 1); + columnLayout.minLogicalWidth = std::max<float>(columnLayout.minLogicalWidth, cellHasContent ? 1 : 0); + columnLayout.maxLogicalWidth = std::max<float>(columnLayout.maxLogicalWidth, 1); if (cell->colSpan() == 1) { - columnLayout.minLogicalWidth = std::max<int>(cell->minPreferredLogicalWidth(), columnLayout.minLogicalWidth); - if (cell->maxPreferredLogicalWidth() > columnLayout.maxLogicalWidth) { - columnLayout.maxLogicalWidth = cell->maxPreferredLogicalWidth(); + columnLayout.minLogicalWidth = std::max(cell->minPreferredLogicalWidth().ceilToFloat(), columnLayout.minLogicalWidth); + float maxPreferredWidth = cell->maxPreferredLogicalWidth().ceilToFloat(); + if (maxPreferredWidth > columnLayout.maxLogicalWidth) { + columnLayout.maxLogicalWidth = maxPreferredWidth; maxContributor = cell; } // All browsers implement a size limit on the cell's max width. // Our limit is based on KHTML's representation that used 16 bits widths. // FIXME: Other browsers have a lower limit for the cell's max width. - const int cCellMaxWidth = 32760; + const float cCellMaxWidth = 32760; Length cellLogicalWidth = cell->styleOrColLogicalWidth(); if (cellLogicalWidth.value() > cCellMaxWidth) - cellLogicalWidth.setValue(cCellMaxWidth); + cellLogicalWidth.setValue(Fixed, cCellMaxWidth); if (cellLogicalWidth.isNegative()) - cellLogicalWidth.setValue(0); + cellLogicalWidth.setValue(Fixed, 0); switch (cellLogicalWidth.type()) { case Fixed: // ignore width=0 - if (cellLogicalWidth.isPositive() && !columnLayout.logicalWidth.isPercent()) { - int logicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(cellLogicalWidth.value()); + if (cellLogicalWidth.isPositive() && !columnLayout.logicalWidth.isPercentOrCalculated()) { + float logicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(cellLogicalWidth.value()); if (columnLayout.logicalWidth.isFixed()) { // Nav/IE weirdness if ((logicalWidth > columnLayout.logicalWidth.value()) @@ -108,7 +111,7 @@ void AutoTableLayout::recalcColumn(unsigned effCol) break; case Percent: m_hasPercent = true; - if (cellLogicalWidth.isPositive() && (!columnLayout.logicalWidth.isPercent() || cellLogicalWidth.value() > columnLayout.logicalWidth.value())) + if (cellLogicalWidth.isPositive() && (!columnLayout.logicalWidth.isPercent() || cellLogicalWidth.percent() > columnLayout.logicalWidth.percent())) columnLayout.logicalWidth = cellLogicalWidth; break; case Relative: @@ -120,7 +123,7 @@ void AutoTableLayout::recalcColumn(unsigned effCol) default: break; } - } else if (!effCol || section->primaryCellAt(i, effCol - 1) != cell) { + } else if (!effCol || section.primaryCellAt(i, effCol - 1) != cell) { // This spanning cell originates in this column. Insert the cell into spanning cells list. insertSpanCell(cell); } @@ -132,7 +135,7 @@ void AutoTableLayout::recalcColumn(unsigned effCol) if (columnLayout.logicalWidth.isFixed()) { if (m_table->document().inQuirksMode() && columnLayout.maxLogicalWidth > columnLayout.logicalWidth.value() && fixedContributor != maxContributor) { columnLayout.logicalWidth = Length(); - fixedContributor = 0; + fixedContributor = nullptr; } } @@ -158,7 +161,7 @@ void AutoTableLayout::fullRecalc() Length colLogicalWidth = column->style().logicalWidth(); if (colLogicalWidth.isAuto()) colLogicalWidth = groupLogicalWidth; - if ((colLogicalWidth.isFixed() || colLogicalWidth.isPercent()) && colLogicalWidth.isZero()) + if ((colLogicalWidth.isFixed() || colLogicalWidth.isPercentOrCalculated()) && colLogicalWidth.isZero()) colLogicalWidth = Length(); unsigned effCol = m_table->colToEffCol(currentColumn); unsigned span = column->span(); @@ -179,32 +182,50 @@ void AutoTableLayout::fullRecalc() recalcColumn(i); } +static bool shouldScaleColumnsForParent(const RenderTable& table) +{ + RenderBlock* containingBlock = table.containingBlock(); + while (containingBlock && !is<RenderView>(containingBlock)) { + // It doesn't matter if our table is auto or fixed: auto means we don't + // scale. Fixed doesn't care if we do or not because it doesn't depend + // on the cell contents' preferred widths. + if (is<RenderTableCell>(containingBlock)) + return false; + containingBlock = containingBlock->containingBlock(); + } + return true; +} + // FIXME: This needs to be adapted for vertical writing modes. -static bool shouldScaleColumns(RenderTable* table) +static bool shouldScaleColumnsForSelf(RenderTable* table) { + // Normally, scale all columns to satisfy this from CSS2.2: + // "A percentage value for a column width is relative to the table width. + // If the table has 'width: auto', a percentage represents a constraint on the column's width" + // A special case. If this table is not fixed width and contained inside // a cell, then don't bloat the maxwidth by examining percentage growth. bool scale = true; while (table) { - Length tw = table->style().width(); - if ((tw.isAuto() || tw.isPercent()) && !table->isOutOfFlowPositioned()) { - RenderBlock* cb = table->containingBlock(); - while (cb && !cb->isRenderView() && !cb->isTableCell() && - cb->style().width().isAuto() && !cb->isOutOfFlowPositioned()) - cb = cb->containingBlock(); - - table = 0; - if (cb && cb->isTableCell() && - (cb->style().width().isAuto() || cb->style().width().isPercent())) { - RenderTableCell* cell = toRenderTableCell(cb); - if (cell->colSpan() > 1 || cell->table()->style().width().isAuto()) + Length tableWidth = table->style().width(); + if ((tableWidth.isAuto() || tableWidth.isPercentOrCalculated()) && !table->isOutOfFlowPositioned()) { + RenderBlock* containingBlock = table->containingBlock(); + while (containingBlock && !is<RenderView>(*containingBlock) && !is<RenderTableCell>(*containingBlock) + && containingBlock->style().width().isAuto() && !containingBlock->isOutOfFlowPositioned()) + containingBlock = containingBlock->containingBlock(); + + table = nullptr; + if (is<RenderTableCell>(containingBlock) + && (containingBlock->style().width().isAuto() || containingBlock->style().width().isPercentOrCalculated())) { + RenderTableCell& cell = downcast<RenderTableCell>(*containingBlock); + if (cell.colSpan() > 1 || cell.table()->style().width().isAuto()) scale = false; else - table = cell->table(); + table = cell.table(); } } else - table = 0; + table = nullptr; } return scale; } @@ -213,12 +234,12 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout { fullRecalc(); - int spanMaxLogicalWidth = calcEffectiveLogicalWidth(); + float spanMaxLogicalWidth = calcEffectiveLogicalWidth(); minWidth = 0; maxWidth = 0; float maxPercent = 0; float maxNonPercent = 0; - bool scaleColumns = shouldScaleColumns(m_table); + bool scaleColumnsForSelf = shouldScaleColumnsForSelf(m_table); // We substitute 0 percent by (epsilon / percentScaleFactor) percent in two places below to avoid division by zero. // FIXME: Handle the 0% cases properly. @@ -228,10 +249,10 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout for (size_t i = 0; i < m_layoutStruct.size(); ++i) { minWidth += m_layoutStruct[i].effectiveMinLogicalWidth; maxWidth += m_layoutStruct[i].effectiveMaxLogicalWidth; - if (scaleColumns) { + if (scaleColumnsForSelf) { if (m_layoutStruct[i].effectiveLogicalWidth.isPercent()) { - float percent = std::min(static_cast<float>(m_layoutStruct[i].effectiveLogicalWidth.percent()), remainingPercent); - float logicalWidth = static_cast<float>(m_layoutStruct[i].effectiveMaxLogicalWidth) * 100 / std::max(percent, epsilon); + float percent = std::min(m_layoutStruct[i].effectiveLogicalWidth.percent(), remainingPercent); + float logicalWidth = m_layoutStruct[i].effectiveMaxLogicalWidth * 100 / std::max(percent, epsilon); maxPercent = std::max(logicalWidth, maxPercent); remainingPercent -= percent; } else @@ -239,32 +260,34 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout } } - if (scaleColumns) { + if (scaleColumnsForSelf) { maxNonPercent = maxNonPercent * 100 / std::max(remainingPercent, epsilon); - maxWidth = std::max<int>(maxWidth, static_cast<int>(std::min(maxNonPercent, static_cast<float>(tableMaxWidth)))); - maxWidth = std::max<int>(maxWidth, static_cast<int>(std::min(maxPercent, static_cast<float>(tableMaxWidth)))); + m_scaledWidthFromPercentColumns = LayoutUnit(std::min<float>(maxNonPercent, tableMaxWidth)); + m_scaledWidthFromPercentColumns = std::max(m_scaledWidthFromPercentColumns, LayoutUnit(std::min<float>(maxPercent, tableMaxWidth))); + if (m_scaledWidthFromPercentColumns > maxWidth && shouldScaleColumnsForParent(*m_table)) + maxWidth = m_scaledWidthFromPercentColumns; } - maxWidth = std::max<int>(maxWidth, spanMaxLogicalWidth); + maxWidth = std::max(maxWidth, LayoutUnit(spanMaxLogicalWidth)); } void AutoTableLayout::applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const { Length tableLogicalWidth = m_table->style().logicalWidth(); if (tableLogicalWidth.isFixed() && tableLogicalWidth.isPositive()) - minWidth = maxWidth = std::max<int>(minWidth, tableLogicalWidth.value()); + minWidth = maxWidth = std::max(minWidth, LayoutUnit(tableLogicalWidth.value())); } /* This method takes care of colspans. effWidth is the same as width for cells without colspans. If we have colspans, they get modified. */ -int AutoTableLayout::calcEffectiveLogicalWidth() +float AutoTableLayout::calcEffectiveLogicalWidth() { - int maxLogicalWidth = 0; + float maxLogicalWidth = 0; size_t nEffCols = m_layoutStruct.size(); - int spacingInRowDirection = m_table->hBorderSpacing(); + float spacingInRowDirection = m_table->hBorderSpacing(); for (size_t i = 0; i < nEffCols; ++i) { m_layoutStruct[i].effectiveLogicalWidth = m_layoutStruct[i].logicalWidth; @@ -285,16 +308,16 @@ int AutoTableLayout::calcEffectiveLogicalWidth() unsigned effCol = m_table->colToEffCol(cell->col()); size_t lastCol = effCol; - int cellMinLogicalWidth = cell->minPreferredLogicalWidth() + spacingInRowDirection; - int cellMaxLogicalWidth = cell->maxPreferredLogicalWidth() + spacingInRowDirection; + float cellMinLogicalWidth = cell->minPreferredLogicalWidth() + spacingInRowDirection; + float cellMaxLogicalWidth = cell->maxPreferredLogicalWidth() + spacingInRowDirection; float totalPercent = 0; - int spanMinLogicalWidth = 0; - int spanMaxLogicalWidth = 0; + float spanMinLogicalWidth = 0; + float spanMaxLogicalWidth = 0; bool allColsArePercent = true; bool allColsAreFixed = true; bool haveAuto = false; bool spanHasEmptyCellsOnly = true; - int fixedWidth = 0; + float fixedWidth = 0; while (lastCol < nEffCols && span > 0) { Layout& columnLayout = m_layoutStruct[lastCol]; switch (columnLayout.logicalWidth.type()) { @@ -345,19 +368,19 @@ int AutoTableLayout::calcEffectiveLogicalWidth() // can't satify this condition, treat as variable cellLogicalWidth = Length(); } else { - maxLogicalWidth = std::max(maxLogicalWidth, static_cast<int>(std::max(spanMaxLogicalWidth, cellMaxLogicalWidth) * 100 / cellLogicalWidth.percent())); + maxLogicalWidth = std::max(maxLogicalWidth, std::max(spanMaxLogicalWidth, cellMaxLogicalWidth) * 100 / cellLogicalWidth.percent()); // all non percent columns in the span get percent values to sum up correctly. float percentMissing = cellLogicalWidth.percent() - totalPercent; - int totalWidth = 0; + float totalWidth = 0; for (unsigned pos = effCol; pos < lastCol; ++pos) { - if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) + if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercentOrCalculated()) totalWidth += m_layoutStruct[pos].effectiveMaxLogicalWidth; } for (unsigned pos = effCol; pos < lastCol && totalWidth > 0; ++pos) { - if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) { - float percent = percentMissing * static_cast<float>(m_layoutStruct[pos].effectiveMaxLogicalWidth) / totalWidth; + if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercentOrCalculated()) { + float percent = percentMissing * m_layoutStruct[pos].effectiveMaxLogicalWidth / totalWidth; totalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth; percentMissing -= percent; if (percent > 0) @@ -373,38 +396,38 @@ int AutoTableLayout::calcEffectiveLogicalWidth() if (cellMinLogicalWidth > spanMinLogicalWidth) { if (allColsAreFixed) { for (unsigned pos = effCol; fixedWidth > 0 && pos < lastCol; ++pos) { - int cellLogicalWidth = std::max(m_layoutStruct[pos].effectiveMinLogicalWidth, static_cast<int>(cellMinLogicalWidth * m_layoutStruct[pos].logicalWidth.value() / fixedWidth)); + float cellLogicalWidth = std::max(m_layoutStruct[pos].effectiveMinLogicalWidth, cellMinLogicalWidth * m_layoutStruct[pos].logicalWidth.value() / fixedWidth); fixedWidth -= m_layoutStruct[pos].logicalWidth.value(); cellMinLogicalWidth -= cellLogicalWidth; m_layoutStruct[pos].effectiveMinLogicalWidth = cellLogicalWidth; } } else if (allColsArePercent) { // In this case, we just split the colspan's min amd max widths following the percentage. - int allocatedMinLogicalWidth = 0; - int allocatedMaxLogicalWidth = 0; + float allocatedMinLogicalWidth = 0; + float allocatedMaxLogicalWidth = 0; for (unsigned pos = effCol; pos < lastCol; ++pos) { ASSERT(m_layoutStruct[pos].logicalWidth.isPercent() || m_layoutStruct[pos].effectiveLogicalWidth.isPercent()); // |allColsArePercent| means that either the logicalWidth *or* the effectiveLogicalWidth are percents, handle both of them here. float percent = m_layoutStruct[pos].logicalWidth.isPercent() ? m_layoutStruct[pos].logicalWidth.percent() : m_layoutStruct[pos].effectiveLogicalWidth.percent(); - int columnMinLogicalWidth = static_cast<int>(percent * cellMinLogicalWidth / totalPercent); - int columnMaxLogicalWidth = static_cast<int>(percent * cellMaxLogicalWidth / totalPercent); + float columnMinLogicalWidth = percent * cellMinLogicalWidth / totalPercent; + float columnMaxLogicalWidth = percent * cellMaxLogicalWidth / totalPercent; m_layoutStruct[pos].effectiveMinLogicalWidth = std::max(m_layoutStruct[pos].effectiveMinLogicalWidth, columnMinLogicalWidth); m_layoutStruct[pos].effectiveMaxLogicalWidth = columnMaxLogicalWidth; allocatedMinLogicalWidth += columnMinLogicalWidth; allocatedMaxLogicalWidth += columnMaxLogicalWidth; } - ASSERT(allocatedMinLogicalWidth <= cellMinLogicalWidth); - ASSERT(allocatedMaxLogicalWidth <= cellMaxLogicalWidth); + ASSERT(allocatedMinLogicalWidth < cellMinLogicalWidth || WTF::areEssentiallyEqual(allocatedMinLogicalWidth, cellMinLogicalWidth)); + ASSERT(allocatedMaxLogicalWidth < cellMaxLogicalWidth || WTF::areEssentiallyEqual(allocatedMaxLogicalWidth, cellMaxLogicalWidth)); cellMinLogicalWidth -= allocatedMinLogicalWidth; cellMaxLogicalWidth -= allocatedMaxLogicalWidth; } else { - int remainingMaxLogicalWidth = spanMaxLogicalWidth; - int remainingMinLogicalWidth = spanMinLogicalWidth; + float remainingMaxLogicalWidth = spanMaxLogicalWidth; + float remainingMinLogicalWidth = spanMinLogicalWidth; // Give min to variable first, to fixed second, and to others third. for (unsigned pos = effCol; remainingMaxLogicalWidth >= 0 && pos < lastCol; ++pos) { if (m_layoutStruct[pos].logicalWidth.isFixed() && haveAuto && fixedWidth <= cellMinLogicalWidth) { - int colMinLogicalWidth = std::max<int>(m_layoutStruct[pos].effectiveMinLogicalWidth, m_layoutStruct[pos].logicalWidth.value()); + float colMinLogicalWidth = std::max(m_layoutStruct[pos].effectiveMinLogicalWidth, m_layoutStruct[pos].logicalWidth.value()); fixedWidth -= m_layoutStruct[pos].logicalWidth.value(); remainingMinLogicalWidth -= m_layoutStruct[pos].effectiveMinLogicalWidth; remainingMaxLogicalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth; @@ -415,8 +438,8 @@ int AutoTableLayout::calcEffectiveLogicalWidth() for (unsigned pos = effCol; remainingMaxLogicalWidth >= 0 && pos < lastCol && remainingMinLogicalWidth < cellMinLogicalWidth; ++pos) { if (!(m_layoutStruct[pos].logicalWidth.isFixed() && haveAuto && fixedWidth <= cellMinLogicalWidth)) { - int colMinLogicalWidth = std::max<int>(m_layoutStruct[pos].effectiveMinLogicalWidth, static_cast<int>(remainingMaxLogicalWidth ? cellMinLogicalWidth * static_cast<float>(m_layoutStruct[pos].effectiveMaxLogicalWidth) / remainingMaxLogicalWidth : cellMinLogicalWidth)); - colMinLogicalWidth = std::min<int>(m_layoutStruct[pos].effectiveMinLogicalWidth + (cellMinLogicalWidth - remainingMinLogicalWidth), colMinLogicalWidth); + float colMinLogicalWidth = std::max(m_layoutStruct[pos].effectiveMinLogicalWidth, remainingMaxLogicalWidth ? cellMinLogicalWidth * m_layoutStruct[pos].effectiveMaxLogicalWidth / remainingMaxLogicalWidth : cellMinLogicalWidth); + colMinLogicalWidth = std::min(m_layoutStruct[pos].effectiveMinLogicalWidth + (cellMinLogicalWidth - remainingMinLogicalWidth), colMinLogicalWidth); remainingMaxLogicalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth; remainingMinLogicalWidth -= m_layoutStruct[pos].effectiveMinLogicalWidth; cellMinLogicalWidth -= colMinLogicalWidth; @@ -425,10 +448,10 @@ int AutoTableLayout::calcEffectiveLogicalWidth() } } } - if (!cellLogicalWidth.isPercent()) { + if (!cellLogicalWidth.isPercentOrCalculated()) { if (cellMaxLogicalWidth > spanMaxLogicalWidth) { for (unsigned pos = effCol; spanMaxLogicalWidth >= 0 && pos < lastCol; ++pos) { - int colMaxLogicalWidth = std::max(m_layoutStruct[pos].effectiveMaxLogicalWidth, static_cast<int>(spanMaxLogicalWidth ? cellMaxLogicalWidth * static_cast<float>(m_layoutStruct[pos].effectiveMaxLogicalWidth) / spanMaxLogicalWidth : cellMaxLogicalWidth)); + float colMaxLogicalWidth = std::max(m_layoutStruct[pos].effectiveMaxLogicalWidth, spanMaxLogicalWidth ? cellMaxLogicalWidth * m_layoutStruct[pos].effectiveMaxLogicalWidth / spanMaxLogicalWidth : cellMaxLogicalWidth); spanMaxLogicalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth; cellMaxLogicalWidth -= colMaxLogicalWidth; m_layoutStruct[pos].effectiveMaxLogicalWidth = colMaxLogicalWidth; @@ -446,7 +469,7 @@ int AutoTableLayout::calcEffectiveLogicalWidth() } m_effectiveLogicalWidthDirty = false; - return std::min(maxLogicalWidth, INT_MAX / 2); + return std::min<float>(maxLogicalWidth, tableMaxWidth); } /* gets all cells that originate in a column and have a cellspan > 1 @@ -479,8 +502,8 @@ void AutoTableLayout::insertSpanCell(RenderTableCell *cell) void AutoTableLayout::layout() { // table layout based on the values collected in the layout structure. - int tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection(); - int available = tableLogicalWidth; + float tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection(); + float available = tableLogicalWidth; size_t nEffCols = m_table->numEffCols(); // FIXME: It is possible to be called without having properly updated our internal representation. @@ -495,18 +518,18 @@ void AutoTableLayout::layout() calcEffectiveLogicalWidth(); bool havePercent = false; - int totalRelative = 0; + float totalRelative = 0; int numAuto = 0; int numFixed = 0; float totalAuto = 0; float totalFixed = 0; float totalPercent = 0; - int allocAuto = 0; + float allocAuto = 0; unsigned numAutoEmptyCellsOnly = 0; // fill up every cell with its minWidth for (size_t i = 0; i < nEffCols; ++i) { - int cellLogicalWidth = m_layoutStruct[i].effectiveMinLogicalWidth; + float cellLogicalWidth = m_layoutStruct[i].effectiveMinLogicalWidth; m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; available -= cellLogicalWidth; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; @@ -540,23 +563,23 @@ void AutoTableLayout::layout() if (available > 0 && havePercent) { for (size_t i = 0; i < nEffCols; ++i) { Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; - if (logicalWidth.isPercent()) { - int cellLogicalWidth = std::max<int>(m_layoutStruct[i].effectiveMinLogicalWidth, minimumValueForLength(logicalWidth, tableLogicalWidth)); + if (logicalWidth.isPercentOrCalculated()) { + float cellLogicalWidth = std::max<float>(m_layoutStruct[i].effectiveMinLogicalWidth, minimumValueForLength(logicalWidth, tableLogicalWidth)); available += m_layoutStruct[i].computedLogicalWidth - cellLogicalWidth; m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; } } if (totalPercent > 100) { // remove overallocated space from the last columns - int excess = tableLogicalWidth * (totalPercent - 100) / 100; + float excess = tableLogicalWidth * (totalPercent - 100) / 100; for (unsigned i = nEffCols; i; ) { --i; - if (m_layoutStruct[i].effectiveLogicalWidth.isPercent()) { - int cellLogicalWidth = m_layoutStruct[i].computedLogicalWidth; - int reduction = std::min(cellLogicalWidth, excess); + if (m_layoutStruct[i].effectiveLogicalWidth.isPercentOrCalculated()) { + float cellLogicalWidth = m_layoutStruct[i].computedLogicalWidth; + float reduction = std::min(cellLogicalWidth, excess); // the lines below might look inconsistent, but that's the way it's handled in mozilla excess -= reduction; - int newLogicalWidth = std::max<int>(m_layoutStruct[i].effectiveMinLogicalWidth, cellLogicalWidth - reduction); + float newLogicalWidth = std::max(m_layoutStruct[i].effectiveMinLogicalWidth, cellLogicalWidth - reduction); available += cellLogicalWidth - newLogicalWidth; m_layoutStruct[i].computedLogicalWidth = newLogicalWidth; } @@ -581,7 +604,7 @@ void AutoTableLayout::layout() Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isRelative() && logicalWidth.value() != 0) { // width=0* gets effMinWidth. - int cellLogicalWidth = logicalWidth.value() * tableLogicalWidth / totalRelative; + float cellLogicalWidth = logicalWidth.value() * tableLogicalWidth / totalRelative; available += m_layoutStruct[i].computedLogicalWidth - cellLogicalWidth; m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; } @@ -594,7 +617,7 @@ void AutoTableLayout::layout() for (size_t i = 0; i < nEffCols; ++i) { Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isAuto() && totalAuto && !m_layoutStruct[i].emptyCellsOnly) { - int cellLogicalWidth = std::max<int>(m_layoutStruct[i].computedLogicalWidth, static_cast<int>(available * static_cast<float>(m_layoutStruct[i].effectiveMaxLogicalWidth) / totalAuto)); + float cellLogicalWidth = std::max(m_layoutStruct[i].computedLogicalWidth, available * m_layoutStruct[i].effectiveMaxLogicalWidth / totalAuto); available -= cellLogicalWidth; totalAuto -= m_layoutStruct[i].effectiveMaxLogicalWidth; m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth; @@ -607,7 +630,7 @@ void AutoTableLayout::layout() for (size_t i = 0; i < nEffCols; ++i) { Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isFixed()) { - int cellLogicalWidth = static_cast<int>(available * static_cast<float>(m_layoutStruct[i].effectiveMaxLogicalWidth) / totalFixed); + float cellLogicalWidth = available * m_layoutStruct[i].effectiveMaxLogicalWidth / totalFixed; available -= cellLogicalWidth; totalFixed -= m_layoutStruct[i].effectiveMaxLogicalWidth; m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth; @@ -620,7 +643,7 @@ void AutoTableLayout::layout() for (size_t i = 0; i < nEffCols; ++i) { Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isPercent()) { - int cellLogicalWidth = available * logicalWidth.percent() / totalPercent; + float cellLogicalWidth = available * logicalWidth.percent() / totalPercent; available -= cellLogicalWidth; totalPercent -= logicalWidth.percent(); m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth; @@ -639,7 +662,7 @@ void AutoTableLayout::layout() // variable columns with empty cells only don't get any width if (m_layoutStruct[i].effectiveLogicalWidth.isAuto() && m_layoutStruct[i].emptyCellsOnly) continue; - int cellLogicalWidth = available / total; + float cellLogicalWidth = available / total; available -= cellLogicalWidth; total--; m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth; @@ -647,7 +670,7 @@ void AutoTableLayout::layout() } // If we have overallocated, reduce every cell according to the difference between desired width and minwidth - // this seems to produce to the pixel exact results with IE. Wonder is some of this also holds for width distributing. + // this seems to produce to the pixel exact results with IE. Wonder if some of this also holds for width distributing. if (available < 0) { // Need to reduce cells with the following prioritization: // (1) Auto @@ -656,7 +679,7 @@ void AutoTableLayout::layout() // (4) Percent // This is basically the reverse of how we grew the cells. if (available < 0) { - int logicalWidthBeyondMin = 0; + float logicalWidthBeyondMin = 0; for (unsigned i = nEffCols; i; ) { --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; @@ -668,8 +691,8 @@ void AutoTableLayout::layout() --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isAuto()) { - int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; - int reduce = available * minMaxDiff / logicalWidthBeyondMin; + float minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; + float reduce = available * minMaxDiff / logicalWidthBeyondMin; m_layoutStruct[i].computedLogicalWidth += reduce; available -= reduce; logicalWidthBeyondMin -= minMaxDiff; @@ -680,7 +703,7 @@ void AutoTableLayout::layout() } if (available < 0) { - int logicalWidthBeyondMin = 0; + float logicalWidthBeyondMin = 0; for (unsigned i = nEffCols; i; ) { --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; @@ -692,8 +715,8 @@ void AutoTableLayout::layout() --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isRelative()) { - int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; - int reduce = available * minMaxDiff / logicalWidthBeyondMin; + float minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; + float reduce = available * minMaxDiff / logicalWidthBeyondMin; m_layoutStruct[i].computedLogicalWidth += reduce; available -= reduce; logicalWidthBeyondMin -= minMaxDiff; @@ -704,7 +727,7 @@ void AutoTableLayout::layout() } if (available < 0) { - int logicalWidthBeyondMin = 0; + float logicalWidthBeyondMin = 0; for (unsigned i = nEffCols; i; ) { --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; @@ -716,8 +739,8 @@ void AutoTableLayout::layout() --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; if (logicalWidth.isFixed()) { - int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; - int reduce = available * minMaxDiff / logicalWidthBeyondMin; + float minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; + float reduce = available * minMaxDiff / logicalWidthBeyondMin; m_layoutStruct[i].computedLogicalWidth += reduce; available -= reduce; logicalWidthBeyondMin -= minMaxDiff; @@ -728,20 +751,20 @@ void AutoTableLayout::layout() } if (available < 0) { - int logicalWidthBeyondMin = 0; + float logicalWidthBeyondMin = 0; for (unsigned i = nEffCols; i; ) { --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; - if (logicalWidth.isPercent()) + if (logicalWidth.isPercentOrCalculated()) logicalWidthBeyondMin += m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; } for (unsigned i = nEffCols; i && logicalWidthBeyondMin > 0; ) { --i; Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth; - if (logicalWidth.isPercent()) { - int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; - int reduce = available * minMaxDiff / logicalWidthBeyondMin; + if (logicalWidth.isPercentOrCalculated()) { + float minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth; + float reduce = available * minMaxDiff / logicalWidthBeyondMin; m_layoutStruct[i].computedLogicalWidth += reduce; available -= reduce; logicalWidthBeyondMin -= minMaxDiff; @@ -752,10 +775,10 @@ void AutoTableLayout::layout() } } - int pos = 0; + LayoutUnit pos = 0; for (size_t i = 0; i < nEffCols; ++i) { m_table->setColumnPosition(i, pos); - pos += m_layoutStruct[i].computedLogicalWidth + m_table->hBorderSpacing(); + pos += LayoutUnit::fromFloatCeil(m_layoutStruct[i].computedLogicalWidth) + m_table->hBorderSpacing(); } m_table->setColumnPosition(m_table->columnPositions().size() - 1, pos); } |