📄 render_table.cpp
字号:
#ifndef NDEBUGvoid 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) : RenderBox(node){ // init RenderObject attributes setInline(false); // our object is not Inline 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(); RenderBox::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); RenderBox::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 = grid.size(); int nCols = table()->numEffCols(); if ( numRows > nRows ) { grid.resize( numRows ); 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 = grid.size(); 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 = grid.size(); 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 = grid.size(); 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->getCellPercentageHeight()) { cell->setCellPercentageHeight(0); 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 = grid.size(); 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]; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -