📄 render_table.cpp
字号:
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) { // 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, e.g., textareas to grow to // fill the area. FIXME: <div>s and blocks still don't // work right. We'll need to have an efficient way of // invalidating all percent height objects in a render subtree. // For now, we just handle immediate children. -dwh bool cellChildrenFlex = false; RenderObject* o = cell->firstChild(); while (o) { if (!o->isText() && o->style()->height().isPercent()) { o->setNeedsLayout(true, false); cell->setChildNeedsLayout(true, false); cellChildrenFlex = true; } o = o->nextSibling(); } if (cellChildrenFlex) { cell->setCellPercentageHeight(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){ unsigned int totalRows = grid.size(); unsigned int totalCols = table()->columns.size(); tx += m_x; ty += m_y; // 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); } } }}void RenderTableSection::recalcCells(){ cCol = 0; cRow = -1; clearGrid(); grid.resize( 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 = grid.size(); while ( rows-- ) { delete grid[rows].row; }}RenderObject* RenderTableSection::removeChildNode(RenderObject* child){ setNeedCellRecalc(); return RenderContainer::removeChildNode( child );}#ifndef NDEBUGvoid 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 kdDebug( 6040 ) << renderName() << "(TableRow)::addChild( " << child->renderName() << " )" << ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;#endif if (child->element() && child->element()->id() == ID_FORM) { RenderContainer::addChild(child,beforeChild); return; } RenderTableCell *cell; if ( !child->isTableCell() ) { RenderObject *last = beforeChild; if ( !last ) last = lastChild(); RenderTableCell *cell = 0; if( last && last->isAnonymous() && last->isTableCell() ) cell = static_cast<RenderTableCell *>(last); else { cell = new (renderArena()) RenderTableCell(document() /* anonymous object */); RenderStyle *newStyle = new (renderArena()) RenderStyle(); newStyle->inheritFrom(style()); newStyle->setDisplay( TABLE_CELL ); cell->setStyle(newStyle); addChild(cell, beforeChild); } cell->addChild(child); child->setNeedsLayoutAndMinMaxRecalc(); return; } else cell = static_cast<RenderTableCell *>(child); static_cast<RenderTableSection *>(parent())->addCell( cell ); RenderContainer::addChild(cell,beforeChild); if ( ( beforeChild || nextSibling()) && section() ) section()->setNeedCellRecalc();}RenderObject* RenderTableRow::removeChildNode(RenderObject* child){// RenderTableCell detach should do it// if ( section() )// section()->setNeedCellRecalc(); return RenderContainer::removeChildNode( child );}#ifndef NDEBUGvoid RenderTableRow::dump(QTextStream *stream, QString ind) const{ RenderContainer::dump(stream,ind);}#endifvoid RenderTableRow::layout(){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); RenderObject *child = firstChild(); while( child ) { if (child->isTableCell()) { RenderTableCell *cell = static_cast<RenderTableCell *>(child); if (child->needsLayout()) { cell->calcVerticalMargins(); cell->layout(); cell->setCellTopExtra(0); cell->setCellBottomExtra(0); } } child = child->nextSibling(); } setNeedsLayout(false);}QRect RenderTableRow::getAbsoluteRepaintRect(){ // For now, just repaint the whole table. // FIXME: Find a better way to do this. RenderTable* parentTable = table(); if (parentTable) return parentTable->getAbsoluteRepaintRect(); else return QRect();}// -------------------------------------------------------------------------RenderTableCell::RenderTableCell(DOM::NodeImpl* _node) : RenderBlock(_node){ _col = -1; _row = -1; updateFromElement(); setShouldPaintBackgroundOrBorder(true); _topExtra = 0; _bottomExtra = 0; m_percentageHeight = 0;}void RenderTableCell::detach(){ if (parent() && section()) section()->setNeedCellRecalc(); RenderBlock::detach();}void RenderTableCell::updateFromElement(){ DOM::NodeImpl *node = element(); if ( node && (node->id() == ID_TD || node->id() == ID_TH) ) { DOM::HTMLTableCellElementImpl *tc = static_cast<DOM::HTMLTableCellElementImpl *>(node); cSpan = tc->colSpan(); rSpan = tc->rowSpan(); } else { cSpan = rSpan = 1; }}int RenderTableCell::getCellPercentageHeight() const{ return m_percentageHeight;}void RenderTableCell::setCellPercentageHeight(int h){ m_percentageHeight = h;} void RenderTableCell::calcMinMaxWidth()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -