📄 render_table.cpp
字号:
void RenderTable::updateFirstLetter()
{}
#ifndef NDEBUG
void RenderTable::dump(QTextStream *stream, QString ind) const
{
if (tCaption)
*stream << " tCaption";
if (head)
*stream << " head";
if (foot)
*stream << " foot";
*stream << endl << ind << "cspans:";
for ( unsigned int i = 0; i < columns.size(); i++ )
*stream << " " << columns[i].span;
*stream << endl << ind;
RenderBlock::dump(stream,ind);
}
#endif
// --------------------------------------------------------------------------
RenderTableSection::RenderTableSection(DOM::NodeImpl* node)
: RenderContainer(node)
{
// init RenderObject attributes
setInline(false); // our object is not Inline
gridRows = 0;
cCol = 0;
cRow = -1;
needCellRecalc = false;
}
RenderTableSection::~RenderTableSection()
{
clearGrid();
}
void RenderTableSection::detach()
{
// recalc cell info because RenderTable has unguarded pointers
// stored that point to this RenderTableSection.
if (table())
table()->setNeedSectionRecalc();
RenderContainer::detach();
}
void RenderTableSection::setStyle(RenderStyle* _style)
{
// we don't allow changing this one
if (style())
_style->setDisplay(style()->display());
else if (_style->display() != TABLE_FOOTER_GROUP && _style->display() != TABLE_HEADER_GROUP)
_style->setDisplay(TABLE_ROW_GROUP);
RenderContainer::setStyle(_style);
}
void RenderTableSection::addChild(RenderObject *child, RenderObject *beforeChild)
{
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << renderName() << "(TableSection)::addChild( " << child->renderName() << ", beforeChild=" <<
(beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
#endif
RenderObject *row = child;
if (child->element() && child->element()->id() == ID_FORM) {
RenderContainer::addChild(child,beforeChild);
return;
}
if ( !child->isTableRow() ) {
if( !beforeChild )
beforeChild = lastChild();
if( beforeChild && beforeChild->isAnonymous() )
row = beforeChild;
else {
RenderObject *lastBox = beforeChild;
while ( lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow() )
lastBox = lastBox->parent();
if ( lastBox && lastBox->isAnonymous() ) {
lastBox->addChild( child, beforeChild );
return;
} else {
//kdDebug( 6040 ) << "creating anonymous table row" << endl;
row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
RenderStyle *newStyle = new (renderArena()) RenderStyle();
newStyle->inheritFrom(style());
newStyle->setDisplay( TABLE_ROW );
row->setStyle(newStyle);
addChild(row, beforeChild);
}
}
row->addChild(child);
child->setNeedsLayoutAndMinMaxRecalc();
return;
}
if (beforeChild)
setNeedCellRecalc();
cRow++;
cCol = 0;
ensureRows( cRow+1 );
if (!beforeChild) {
grid[cRow].height = child->style()->height();
if ( grid[cRow].height.type == Relative )
grid[cRow].height = Length();
}
RenderContainer::addChild(child,beforeChild);
}
void RenderTableSection::ensureRows(int numRows)
{
int nRows = gridRows;
if (numRows > nRows) {
if (numRows > static_cast<int>(grid.size()))
grid.resize(numRows*2+1);
gridRows = numRows;
int nCols = table()->numEffCols();
for (int r = nRows; r < numRows; r++ ) {
grid[r].row = new Row(nCols);
grid[r].row->fill(0);
grid[r].baseLine = 0;
grid[r].height = Length();
}
}
}
void RenderTableSection::addCell( RenderTableCell *cell )
{
int rSpan = cell->rowSpan();
int cSpan = cell->colSpan();
QMemArray<RenderTable::ColumnStruct> &columns = table()->columns;
int nCols = columns.size();
// ### mozilla still seems to do the old HTML way, even for strict DTD
// (see the annotation on table cell layouting in the CSS specs and the testcase below:
// <TABLE border>
// <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
// <TR><TD colspan="2">5
// </TABLE>
#if 0
// find empty space for the cell
bool found = false;
while ( !found ) {
found = true;
while ( cCol < nCols && cellAt( cRow, cCol ) )
cCol++;
int pos = cCol;
int span = 0;
while ( pos < nCols && span < cSpan ) {
if ( cellAt( cRow, pos ) ) {
found = false;
cCol = pos;
break;
}
span += columns[pos].span;
pos++;
}
}
#else
while ( cCol < nCols && cellAt( cRow, cCol ) )
cCol++;
#endif
// qDebug("adding cell at %d/%d span=(%d/%d)", cRow, cCol, rSpan, cSpan );
if ( rSpan == 1 ) {
// we ignore height settings on rowspan cells
Length height = cell->style()->height();
if ( height.value > 0 || (height.type == Relative && height.value >= 0) ) {
Length cRowHeight = grid[cRow].height;
switch( height.type ) {
case Percent:
if ( !(cRowHeight.type == Percent) ||
( cRowHeight.type == Percent && cRowHeight.value < height.value ) )
grid[cRow].height = height;
break;
case Fixed:
if ( cRowHeight.type < Percent ||
( cRowHeight.type == Fixed && cRowHeight.value < height.value ) )
grid[cRow].height = height;
break;
case Relative:
#if 0
// we treat this as variable. This is correct according to HTML4, as it only specifies length for the height.
if ( cRowHeight.type == Variable ||
( cRowHeight.type == Relative && cRowHeight.value < height.value ) )
grid[cRow].height = height;
break;
#endif
default:
break;
}
}
}
// make sure we have enough rows
ensureRows( cRow + rSpan );
int col = cCol;
// tell the cell where it is
RenderTableCell *set = cell;
while ( cSpan ) {
int currentSpan;
if ( cCol >= nCols ) {
table()->appendColumn( cSpan );
currentSpan = cSpan;
} else {
if ( cSpan < columns[cCol].span )
table()->splitColumn( cCol, cSpan );
currentSpan = columns[cCol].span;
}
int r = 0;
while ( r < rSpan ) {
if ( !cellAt( cRow + r, cCol ) ) {
// qDebug(" adding cell at %d, %d", cRow + r, cCol );
cellAt( cRow + r, cCol ) = set;
}
r++;
}
cCol++;
cSpan -= currentSpan;
set = (RenderTableCell *)-1;
}
if ( cell ) {
cell->setRow( cRow );
cell->setCol( table()->effColToCol( col ) );
}
}
void RenderTableSection::setCellWidths()
{
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
#endif
QMemArray<int> &columnPos = table()->columnPos;
int rows = gridRows;
for ( int i = 0; i < rows; i++ ) {
Row &row = *grid[i].row;
int cols = row.size();
for ( int j = 0; j < cols; j++ ) {
RenderTableCell *cell = row[j];
// qDebug("cell[%d,%d] = %p", i, j, cell );
if ( !cell || cell == (RenderTableCell *)-1 )
continue;
int endCol = j;
int cspan = cell->colSpan();
while ( cspan && endCol < cols ) {
cspan -= table()->columns[endCol].span;
endCol++;
}
int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << "setting width of cell " << cell << " " << cell->row() << "/" << cell->col() << " to " << w << " colspan=" << cell->colSpan() << " start=" << j << " end=" << endCol << endl;
#endif
int oldWidth = cell->width();
if ( w != oldWidth ) {
cell->setNeedsLayout(true);
cell->setWidth( w );
}
}
}
}
void RenderTableSection::calcRowHeight()
{
int indx;
RenderTableCell *cell;
int totalRows = gridRows;
int spacing = table()->vBorderSpacing();
rowPos.resize( totalRows + 1 );
rowPos[0] = spacing;
for ( int r = 0; r < totalRows; r++ ) {
rowPos[r+1] = 0;
int baseline=0;
int bdesc = 0;
// qDebug("height of row %d is %d/%d", r, grid[r].height.value, grid[r].height.type );
int ch = grid[r].height.minWidth( 0 );
int pos = rowPos[ r+1 ] + ch + spacing;
if ( pos > rowPos[r+1] )
rowPos[r+1] = pos;
Row *row = grid[r].row;
int totalCols = row->size();
int totalRows = gridRows;
for ( int c = 0; c < totalCols; c++ ) {
cell = cellAt(r, c);
if ( !cell || cell == (RenderTableCell *)-1 )
continue;
if ( r < totalRows - 1 && cellAt(r+1, c) == cell )
continue;
if ( ( indx = r - cell->rowSpan() + 1 ) < 0 )
indx = 0;
if (cell->overrideSize() != -1) {
cell->setOverrideSize(-1);
cell->setChildNeedsLayout(true, false);
cell->layoutIfNeeded();
}
// Explicit heights use the border box in quirks mode. In strict mode do the right
// thing and actually add in the border and padding.
ch = cell->style()->height().width(0) +
(cell->style()->htmlHacks() ? 0 : (cell->paddingTop() + cell->paddingBottom() +
cell->borderTop() + cell->borderBottom()));
if (cell->height() > ch)
ch = cell->height();
pos = rowPos[ indx ] + ch + spacing;
if ( pos > rowPos[r+1] )
rowPos[r+1] = pos;
// find out the baseline
EVerticalAlign va = cell->style()->verticalAlign();
if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP
|| va == SUPER || va == SUB)
{
int b=cell->baselinePosition();
if (b>baseline)
baseline=b;
int td = rowPos[ indx ] + ch - b;
if (td>bdesc)
bdesc = td;
}
}
//do we have baseline aligned elements?
if (baseline) {
// increase rowheight if baseline requires
int bRowPos = baseline + bdesc + spacing ; // + 2*padding
if (rowPos[r+1]<bRowPos)
rowPos[r+1]=bRowPos;
grid[r].baseLine = baseline;
}
if ( rowPos[r+1] < rowPos[r] )
rowPos[r+1] = rowPos[r];
// qDebug("rowpos(%d)=%d", r, rowPos[r] );
}
}
int RenderTableSection::layoutRows( int toAdd )
{
int rHeight;
int rindx;
int totalRows = gridRows;
int hspacing = table()->hBorderSpacing();
int vspacing = table()->vBorderSpacing();
if (toAdd && totalRows && (rowPos[totalRows] || !nextSibling())) {
int totalHeight = rowPos[totalRows] + toAdd;
// qDebug("layoutRows: totalHeight = %d", totalHeight );
int dh = toAdd;
int totalPercent = 0;
int numVariable = 0;
for ( int r = 0; r < totalRows; r++ ) {
if ( grid[r].height.type == Variable )
numVariable++;
else if ( grid[r].height.type == Percent )
totalPercent += grid[r].height.value;
}
if ( totalPercent ) {
// qDebug("distributing %d over percent rows totalPercent=%d", dh, totalPercent );
// try to satisfy percent
int add = 0;
if ( totalPercent > 100 )
totalPercent = 100;
int rh = rowPos[1]-rowPos[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -