⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render_table.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        int dh = toAdd;	int totalPercent = 0;	int numVariable = 0;	for ( int r = 0; r < totalRows; r++ ) {            if ( grid[r].height.isVariable() && !emptyRow(r))		numVariable++;	    else if ( grid[r].height.isPercent() )		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.isPercent() ) {		    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 = kMax(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 non-empty variable rows//	    qDebug("distributing %d over variable rows numVariable=%d", dh,  numVariable );	    int add = 0;            int toAdd = dh/numVariable;            for ( int r = 0; r < totalRows; r++ ) {                if ( grid[r].height.isVariable() && !emptyRow(r)) {		    add += toAdd;		}                rowPos[r+1] += add;	    }            dh -= add;        }        if (dh>0 && rowPos[totalRows]) {	    // if some left overs, distribute weighted.            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;            }            dh -= add;        }        if (dh > totalRows) {            // distribute to tables with all empty rows            int add=0;            int toAdd = dh/totalRows;            for ( int r = 0; r < totalRows; r++ ) {                add += toAdd;                rowPos[r+1] += add;            }            dh -= add;        }        // Finally distribute round-off values        if (dh > 0) {            // There is not enough for every row            int add=0;            for ( int r = 0; r < totalRows; r++ ) {                if (add < dh) add++;                rowPos[r+1] += add;            }            dh -= add;        }        assert (dh == 0);    }    int leftOffset = borderLeft() + 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 flexAllChildren = grid[r].needFlex || (!table()->style()->height().isVariable() && rHeight != cell->height());            cell->setHasFlexedAnonymous(false);            if ( flexAllChildren && flexCellChildren(cell) ) {                cell->setCellPercentageHeight(kMax(0,                                                   rHeight - cell->borderTop() - cell->paddingTop() -                                                   cell->borderBottom() - cell->paddingBottom()));                cell->layoutIfNeeded();            }            {#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;		}		te = kMax( 0, te );#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);	    }            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] );	    }        }    }    m_height = rowPos[totalRows];    return m_height;}bool RenderTableSection::flexCellChildren(RenderObject* p) const{    if (!p)         return false;    RenderObject* o = p->firstChild();    bool didFlex = false;    while (o) {        if (!o->isText() && o->style()->height().isPercent()) {            if (o->isWidget()) {                // cancel resizes from transitory relayouts                static_cast<RenderWidget *>(o)->cancelPendingResize();            }            o->setNeedsLayout(true, false);            p->setChildNeedsLayout(true, false);            didFlex = true;        } else if (o->isAnonymousBlock() && flexCellChildren( o )) {            p->setChildNeedsLayout(true, false);            if (p->isTableCell())                static_cast<RenderTableCell*>(p)->setHasFlexedAnonymous();            didFlex = true;        }        o = o->nextSibling();    }    return didFlex;}inline static RenderTableRow *firstTableRow(RenderObject *row){    while (row && !row->isTableRow())        row = row->nextSibling();    return static_cast<RenderTableRow *>(row);}inline static RenderTableRow *nextTableRow(RenderObject *row){    row = row ? row->nextSibling() : row;    while (row && !row->isTableRow())        row = row->nextSibling();    return static_cast<RenderTableRow *>(row);}void RenderTableSection::paint( PaintInfo& pI, int tx, int ty ){    unsigned int totalRows = grid.size();    unsigned int totalCols = table()->columns.size();    tx += m_x;    ty += m_y;    if (pI.phase == PaintActionOutline)        paintOutline(pI.p, tx, ty, width(), height(), style());    CollapsedBorderValue *cbs = table()->currentBorderStyle();    int cbsw2 = cbs ? cbs->width()/2 : 0;    int cbsw21 = cbs ? (cbs->width()+1)/2 : 0;    RenderTableRow *trow = firstTableRow(firstChild());    int x = pI.r.x(), y = pI.r.y(), w = pI.r.width(), h = pI.r.height();    // check which rows and cols are visible and only paint these    // ### fixme: could use a binary search here    int os = 2*maximalOutlineSize(pI.phase);    unsigned int startrow = 0;    unsigned int endrow = totalRows;    for ( ; startrow < totalRows; startrow++, trow = nextTableRow(trow) ) {	if ( ty + rowPos[startrow+1] + kMax(cbsw21, os) > y - os )	    break;    }    for ( ; endrow > 0; endrow-- ) {	if ( ty + rowPos[endrow-1] - kMax(cbsw2, os) < 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] + kMax(cbsw21, os) > x - os )		break;	}	for ( ; endcol > 0; endcol-- ) {	    if ( tx + table()->columnPos[endcol-1] - kMax(cbsw2, os) < x + w + os )		break;	}    }    if ( startcol < endcol ) {	// draw the cells	for ( unsigned int r = startrow; r < endrow; r++, trow = nextTableRow(trow) ) {	    // paint the row	    if (trow) {	        int height = rowPos[r+1] - rowPos[r] - table()->borderVSpacing();	        trow->paintRow(pI, tx, ty + rowPos[r], width(), height);	    }	    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;		if ( (r < endrow - 1) && (cellAt(r+1, c) == cell) )		    continue;#ifdef TABLE_PRINT		kdDebug( 6040 ) << "painting cell " << r << "/" << c << endl;#endif		cell->paint( pI, 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;    }}bool RenderTableSection::emptyRow(int rowNum) {    Row &r = *grid[rowNum].row;    const int s = r.size();    RenderTableCell *cell;    for(int i=0; i<s; i++) {        cell = r[i];        if (!cell || cell==(RenderTableCell*)-1)            continue;        return false;    }    return true;}RenderObject* RenderTableSection::removeChildNode(RenderObject* child){    setNeedCellRecalc();    return RenderContainer::removeChildNode( child );}bool RenderTableSection::canClear(RenderObject */*child*/, PageBreakLevel level){    // We cannot clear rows yet.    return parent()->canClear(this, level);}void RenderTableSection::addSpaceAt(int pos, int dy){    const int nEffCols = table()->numEffCols();    const int totalRows = numRows();    for ( int r = 0; r < totalRows; r++ ) {        if (rowPos[r] >= pos) {            rowPos[r] += dy;            Row *row = grid[r].row;            int totalCols = row->size();            int rindx;            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;                cell->setPos(cell->xPos(), rowPos[r]);            }        }    }    if (rowPos[totalRows] >= pos)        rowPos[totalRows] += dy;    m_height = rowPos[totalRows];    setContainsPageBreak(true);}#ifdef ENABLE_DUMPvoid RenderTableSection::dump(QTextStream &stream, const QString &ind) const{    RenderContainer::dump(stream,ind);    stream << " grid=(" << grid.size() << "," << table()->numEffCols() << ")";    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 << " null cell";	}    }}#endifstatic RenderTableCell *seekCell(RenderTableSection *section, int row, int col){    if (row < 0 || col < 0 || row >= section->numRows()) return 0;    // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it    while ( col && section->cellAt( row, col ) == (RenderTableCell *)-1 )	col--;    return section->cellAt(row, col);}/** Looks for the first element suitable for text selection, beginning from * the last. * @param base search is restricted within this node. This node must have *	a renderer. * @return the element or @p base if no suitable element found. */static NodeImpl *findLastSelectableNode(NodeImpl *base){  NodeImpl *last = base;  // Look for last text/cdata node that has a renderer,  // or last childless replaced element  while ( last && !(last->renderer()  	&& ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)		|| (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))  {    NodeImpl *next = last->lastChild();    if ( !next ) next = last->previousSibling();    while ( last && last != base && !next )    {      last = last->parentNode();      if ( last && last != base )        next = last->previousSibling();    }    last = next;  }  return last ? last : base;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -