FixedTableLayout.cpp [plain text]
#include "config.h"
#include "FixedTableLayout.h"
#include "RenderTable.h"
#include "RenderTableCell.h"
#include "RenderTableCol.h"
#include "RenderTableSection.h"
using namespace std;
namespace WebCore {
FixedTableLayout::FixedTableLayout(RenderTable* table)
: TableLayout(table)
{
}
int FixedTableLayout::calcWidthArray(int)
{
int usedWidth = 0;
RenderObject* child = m_table->firstChild();
int cCol = 0;
int nEffCols = m_table->numEffCols();
m_width.resize(nEffCols);
m_width.fill(Length(Auto));
Length grpWidth;
while (child) {
if (child->isTableCol()) {
RenderTableCol *col = static_cast<RenderTableCol *>(child);
int span = col->span();
if (col->firstChild())
grpWidth = col->style()->width();
else {
Length w = col->style()->width();
if (w.isAuto())
w = grpWidth;
int effWidth = 0;
if (w.isFixed() && w.value() > 0)
effWidth = w.value();
int usedSpan = 0;
int i = 0;
while (usedSpan < span) {
if(cCol + i >= nEffCols) {
m_table->appendColumn(span - usedSpan);
nEffCols++;
m_width.resize(nEffCols);
m_width[nEffCols-1] = Length();
}
int eSpan = m_table->spanOfEffCol(cCol+i);
if ((w.isFixed() || w.isPercent()) && w.isPositive()) {
m_width[cCol + i].setRawValue(w.type(), w.rawValue() * eSpan);
usedWidth += effWidth * eSpan;
}
usedSpan += eSpan;
i++;
}
cCol += i;
}
} else
break;
RenderObject *next = child->firstChild();
if (!next)
next = child->nextSibling();
if (!next && child->parent()->isTableCol()) {
next = child->parent()->nextSibling();
grpWidth = Length();
}
child = next;
}
RenderTableSection* section = m_table->header();
if (!section)
section = m_table->firstBody();
if (!section)
section = m_table->footer();
if (section && !section->numRows())
section = m_table->sectionBelow(section, true);
if (section) {
cCol = 0;
RenderObject* firstRow = section->firstChild();
child = firstRow->firstChild();
while (child) {
if (child->isTableCell()) {
RenderTableCell* cell = static_cast<RenderTableCell*>(child);
if (cell->prefWidthsDirty())
cell->calcPrefWidths();
Length w = cell->styleOrColWidth();
int span = cell->colSpan();
int effWidth = 0;
if (w.isFixed() && w.isPositive())
effWidth = w.value();
int usedSpan = 0;
int i = 0;
while (usedSpan < span) {
ASSERT(cCol + i < nEffCols);
int eSpan = m_table->spanOfEffCol(cCol + i);
if (m_width[cCol + i].isAuto() && w.type() != Auto) {
m_width[cCol + i].setRawValue(w.type(), w.rawValue() * eSpan / span);
usedWidth += effWidth * eSpan / span;
}
usedSpan += eSpan;
i++;
}
cCol += i;
}
child = child->nextSibling();
}
}
return usedWidth;
}
void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth)
{
int bs = m_table->bordersPaddingAndSpacing();
int tableWidth = m_table->style()->width().isFixed() ? m_table->style()->width().value() - bs : 0;
int mw = calcWidthArray(tableWidth) + bs;
minWidth = max(mw, tableWidth);
maxWidth = minWidth;
}
void FixedTableLayout::layout()
{
int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing();
int nEffCols = m_table->numEffCols();
Vector<int> calcWidth(nEffCols, 0);
int numAuto = 0;
int autoSpan = 0;
int totalFixedWidth = 0;
int totalPercentWidth = 0;
int totalRawPercent = 0;
for (int 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] = m_width[i].calcValue(tableWidth);
totalPercentWidth += calcWidth[i];
totalRawPercent += m_width[i].rawValue();
} else if (m_width[i].isAuto()) {
numAuto++;
autoSpan += m_table->spanOfEffCol(i);
}
}
int hspacing = m_table->hBorderSpacing();
int totalWidth = totalFixedWidth + totalPercentWidth;
if (!numAuto || totalWidth > tableWidth) {
if (totalWidth != tableWidth) {
if (totalFixedWidth && totalWidth < tableWidth) {
totalFixedWidth = 0;
for (int i = 0; i < nEffCols; i++) {
if (m_width[i].isFixed()) {
calcWidth[i] = calcWidth[i] * tableWidth / totalWidth;
totalFixedWidth += calcWidth[i];
}
}
}
if (totalRawPercent) {
totalPercentWidth = 0;
for (int i = 0; i < nEffCols; i++) {
if (m_width[i].isPercent()) {
calcWidth[i] = m_width[i].rawValue() * (tableWidth - totalFixedWidth) / totalRawPercent;
totalPercentWidth += calcWidth[i];
}
}
}
totalWidth = totalFixedWidth + totalPercentWidth;
}
} else {
int remainingWidth = tableWidth - totalFixedWidth - totalPercentWidth - hspacing * (autoSpan - numAuto);
int lastAuto = 0;
for (int i = 0; i < nEffCols; i++) {
if (m_width[i].isAuto()) {
int span = m_table->spanOfEffCol(i);
int w = remainingWidth * span / autoSpan;
calcWidth[i] = w + hspacing * (span - 1);
remainingWidth -= w;
if (!remainingWidth)
break;
lastAuto = i;
numAuto--;
autoSpan -= span;
}
}
if (remainingWidth)
calcWidth[lastAuto] += remainingWidth;
totalWidth = tableWidth;
}
if (totalWidth < tableWidth) {
int remainingWidth = tableWidth - 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 (int i = 0; i < nEffCols; i++) {
m_table->columnPositions()[i] = pos;
pos += calcWidth[i] + hspacing;
}
int colPositionsSize = m_table->columnPositions().size();
if (colPositionsSize > 0)
m_table->columnPositions()[colPositionsSize - 1] = pos;
}
}