This source file includes following definitions.
- calcWidthArray
- computeIntrinsicLogicalWidths
- applyPreferredLogicalWidthQuirks
- layout
- willChangeTableLayout
#include "config.h"
#include "core/rendering/FixedTableLayout.h"
#include "core/rendering/RenderTable.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderTableCol.h"
#include "core/rendering/RenderTableSection.h"
#include "platform/LayoutUnit.h"
using namespace std;
namespace WebCore {
FixedTableLayout::FixedTableLayout(RenderTable* table)
: TableLayout(table)
{
}
int FixedTableLayout::calcWidthArray()
{
int usedWidth = 0;
unsigned nEffCols = m_table->numEffCols();
m_width.resize(nEffCols);
m_width.fill(Length(Auto));
unsigned currentEffectiveColumn = 0;
for (RenderTableCol* col = m_table->firstColumn(); col; col = col->nextColumn()) {
col->clearPreferredLogicalWidthsDirtyBits();
if (col->isTableColumnGroupWithColumnChildren())
continue;
Length colStyleLogicalWidth = col->style()->logicalWidth();
int effectiveColWidth = 0;
if (colStyleLogicalWidth.isFixed() && colStyleLogicalWidth.value() > 0)
effectiveColWidth = colStyleLogicalWidth.value();
unsigned span = col->span();
while (span) {
unsigned spanInCurrentEffectiveColumn;
if (currentEffectiveColumn >= nEffCols) {
m_table->appendColumn(span);
nEffCols++;
m_width.append(Length());
spanInCurrentEffectiveColumn = span;
} else {
if (span < m_table->spanOfEffCol(currentEffectiveColumn)) {
m_table->splitColumn(currentEffectiveColumn, span);
nEffCols++;
m_width.append(Length());
}
spanInCurrentEffectiveColumn = m_table->spanOfEffCol(currentEffectiveColumn);
}
if ((colStyleLogicalWidth.isFixed() || colStyleLogicalWidth.isPercent()) && colStyleLogicalWidth.isPositive()) {
m_width[currentEffectiveColumn] = colStyleLogicalWidth;
m_width[currentEffectiveColumn] *= spanInCurrentEffectiveColumn;
usedWidth += effectiveColWidth * spanInCurrentEffectiveColumn;
}
span -= spanInCurrentEffectiveColumn;
currentEffectiveColumn++;
}
}
RenderTableSection* section = m_table->topNonEmptySection();
if (!section)
return usedWidth;
unsigned currentColumn = 0;
RenderObject* firstRow = section->firstChild();
for (RenderObject* child = firstRow->firstChild(); child; child = child->nextSibling()) {
if (!child->isTableCell())
continue;
RenderTableCell* cell = toRenderTableCell(child);
Length logicalWidth = cell->styleOrColLogicalWidth();
unsigned span = cell->colSpan();
int fixedBorderBoxLogicalWidth = 0;
if (logicalWidth.isFixed() && logicalWidth.isPositive()) {
fixedBorderBoxLogicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(logicalWidth.value());
logicalWidth.setValue(fixedBorderBoxLogicalWidth);
}
unsigned usedSpan = 0;
while (usedSpan < span && currentColumn < nEffCols) {
float eSpan = m_table->spanOfEffCol(currentColumn);
if (m_width[currentColumn].isAuto() && logicalWidth.type() != Auto) {
m_width[currentColumn] = logicalWidth;
m_width[currentColumn] *= eSpan / span;
usedWidth += fixedBorderBoxLogicalWidth * eSpan / span;
}
usedSpan += eSpan;
++currentColumn;
}
if (cell->preferredLogicalWidthsDirty())
cell->clearPreferredLogicalWidthsDirty();
}
return usedWidth;
}
void FixedTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth)
{
minWidth = maxWidth = calcWidthArray();
}
void FixedTableLayout::applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
{
Length tableLogicalWidth = m_table->style()->logicalWidth();
if (tableLogicalWidth.isFixed() && tableLogicalWidth.isPositive())
minWidth = maxWidth = max<int>(minWidth, tableLogicalWidth.value() - m_table->bordersPaddingAndSpacingInRowDirection());
if (m_table->style()->logicalWidth().isPercent() && maxWidth < tableMaxWidth)
maxWidth = tableMaxWidth;
}
void FixedTableLayout::layout()
{
int tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection();
unsigned nEffCols = m_table->numEffCols();
if (nEffCols != m_width.size()) {
calcWidthArray();
nEffCols = m_table->numEffCols();
}
Vector<int> calcWidth(nEffCols, 0);
unsigned numAuto = 0;
unsigned autoSpan = 0;
int totalFixedWidth = 0;
int totalPercentWidth = 0;
float totalPercent = 0;
for (unsigned i = 0; i < nEffCols; i++) {
if (m_width[i].isFixed()) {
calcWidth[i] = m_width[i].value();
totalFixedWidth += calcWidth[i];
} else if (m_width[i].isPercent()) {
calcWidth[i] = valueForLength(m_width[i], tableLogicalWidth);
totalPercentWidth += calcWidth[i];
totalPercent += m_width[i].percent();
} else if (m_width[i].isAuto()) {
numAuto++;
autoSpan += m_table->spanOfEffCol(i);
}
}
int hspacing = m_table->hBorderSpacing();
int totalWidth = totalFixedWidth + totalPercentWidth;
if (!numAuto || totalWidth > tableLogicalWidth) {
if (totalWidth != tableLogicalWidth) {
if (totalFixedWidth && totalWidth < tableLogicalWidth) {
totalFixedWidth = 0;
for (unsigned i = 0; i < nEffCols; i++) {
if (m_width[i].isFixed()) {
calcWidth[i] = calcWidth[i] * tableLogicalWidth / totalWidth;
totalFixedWidth += calcWidth[i];
}
}
}
if (totalPercent) {
totalPercentWidth = 0;
for (unsigned i = 0; i < nEffCols; i++) {
if (m_width[i].isPercent()) {
calcWidth[i] = m_width[i].percent() * (tableLogicalWidth - totalFixedWidth) / totalPercent;
totalPercentWidth += calcWidth[i];
}
}
}
totalWidth = totalFixedWidth + totalPercentWidth;
}
} else {
ASSERT(autoSpan >= numAuto);
int remainingWidth = tableLogicalWidth - totalFixedWidth - totalPercentWidth - hspacing * (autoSpan - numAuto);
int lastAuto = 0;
for (unsigned i = 0; i < nEffCols; i++) {
if (m_width[i].isAuto()) {
unsigned span = m_table->spanOfEffCol(i);
int w = remainingWidth * span / autoSpan;
calcWidth[i] = w + hspacing * (span - 1);
remainingWidth -= w;
if (!remainingWidth)
break;
lastAuto = i;
numAuto--;
ASSERT(autoSpan >= span);
autoSpan -= span;
}
}
if (remainingWidth)
calcWidth[lastAuto] += remainingWidth;
totalWidth = tableLogicalWidth;
}
if (totalWidth < tableLogicalWidth) {
int remainingWidth = tableLogicalWidth - totalWidth;
int total = nEffCols;
while (total) {
int w = remainingWidth / total;
remainingWidth -= w;
calcWidth[--total] += w;
}
if (nEffCols > 0)
calcWidth[nEffCols - 1] += remainingWidth;
}
int pos = 0;
for (unsigned i = 0; i < nEffCols; i++) {
m_table->setColumnPosition(i, pos);
pos += calcWidth[i] + hspacing;
}
int colPositionsSize = m_table->columnPositions().size();
if (colPositionsSize > 0)
m_table->setColumnPosition(colPositionsSize - 1, pos);
}
void FixedTableLayout::willChangeTableLayout()
{
m_table->recalcSectionsIfNeeded();
for (RenderTableSection* section = m_table->topNonEmptySection(); section; section = m_table->sectionBelow(section)) {
for (unsigned i = 0; i < section->numRows(); i++) {
RenderTableRow* row = section->rowRendererAt(i);
if (!row)
continue;
for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
if (!cell->isTableCell())
continue;
cell->setPreferredLogicalWidthsDirty();
}
}
}
}
}