📄 autotablelayout.cpp
字号:
int percent = min(m_layoutStruct[i].effWidth.rawValue(), remainingPercent); float pw = static_cast<float>(m_layoutStruct[i].effMaxWidth) * 100 * percentScaleFactor / max(percent, epsilon); maxPercent = max(pw, maxPercent); remainingPercent -= percent; } else maxNonPercent += m_layoutStruct[i].effMaxWidth; } } if (scaleColumns) { maxNonPercent = maxNonPercent * 100 * percentScaleFactor / max(remainingPercent, epsilon); maxWidth = max(maxWidth, static_cast<int>(min(maxNonPercent, INT_MAX / 2.0f))); maxWidth = max(maxWidth, static_cast<int>(min(maxPercent, INT_MAX / 2.0f))); } maxWidth = max(maxWidth, spanMaxWidth); int bs = m_table->bordersPaddingAndSpacing(); minWidth += bs; maxWidth += bs; Length tw = m_table->style()->width(); if (tw.isFixed() && tw.value() > 0) { minWidth = max(minWidth, tw.value()); maxWidth = minWidth; }}/* 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(){ float tMaxWidth = 0; unsigned int nEffCols = m_layoutStruct.size(); int hspacing = m_table->hBorderSpacing(); for (unsigned int i = 0; i < nEffCols; i++) { m_layoutStruct[i].effWidth = m_layoutStruct[i].width; m_layoutStruct[i].effMinWidth = m_layoutStruct[i].minWidth; m_layoutStruct[i].effMaxWidth = m_layoutStruct[i].maxWidth; } for (unsigned int i = 0; i < m_spanCells.size(); i++) { RenderTableCell *cell = m_spanCells[i]; if (!cell) break; int span = cell->colSpan(); Length w = cell->styleOrColWidth(); if (!w.isRelative() && w.isZero()) w = Length(); // make it Auto int col = m_table->colToEffCol(cell->col()); unsigned int lastCol = col; int cMinWidth = cell->minPrefWidth() + hspacing; float cMaxWidth = cell->maxPrefWidth() + hspacing; int totalPercent = 0; int minWidth = 0; float maxWidth = 0; bool allColsArePercent = true; bool allColsAreFixed = true; bool haveAuto = false; bool spanHasEmptyCellsOnly = true; int fixedWidth = 0; while (lastCol < nEffCols && span > 0) { switch (m_layoutStruct[lastCol].width.type()) { case Percent: totalPercent += m_layoutStruct[lastCol].width.rawValue(); allColsAreFixed = false; break; case Fixed: if (m_layoutStruct[lastCol].width.value() > 0) { fixedWidth += m_layoutStruct[lastCol].width.value(); allColsArePercent = false; // IE resets effWidth to Auto 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 Auto: haveAuto = 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 (!m_layoutStruct[lastCol].effWidth.isPercent()) { m_layoutStruct[lastCol].effWidth = Length(); allColsArePercent = false; } else totalPercent += m_layoutStruct[lastCol].effWidth.rawValue(); allColsAreFixed = false; } if (!m_layoutStruct[lastCol].emptyCellsOnly) spanHasEmptyCellsOnly = false; span -= m_table->spanOfEffCol(lastCol); minWidth += m_layoutStruct[lastCol].effMinWidth; maxWidth += m_layoutStruct[lastCol].effMaxWidth; lastCol++; cMinWidth -= hspacing; cMaxWidth -= hspacing; } // adjust table max width if needed if (w.isPercent()) { if (totalPercent > w.rawValue() || allColsArePercent) { // can't satify this condition, treat as variable w = Length(); } else { float spanMax = max(maxWidth, cMaxWidth); tMaxWidth = max(tMaxWidth, spanMax * 100 * percentScaleFactor / w.rawValue()); // all non percent columns in the span get percent vlaues to sum up correctly. int percentMissing = w.rawValue() - totalPercent; float totalWidth = 0; for (unsigned int pos = col; pos < lastCol; pos++) { if (!(m_layoutStruct[pos].effWidth.isPercent())) totalWidth += m_layoutStruct[pos].effMaxWidth; } for (unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++) { if (!(m_layoutStruct[pos].effWidth.isPercent())) { int percent = static_cast<int>(percentMissing * static_cast<float>(m_layoutStruct[pos].effMaxWidth) / totalWidth); totalWidth -= m_layoutStruct[pos].effMaxWidth; percentMissing -= percent; if (percent > 0) m_layoutStruct[pos].effWidth.setRawValue(Percent, percent); else m_layoutStruct[pos].effWidth = Length(); } } } } // make sure minWidth and maxWidth of the spanning cell are honoured if (cMinWidth > minWidth) { if (allColsAreFixed) { for (unsigned int pos = col; fixedWidth > 0 && pos < lastCol; pos++) { int w = max(m_layoutStruct[pos].effMinWidth, cMinWidth * m_layoutStruct[pos].width.value() / fixedWidth); fixedWidth -= m_layoutStruct[pos].width.value(); cMinWidth -= w; m_layoutStruct[pos].effMinWidth = w; } } else { float 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 (m_layoutStruct[pos].width.isFixed() && haveAuto && fixedWidth <= cMinWidth) { int w = max(m_layoutStruct[pos].effMinWidth, m_layoutStruct[pos].width.value()); fixedWidth -= m_layoutStruct[pos].width.value(); minw -= m_layoutStruct[pos].effMinWidth; maxw -= m_layoutStruct[pos].effMaxWidth; cMinWidth -= w; m_layoutStruct[pos].effMinWidth = w; } } for (unsigned int pos = col; maxw >= 0 && pos < lastCol && minw < cMinWidth; pos++) { if (!(m_layoutStruct[pos].width.isFixed() && haveAuto && fixedWidth <= cMinWidth)) { int w = max(m_layoutStruct[pos].effMinWidth, static_cast<int>(maxw ? cMinWidth * static_cast<float>(m_layoutStruct[pos].effMaxWidth) / maxw : cMinWidth)); w = min(m_layoutStruct[pos].effMinWidth+(cMinWidth-minw), w); maxw -= m_layoutStruct[pos].effMaxWidth; minw -= m_layoutStruct[pos].effMinWidth; cMinWidth -= w; m_layoutStruct[pos].effMinWidth = w; } } } } if (!(w.isPercent())) { if (cMaxWidth > maxWidth) { for (unsigned int pos = col; maxWidth >= 0 && pos < lastCol; pos++) { int w = max(m_layoutStruct[pos].effMaxWidth, static_cast<int>(maxWidth ? cMaxWidth * static_cast<float>(m_layoutStruct[pos].effMaxWidth) / maxWidth : cMaxWidth)); maxWidth -= m_layoutStruct[pos].effMaxWidth; cMaxWidth -= w; m_layoutStruct[pos].effMaxWidth = w; } } } else { for (unsigned int pos = col; pos < lastCol; pos++) m_layoutStruct[pos].maxWidth = max(m_layoutStruct[pos].maxWidth, m_layoutStruct[pos].minWidth); } // treat span ranges consisting of empty cells only as if they had content if (spanHasEmptyCellsOnly) for (unsigned int pos = col; pos < lastCol; pos++) m_layoutStruct[pos].emptyCellsOnly = false; } m_effWidthDirty = false; return static_cast<int>(min(tMaxWidth, INT_MAX / 2.0f));}/* gets all cells that originate in a column and have a cellspan > 1 Sorts them by increasing cellspan*/void AutoTableLayout::insertSpanCell(RenderTableCell *cell){ if (!cell || cell->colSpan() == 1) return; int size = m_spanCells.size(); if (!size || m_spanCells[size-1] != 0) { m_spanCells.grow(size + 10); for (int i = 0; i < 10; i++) m_spanCells[size+i] = 0; size += 10; } // add them in sort. This is a slow algorithm, and a binary search or a fast sorting after collection would be better unsigned int pos = 0; int span = cell->colSpan(); while (pos < m_spanCells.size() && m_spanCells[pos] && span > m_spanCells[pos]->colSpan()) pos++; memmove(m_spanCells.data()+pos+1, m_spanCells.data()+pos, (size-pos-1)*sizeof(RenderTableCell *)); m_spanCells[pos] = cell;}void AutoTableLayout::layout(){ // table layout based on the values collected in the layout structure. int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing(); int available = tableWidth; int nEffCols = m_table->numEffCols(); if (nEffCols != (int)m_layoutStruct.size()) { fullRecalc(); nEffCols = m_table->numEffCols(); } if (m_effWidthDirty) calcEffectiveWidth(); bool havePercent = false; bool haveRelative = false; int totalRelative = 0; int numAuto = 0; int numFixed = 0; float totalAuto = 0; float totalFixed = 0; int totalPercent = 0; int allocAuto = 0; int numAutoEmptyCellsOnly = 0; // fill up every cell with its minWidth for (int i = 0; i < nEffCols; i++) { int w = m_layoutStruct[i].effMinWidth; m_layoutStruct[i].calcWidth = w; available -= w;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -