📄 render_table.cpp
字号:
FindSelectionResult RenderTable::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state ){ int off = offset; DOM::NodeImpl* nod = node; FindSelectionResult pos; TableSectionIterator it(this); for (; *it; ++it) { pos = (*it)->checkSelectionPoint(_x, _y, _tx + m_x, _ty + m_y, nod, off, state); switch(pos) { case SelectionPointBeforeInLine: case SelectionPointInside: //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " returning SelectionPointInside offset=" << offset << endl; node = nod; offset = off; return SelectionPointInside; case SelectionPointBefore: //x,y is before this element -> stop here if ( state.m_lastNode ) { node = state.m_lastNode; offset = state.m_lastOffset; //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " before this child " // << node << "-> returning SelectionPointInside, offset=" << offset << endl; return SelectionPointInside; } else { node = nod; offset = off; //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " before us -> returning SelectionPointBefore " << node << "/" << offset << endl; return SelectionPointBefore; } break; case SelectionPointAfter: if (state.m_afterInLine) break; // fall through case SelectionPointAfterInLine: if (pos == SelectionPointAfterInLine) state.m_afterInLine = true; //kdDebug(6030) << "RenderTable::checkSelectionPoint: selection after: " << nod << " offset: " << off << " afterInLine: " << state.m_afterInLine << endl; state.m_lastNode = nod; state.m_lastOffset = off; // No "return" here, obviously. We must keep looking into the children. break; } } // If we are after the last child, return lastNode/lastOffset // But lastNode can be 0L if there is no child, for instance. if ( state.m_lastNode ) { node = state.m_lastNode; offset = state.m_lastOffset; } // Fallback return SelectionPointAfter;}// --------------------------------------------------------------------------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 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.isRelative() ) 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.isRelative() && height.value() >= 0) ) { Length cRowHeight = grid[cRow].height; switch( height.type() ) { case Percent: if ( !cRowHeight.isPercent() || (cRowHeight.isPercent() && cRowHeight.value() < height.value() ) ) grid[cRow].height = height; break; case Fixed: if ( cRowHeight.type() < Percent || ( cRowHeight.isFixed() && 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()->borderHSpacing();#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 ); } } }}short RenderTableSection::width() const{ return table()->width();}void RenderTableSection::calcRowHeight(){ int indx; RenderTableCell *cell; int totalRows = grid.size(); int vspacing = table()->borderVSpacing(); rowPos.resize( totalRows + 1 ); rowPos[0] = vspacing + borderTop(); 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 + vspacing; if ( pos > rowPos[r+1] ) rowPos[r+1] = pos; Row *row = grid[r].row; int totalCols = row->size(); int totalRows = grid.size(); bool pagedMode = canvas()->pagedMode(); grid[r].needFlex = false; 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->cellPercentageHeight() != -1) { cell->setCellPercentageHeight(-1); cell->setChildNeedsLayout(true, false); if (cell->hasFlexedAnonymous()) { for (RenderObject* o = cell->firstChild(); o ; o = o->nextSibling()) if (o->isAnonymousBlock()) o->setChildNeedsLayout(true, false); } if (pagedMode) cell->setNeedsLayout(true); cell->layoutIfNeeded(); } ch = cell->style()->height().width(0); if ( cell->height() > ch) ch = cell->height(); if (!cell->style()->height().isVariable()) grid[r].needFlex = true; pos = rowPos[ indx ] + ch + vspacing; 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 > cell->borderTop() + cell->paddingTop()) { 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 + vspacing ; // + 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()->borderHSpacing(); int vspacing = table()->borderVSpacing(); if (markedForRepaint()) { repaintDuringLayout(); setMarkedForRepaint(false); } if (toAdd && totalRows && (rowPos[totalRows] || !nextSibling())) { int totalHeight = rowPos[totalRows] + toAdd;// qDebug("layoutRows: totalHeight = %d", totalHeight );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -