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

📄 table_layout.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		    if ( cell->maxWidth() > l.maxWidth ) {
			l.maxWidth = cell->maxWidth();
			maxContributor = cell;
		    }

		    Length w = cell->style()->width();
		    if ( w.value > 32760 )
			w.value = 32760;
		    if ( w.value < 0 )
			w.value = 0;
		    switch( w.type ) {
		    case Fixed:
			// ignore width=0
			if ( w.value > 0 && (int)l.width.type != Percent ) {
                            int wval = w.value + (cell->paddingLeft()+cell->paddingRight());
			    if ( l.width.type == Fixed ) {
                                // Nav/IE weirdness
				if ((wval > l.width.value) ||
				    ((l.width.value == wval) && (maxContributor == cell))) {
				    l.width.value = wval;
				    fixedContributor = cell;
				}
			    } else {
                                l.width.type = Fixed;
				l.width.value = wval;
				fixedContributor = cell;
			    }
			}
			break;
		    case Percent:
                        hasPercent = true;
                        if ( w.value > 0 && (l.width.type != Percent || w.value > l.width.value ) )
                            l.width = w;
			break;
		    case Relative:
			if ( w.type == Variable || (w.type == Relative && w.value > l.width.value ) )
				l.width = w;
		    default:
			break;
		    }
		} else {
                    if ( cell && (!effCol || section->cellAt( i, effCol-1 ) != cell) ) {
                        // This spanning cell originates in this column.  Ensure we have
                        // a min/max width of at least 1px for this column now.
                        l.minWidth = QMAX(l.minWidth, 1);
                        l.maxWidth = QMAX(l.maxWidth, 1);
			insertSpanCell( cell );
                    }
		    last = cell;
		}
	    }
	}
	child = child->nextSibling();
    }

    // Nav/IE weirdness
    if ( l.width.type == Fixed ) {
	if ( table->style()->htmlHacks()
	     && (l.maxWidth > l.width.value) && (fixedContributor != maxContributor)) {
	    l.width = Length();
	    fixedContributor = 0;
	}
    }

    l.maxWidth = kMax(l.maxWidth, l.minWidth);
#ifdef DEBUG_LAYOUT
    qDebug("col %d, final min=%d, max=%d, width=%d(%d)", effCol, l.minWidth, l.maxWidth, l.width.value,  l.width.type );
#endif

    // ### we need to add col elements aswell
}


void AutoTableLayout::fullRecalc()
{
    percentagesDirty = true;
    hasPercent = false;
    effWidthDirty = true;

    int nEffCols = table->numEffCols();
    layoutStruct.resize( nEffCols );
    layoutStruct.fill( Layout() );
    spanCells.fill( 0 );

    RenderObject *child = table->firstChild();
    Length grpWidth;
    int cCol = 0;
    while ( child ) {
	if ( child->isTableCol() ) {
	    RenderTableCol *col = static_cast<RenderTableCol *>(child);
	    int span = col->span();
	    if ( col->firstChild() ) {
		grpWidth = col->style()->width();
	    } else {
		Length w = col->style()->width();
		if ( w.isVariable() )
		    w = grpWidth;
		if ( (w.type == Fixed && w.value == 0) ||
		     (w.type == Percent && w.value == 0) )
		    w = Length();
		int cEffCol = table->colToEffCol( cCol );
#ifdef DEBUG_LAYOUT
		qDebug("    col element %d (eff=%d): Length=%d(%d), span=%d, effColSpan=%d",  cCol, cEffCol, w.value, w.type, span, table->spanOfEffCol(cEffCol ) );
#endif
		if ( (int)w.type != Variable && span == 1 && cEffCol < nEffCols ) {
		    if ( table->spanOfEffCol( cEffCol ) == 1 ) {
			layoutStruct[cEffCol].width = w;
                        if (w.isFixed() && layoutStruct[cEffCol].maxWidth < w.value)
                            layoutStruct[cEffCol].maxWidth = w.value;
                    }
		}
		cCol += span;
	    }
	} else {
	    break;
	}

	RenderObject *next = child->firstChild();
	if ( !next )
	    next = child->nextSibling();
	if ( !next && child->parent()->isTableCol() ) {
	    next = child->parent()->nextSibling();
	    grpWidth = Length();
	}
	child = next;
    }


    for ( int i = 0; i < nEffCols; i++ )
	recalcColumn( i );
}

static bool shouldScaleColumns(RenderTable* table)
{
    // A special case.  If this table is not fixed width and contained inside
    // a cell, then don't bloat the maxwidth by examining percentage growth.
    bool scale = true;
    while (table) {
        Length tw = table->style()->width();
        if ((tw.isVariable() || tw.isPercent()) && !table->isPositioned()) {
            RenderBlock* cb = table->containingBlock();
            while (cb && !cb->isCanvas() && !cb->isTableCell() &&
                cb->style()->width().isVariable() && !cb->isPositioned())
                cb = cb->containingBlock();

            table = 0;
            if (cb && cb->isTableCell() &&
                (cb->style()->width().isVariable() || cb->style()->width().isPercent())) {
                if (tw.isPercent())
                    scale = false;
                else {
                    RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
                    if (cell->colSpan() > 1 || cell->table()->style()->width().isVariable())
                        scale = false;
                    else
                        table = cell->table();
                }
            }
        }
        else
            table = 0;
    }
    return scale;
}

void AutoTableLayout::calcMinMaxWidth()
{
#ifdef DEBUG_LAYOUT
    qDebug("AutoTableLayout::calcMinMaxWidth");
#endif
    fullRecalc();

    int spanMaxWidth = calcEffectiveWidth();
    int minWidth = 0;
    int maxWidth = 0;
    int maxPercent = 0;
    int maxNonPercent = 0;

    int remainingPercent = 100;
    for ( unsigned int i = 0; i < layoutStruct.size(); i++ ) {
	minWidth += layoutStruct[i].effMinWidth;
	maxWidth += layoutStruct[i].effMaxWidth;
	if ( layoutStruct[i].effWidth.type == Percent ) {
            int percent = kMin(layoutStruct[i].effWidth.value, remainingPercent);
            int pw = ( layoutStruct[i].effMaxWidth * 100) / kMax(percent, 1);
            remainingPercent -= percent;
            maxPercent = kMax( pw,  maxPercent );
	} else {
	    maxNonPercent += layoutStruct[i].effMaxWidth;
	}
    }

    if (shouldScaleColumns(table)) {
        maxNonPercent = (maxNonPercent * 100 + 50) / kMax(remainingPercent, 1);
        maxWidth = kMax( maxNonPercent,  maxWidth );
        maxWidth = kMax( maxWidth, maxPercent );
    }

    maxWidth = kMax( maxWidth, spanMaxWidth );
    
    int bs = table->bordersPaddingAndSpacing();
    minWidth += bs;
    maxWidth += bs;

    Length tw = table->style()->width();
    if ( tw.isFixed() && tw.value > 0 ) {
	minWidth = kMax( minWidth, int( tw.value ) );
	maxWidth = minWidth;
    }

    table->m_maxWidth = maxWidth;
    table->m_minWidth = minWidth;
#ifdef DEBUG_LAYOUT
    qDebug("    minWidth=%d, maxWidth=%d", table->m_minWidth, table->m_maxWidth );
#endif
}

/*
  This method takes care of colspans.
  effWidth is the same as width for cells without colspans. If we have colspans, they get modified.
 */
int AutoTableLayout::calcEffectiveWidth()
{
    int tMaxWidth = 0;

    unsigned int nEffCols = layoutStruct.size();
    int hspacing = table->hBorderSpacing();
#ifdef DEBUG_LAYOUT
    qDebug("AutoTableLayout::calcEffectiveWidth for %d cols", nEffCols );
#endif
    for ( unsigned int i = 0; i < nEffCols; i++ ) {
	layoutStruct[i].effWidth = layoutStruct[i].width;
	layoutStruct[i].effMinWidth = layoutStruct[i].minWidth;
	layoutStruct[i].effMaxWidth = layoutStruct[i].maxWidth;
    }

    for ( unsigned int i = 0; i < spanCells.size(); i++ ) {
	RenderTableCell *cell = spanCells[i];
	if ( !cell || cell == (RenderTableCell *)-1 )
	    break;
	int span = cell->colSpan();

	Length w = cell->style()->width();
	if ( !(w.type == Relative) && w.value == 0 )
	    w = Length(); // make it Variable

	int col = table->colToEffCol( cell->col() );
	unsigned int lastCol = col;
	int cMinWidth = cell->minWidth() + hspacing;
	int cMaxWidth = cell->maxWidth() + hspacing;
	int totalPercent = 0;
	int minWidth = 0;
	int maxWidth = 0;
	bool allColsArePercent = true;
	bool allColsAreFixed = true;
	bool haveVariable = false;
	int fixedWidth = 0;
#ifdef DEBUG_LAYOUT
	int cSpan = span;
#endif
	while ( lastCol < nEffCols && span > 0 ) {
	    switch( layoutStruct[lastCol].width.type ) {
	    case Percent:
		totalPercent += layoutStruct[lastCol].width.value;
		allColsAreFixed = false;
		break;
	    case Fixed:
                if (layoutStruct[lastCol].width.value > 0) {
                    fixedWidth += layoutStruct[lastCol].width.value;
                    allColsArePercent = false;
                    // IE resets effWidth to Variable here, but this breaks the konqueror about page and seems to be some bad
                    // legacy behaviour anyway. mozilla doesn't do this so I decided we don't neither.
                    break;
                }
                // fall through
	    case Variable:
		haveVariable = true;
		// fall through
	    default:
                // If the column is a percentage width, do not let the spanning cell overwrite the
                // width value.  This caused a mis-rendering on amazon.com.
                // Sample snippet:
                // <table border=2 width=100%><
                //   <tr><td>1</td><td colspan=2>2-3</tr>
                //   <tr><td>1</td><td colspan=2 width=100%>2-3</td></tr>
                // </table>
                if (layoutStruct[lastCol].effWidth.type != Percent) {
                    layoutStruct[lastCol].effWidth = Length();
                    allColsArePercent = false;
                }
                else
                    totalPercent += layoutStruct[lastCol].effWidth.value;
		allColsAreFixed = false;
	    }
	    span -= table->spanOfEffCol( lastCol );
	    minWidth += layoutStruct[lastCol].effMinWidth;
	    maxWidth += layoutStruct[lastCol].effMaxWidth;
	    lastCol++;
	    cMinWidth -= hspacing;
	    cMaxWidth -= hspacing;
	}
#ifdef DEBUG_LAYOUT
	qDebug("    colspan cell %p at effCol %d, span %d, type %d, value %d cmin=%d min=%d fixedwidth=%d", cell, col, cSpan, w.type, w.value, cMinWidth, minWidth, fixedWidth );
#endif

	// adjust table max width if needed
	if ( w.type == Percent ) {
	    if ( totalPercent > w.value || allColsArePercent ) {
		// can't satify this condition, treat as variable
		w = Length();
	    } else {
		int spanMax = QMAX( maxWidth, cMaxWidth );
#ifdef DEBUG_LAYOUT
		qDebug("    adjusting tMaxWidth (%d): spanMax=%d, value=%d, totalPercent=%d", tMaxWidth, spanMax, w.value, totalPercent );
#endif
		tMaxWidth = QMAX( tMaxWidth, spanMax * 100 / w.value );

		// all non percent columns in the span get percent vlaues to sum up correctly.
		int percentMissing = w.value - totalPercent;
		int totalWidth = 0;
		for ( unsigned int pos = col; pos < lastCol; pos++ ) {
		    if ( !(layoutStruct[pos].width.type == Percent ) )
			totalWidth += layoutStruct[pos].effMaxWidth;
		}

		for ( unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++ ) {
		    if ( !(layoutStruct[pos].width.type == Percent ) ) {
			int percent = percentMissing * layoutStruct[pos].effMaxWidth / totalWidth;
#ifdef DEBUG_LAYOUT
			qDebug("   col %d: setting percent value %d effMaxWidth=%d totalWidth=%d", pos, percent, layoutStruct[pos].effMaxWidth, totalWidth );
#endif
			totalWidth -= layoutStruct[pos].effMaxWidth;
			percentMissing -= percent;
			if ( percent > 0 )
		            layoutStruct[pos].effWidth = Length( percent, Percent );
			else
			    layoutStruct[pos].effWidth = Length();
		    }
		}

	    }
	}

	// make sure minWidth and maxWidth of the spanning cell are honoured
	if ( cMinWidth > minWidth ) {
            if ( allColsAreFixed ) {
#ifdef DEBUG_LAYOUT
		qDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d accroding to fixed sum %d", col, lastCol-1, cMinWidth, minWidth, fixedWidth );
#endif
		for ( unsigned int pos = col; fixedWidth > 0 && pos < lastCol; pos++ ) {
		    int w = QMAX( layoutStruct[pos].effMinWidth, cMinWidth * layoutStruct[pos].width.value / fixedWidth );
#ifdef DEBUG_LAYOUT
		    qDebug("   col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
#endif
		    fixedWidth -= layoutStruct[pos].width.value;
		    cMinWidth -= w;
                    layoutStruct[pos].effMinWidth = w;
		}

	    } else {
#ifdef DEBUG_LAYOUT
		qDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d", col, lastCol-1, cMinWidth, minWidth );
#endif
		int maxw = maxWidth;
                int minw = minWidth;
                
                // Give min to variable first, to fixed second, and to others third.
                for ( unsigned int pos = col; maxw > 0 && pos < lastCol; pos++ ) {
		    if ( layoutStruct[pos].width.type == Fixed && haveVariable && fixedWidth <= cMinWidth ) {
			int w = QMAX( layoutStruct[pos].effMinWidth, layoutStruct[pos].width.value );
			fixedWidth -= layoutStruct[pos].width.value;
                        minw -= layoutStruct[pos].effMinWidth;
#ifdef DEBUG_LAYOUT
                        qDebug("   col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
#endif
                        maxw -= layoutStruct[pos].effMaxWidth;
                        cMinWidth -= w;
                        layoutStruct[pos].effMinWidth = w;
                    }
		}

                for ( unsigned int pos = col; maxw > 0 && pos < lastCol && minw < cMinWidth; pos++ ) {
		    if ( !(layoutStruct[pos].width.type == Fixed && haveVariable && fixedWidth <= cMinWidth) ) {
                        int w = QMAX( layoutStruct[pos].effMinWidth, cMinWidth * layoutStruct[pos].effMaxWidth / maxw );
                        w = QMIN(layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
                                                
#ifdef DEBUG_LAYOUT
                        qDebug("   col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
#endif

⌨️ 快捷键说明

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