📄 render_table.cpp
字号:
for ( int r = 0; r < totalRows; r++ ) {
if ( totalPercent > 0 && grid[r].height.type == Percent ) {
int toAdd = kMin(dh, (totalHeight * grid[r].height.value / 100)-rh);
// If toAdd is negative, then we don't want to shrink the row (this bug
// affected Outlook Web Access).
toAdd = QMAX(0, toAdd);
add += toAdd;
dh -= toAdd;
totalPercent -= grid[r].height.value;
// qDebug( "adding %d to row %d", toAdd, r );
}
if ( r < totalRows-1 )
rh = rowPos[r+2] - rowPos[r+1];
rowPos[r+1] += add;
}
}
if ( numVariable ) {
// distribute over variable cols
// qDebug("distributing %d over variable rows numVariable=%d", dh, numVariable );
int add = 0;
for ( int r = 0; r < totalRows; r++ ) {
if ( numVariable > 0 && grid[r].height.type == Variable ) {
int toAdd = dh/numVariable;
add += toAdd;
dh -= toAdd;
numVariable--;
}
rowPos[r+1] += add;
}
}
if (dh>0 && rowPos[totalRows]) {
// if some left overs, distribute equally.
int tot=rowPos[totalRows];
int add=0;
int prev=rowPos[0];
for ( int r = 0; r < totalRows; r++ ) {
//weight with the original height
add+=dh*(rowPos[r+1]-prev)/tot;
prev=rowPos[r+1];
rowPos[r+1]+=add;
}
}
}
int leftOffset = hspacing;
int nEffCols = table()->numEffCols();
for ( int r = 0; r < totalRows; r++ )
{
Row *row = grid[r].row;
int totalCols = row->size();
for ( int c = 0; c < nEffCols; c++ )
{
RenderTableCell *cell = cellAt(r, c);
if (!cell || cell == (RenderTableCell *)-1 )
continue;
if ( r < totalRows - 1 && cell == cellAt(r+1, c) )
continue;
if ( ( rindx = r-cell->rowSpan()+1 ) < 0 )
rindx = 0;
rHeight = rowPos[r+1] - rowPos[rindx] - vspacing;
// Force percent height children to lay themselves out again.
// This will cause these children to grow to fill the cell.
// FIXME: There is still more work to do here to fully match WinIE (should
// it become necessary to do so). In quirks mode, WinIE behaves like we
// do, but it will clip the cells that spill out of the table section. In
// strict mode, Mozilla and WinIE both regrow the table to accommodate the
// new height of the cell (thus letting the percentages cause growth one
// time only). We may also not be handling row-spanning cells correctly.
//
// Note also the oddity where replaced elements always flex, and yet blocks/tables do
// not necessarily flex. WinIE is crazy and inconsistent, and we can't hope to
// match the behavior perfectly, but we'll continue to refine it as we discover new
// bugs. :)
bool cellChildrenFlex = false;
bool flexAllChildren = cell->style()->height().isFixed() ||
(!table()->style()->height().isVariable() && rHeight != cell->height());
RenderObject* o = cell->firstChild();
while (o) {
if (!o->isText() && o->style()->height().isPercent() && (o->isReplaced() || o->scrollsOverflow() || flexAllChildren)) {
// Tables with no sections do not flex.
if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
o->setNeedsLayout(true, false);
cell->setChildNeedsLayout(true, false);
cellChildrenFlex = true;
}
}
o = o->nextSibling();
}
if (cellChildrenFlex) {
cell->setOverrideSize(kMax(0,
rHeight - cell->borderTop() - cell->paddingTop() -
cell->borderBottom() - cell->paddingBottom()));
cell->layoutIfNeeded();
// Alignment within a cell is based off the calculated
// height, which becomes irrelevant once the cell has
// been resized based off its percentage. -dwh
cell->setCellTopExtra(0);
cell->setCellBottomExtra(0);
}
else {
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << "setting position " << r << "/" << c << ": "
<< table()->columnPos[c] /*+ padding */ << "/" << rowPos[rindx] << " height=" << rHeight<< endl;
#endif
EVerticalAlign va = cell->style()->verticalAlign();
int te=0;
switch (va)
{
case SUB:
case SUPER:
case TEXT_TOP:
case TEXT_BOTTOM:
case BASELINE:
te = getBaseline(r) - cell->baselinePosition() ;
break;
case TOP:
te = 0;
break;
case MIDDLE:
te = (rHeight - cell->height())/2;
break;
case BOTTOM:
te = rHeight - cell->height();
break;
default:
break;
}
#ifdef DEBUG_LAYOUT
// kdDebug( 6040 ) << "CELL " << cell << " te=" << te << ", be=" << rHeight - cell->height() - te << ", rHeight=" << rHeight << ", valign=" << va << endl;
#endif
cell->setCellTopExtra( te );
cell->setCellBottomExtra( rHeight - cell->height() - te);
}
int oldCellX = cell->xPos();
int oldCellY = cell->yPos();
if (style()->direction()==RTL) {
cell->setPos(
table()->columnPos[(int)totalCols] -
table()->columnPos[table()->colToEffCol(cell->col()+cell->colSpan())] +
leftOffset,
rowPos[rindx] );
} else {
cell->setPos( table()->columnPos[c] + leftOffset, rowPos[rindx] );
}
// If the cell moved, we have to repaint it as well as any floating/positioned
// descendants. An exception is if we need a layout. In this case, we know we're going to
// repaint ourselves (and the cell) anyway.
if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
cell->repaintDuringLayoutIfMoved(oldCellX, oldCellY);
}
}
m_height = rowPos[totalRows];
return m_height;
}
void RenderTableSection::paint(PaintInfo& i, int tx, int ty)
{
#if 0
// crashed accessing rowPos (if layout was not called?)
unsigned int totalRows = rowPos.size();
#else
unsigned int totalRows = gridRows;
#endif
unsigned int totalCols = table()->columns.size();
tx += m_x;
ty += m_y;
#ifdef NOKIA_CHANGES
if(needsLayout()) return;
#endif
// check which rows and cols are visible and only paint these
// ### fixme: could use a binary search here
PaintAction paintAction = i.phase;
int x = i.r.x(); int y = i.r.y(); int w = i.r.width(); int h = i.r.height();
int os = 2*maximalOutlineSize(paintAction);
unsigned int startrow = 0;
unsigned int endrow = totalRows;
for ( ; startrow < totalRows; startrow++ ) {
if ( ty + rowPos[startrow+1] >= y - os)
break;
}
for ( ; endrow > 0; endrow-- ) {
if ( ty + rowPos[endrow-1] <= y + h + os)
break;
}
unsigned int startcol = 0;
unsigned int endcol = totalCols;
if ( style()->direction() == LTR ) {
for ( ; startcol < totalCols; startcol++ ) {
if ( tx + table()->columnPos[startcol+1] >= x - os)
break;
}
for ( ; endcol > 0; endcol-- ) {
if ( tx + table()->columnPos[endcol-1] <= x + w + os)
break;
}
}
if ( startcol < endcol ) {
// draw the cells
for ( unsigned int r = startrow; r < endrow; r++ ) {
unsigned int c = startcol;
// since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
while ( c && cellAt( r, c ) == (RenderTableCell *)-1 )
c--;
for ( ; c < endcol; c++ ) {
RenderTableCell *cell = cellAt(r, c);
if (!cell || cell == (RenderTableCell *)-1 )
continue;
// Cells must always paint in the order in which they appear taking into account
// their upper left originating row/column. For cells with rowspans, avoid repainting
// if we've already seen the cell.
if (r > startrow && (cellAt(r-1, c) == cell))
continue;
#ifdef TABLE_PRINT
kdDebug( 6040 ) << "painting cell " << r << "/" << c << endl;
#endif
cell->paint(i, tx, ty);
}
}
}
}
#ifdef NOKIA_CHANGES
void RenderTableSection::getRenderersInRect(QPtrList<BoxInfo>& boxInfoList,int deltaX,int deltaY,const QRect& rect)
{
#if 0
// crashed accessing rowPos (if layout was not called?)
unsigned int totalRows = rowPos.size();
#else
unsigned int totalRows = gridRows;
#endif
unsigned int totalCols = table()->columns.size();
deltaX += m_x;
deltaY += m_y;
if(needsLayout()) return;
int x = rect.x(); int y = rect.y(); int w = rect.width(); int h = rect.height();
unsigned int startrow = 0;
unsigned int endrow = totalRows;
for ( ; startrow < totalRows; startrow++ ) {
if ( deltaY + rowPos[startrow+1] >= y )
break;
}
for ( ; endrow > 0; endrow-- ) {
if ( deltaY + rowPos[endrow-1] <= y + h)
break;
}
unsigned int startcol = 0;
unsigned int endcol = totalCols;
if ( style()->direction() == LTR ) {
for ( ; startcol < totalCols; startcol++ ) {
if ( deltaX + table()->columnPos[startcol+1] >= x )
break;
}
for ( ; endcol > 0; endcol-- ) {
if ( deltaX + table()->columnPos[endcol-1] <= x + w )
break;
}
}
if ( startcol < endcol ) {
//This means that some cells are in the view
BoxInfo* sel = new BoxInfo;
sel->renderObject = this;
sel->absoluteXPos = deltaX;
sel->absoluteYPos = deltaY;
sel->width = width();
sel->height = height();
sel->area = 0;
boxInfoList.append(sel);
// draw the cells
for ( unsigned int r = startrow; r < endrow; r++ ) {
unsigned int c = startcol;
// since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
while ( c && cellAt( r, c ) == (RenderTableCell *)-1 )
c--;
for ( ; c < endcol; c++ ) {
RenderTableCell *cell = cellAt(r, c);
if (!cell || cell == (RenderTableCell *)-1 )
continue;
// Cells must always paint in the order in which they appear taking into account
// their upper left originating row/column. For cells with rowspans, avoid repainting
// if we've already seen the cell.
if (r > startrow && (cellAt(r-1, c) == cell))
continue;
cell->getRenderersInRect(boxInfoList, deltaX, deltaY,rect);
}
}
}
}
#endif
void RenderTableSection::recalcCells()
{
cCol = 0;
cRow = -1;
clearGrid();
gridRows = 0;
RenderObject *row = firstChild();
while ( row ) {
cRow++;
cCol = 0;
ensureRows( cRow+1 );
RenderObject *cell = row->firstChild();
while ( cell ) {
if ( cell->isTableCell() )
addCell( static_cast<RenderTableCell *>(cell) );
cell = cell->nextSibling();
}
row = row->nextSibling();
}
needCellRecalc = false;
setNeedsLayout(true);
}
void RenderTableSection::clearGrid()
{
int rows = gridRows;
while ( rows-- ) {
delete grid[rows].row;
}
}
RenderObject* RenderTableSection::removeChildNode(RenderObject* child)
{
setNeedCellRecalc();
return RenderContainer::removeChildNode( child );
}
#ifndef NDEBUG
void RenderTableSection::dump(QTextStream *stream, QString ind) const
{
*stream << endl << ind << "grid=(" << grid.size() << "," << table()->numEffCols() << ")" << endl << ind;
for ( unsigned int r = 0; r < grid.size(); r++ ) {
for ( int c = 0; c < table()->numEffCols(); c++ ) {
if ( cellAt( r, c ) && cellAt( r, c ) != (RenderTableCell *)-1 )
*stream << "(" << cellAt( r, c )->row() << "," << cellAt( r, c )->col() << ","
<< cellAt(r, c)->rowSpan() << "," << cellAt(r, c)->colSpan() << ") ";
else
*stream << cellAt( r, c ) << "null cell ";
}
*stream << endl << ind;
}
RenderContainer::dump(stream,ind);
}
#endif
// -------------------------------------------------------------------------
RenderTableRow::RenderTableRow(DOM::NodeImpl* node)
: RenderContainer(node)
{
// init RenderObject attributes
setInline(false); // our object is not Inline
}
void RenderTableRow::detach()
{
RenderTableSection *s = section();
if (s) {
s->setNeedCellRecalc();
}
RenderContainer::detach();
}
void RenderTableRow::setStyle(RenderStyle* style)
{
style->setDisplay(TABLE_ROW);
RenderContainer::setStyle(style);
}
void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild)
{
#ifdef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -