📄 table_layout.cpp
字号:
if ( cell == (RenderTableCell *)-1 ) continue; if ( cell && cell->colSpan() == 1 ) { // A 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); if ( !cell->minMaxKnown() ) cell->calcMinMaxWidth(); if ( cell->minWidth() > l.minWidth ) l.minWidth = cell->minWidth(); 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) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -