📄 table_layout.cpp
字号:
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(); w.l.value = kMin( 32767, kMax( 0, w.value() ) ); switch( w.type() ) { case Fixed: // ignore width=0 if ( w.value() > 0 && !l.width.isPercent() ) { // ### we should use box'es paddings here I guess. int wval = w.value() + cell->paddingLeft() + cell->paddingRight(); if ( l.width.isFixed() ) { // Nav/IE weirdness if ((wval > l.width.value()) || ((l.width.value() == wval) && (maxContributor == cell))) { l.width.l.value = wval; fixedContributor = cell; } } else { l.width = Length( wval, Fixed ); fixedContributor = cell; } } break; case Percent: hasPercent = true; if ( w.value() > 0 && (!l.width.isPercent() || w.value() > l.width.value() ) ) l.width = w; break; case Relative: if ( w.isVariable() || (w.isRelative() && 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 = kMax(int( l.minWidth ), 1); l.maxWidth = kMax(int( l.maxWidth ), 1); insertSpanCell( cell ); } last = cell; } } } child = child->nextSibling(); } // Nav/IE weirdness if ( l.width.isFixed() ) { if ( table->style()->htmlHacks() && (l.maxWidth > l.width.value()) && (fixedContributor != maxContributor)) { l.width = Length(); fixedContributor = 0; } } l.maxWidth = kMax(l.maxWidth, int(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.isFixed() && w.value() == 0) || (w.isPercent() && 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 ( !w.isVariable() && 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.isPercent() ) { 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 = kMin(maxWidth, 0x7fff); table->m_minWidth = kMin(minWidth, 0x7fff);#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->borderHSpacing();#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.isRelative() && 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 behavior anyway. mozilla doesn't do this so I decided we don't either. 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.isPercent()) { 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.isPercent() ) { if ( totalPercent > w.value() || allColsArePercent ) { // can't satify this condition, treat as variable w = Length(); } else { int spanMax = kMax( maxWidth, cMaxWidth );#ifdef DEBUG_LAYOUT qDebug(" adjusting tMaxWidth (%d): spanMax=%d, value=%d, totalPercent=%d", tMaxWidth, spanMax, w.value(), totalPercent );#endif tMaxWidth = kMax( tMaxWidth, spanMax * 100 / w.value() ); // all non percent columns in the span get percent values to sum up correctly. int percentMissing = w.value() - totalPercent; int totalWidth = 0; for ( unsigned int pos = col; pos < lastCol; pos++ ) { if ( !(layoutStruct[pos].width.isPercent() ) ) totalWidth += layoutStruct[pos].effMaxWidth; } for ( unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++ ) { if ( !(layoutStruct[pos].width.isPercent() ) ) { 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 = kMax( int( 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 if ( allColsArePercent ) { int maxw = maxWidth; int minw = minWidth; int cminw = cMinWidth; for ( unsigned int pos = col; maxw > 0 && pos < lastCol; pos++ ) { if ( layoutStruct[pos].effWidth.isPercent() && layoutStruct[pos].effWidth.value()>0 && fixedWidth <= cMinWidth) { int w = layoutStruct[pos].effMinWidth; w = kMax( w, cminw*layoutStruct[pos].effWidth.value()/totalPercent ); w = kMin(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 maxw -= layoutStruct[pos].effMaxWidth; minw -= layoutStruct[pos].effMinWidth; 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.isFixed() && haveVariable && fixedWidth <= cMinWidth ) { int w = kMax( int( 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -