diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderTableCell.cpp')
| -rw-r--r-- | Source/WebCore/rendering/RenderTableCell.cpp | 190 |
1 files changed, 124 insertions, 66 deletions
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp index 3c0e3e3bd..55ac553dd 100644 --- a/Source/WebCore/rendering/RenderTableCell.cpp +++ b/Source/WebCore/rendering/RenderTableCell.cpp @@ -36,20 +36,35 @@ #include "StyleInheritedData.h" #include "TransformState.h" +#if ENABLE(MATHML) +#include "MathMLElement.h" +#include "MathMLNames.h" +#endif + using namespace std; namespace WebCore { using namespace HTMLNames; +struct SameSizeAsRenderTableCell : public RenderBlock { + unsigned bitfields; + int paddings[2]; +}; + +COMPILE_ASSERT(sizeof(RenderTableCell) == sizeof(SameSizeAsRenderTableCell), RenderTableCell_should_stay_small); +COMPILE_ASSERT(sizeof(CollapsedBorderValue) == 8, CollapsedBorderValue_should_stay_small); + RenderTableCell::RenderTableCell(Node* node) : RenderBlock(node) , m_column(unsetColumnIndex) , m_cellWidthChanged(false) - , m_hasAssociatedTableCellElement(node && (node->hasTagName(tdTag) || node->hasTagName(thTag))) , m_intrinsicPaddingBefore(0) , m_intrinsicPaddingAfter(0) { + // We only update the flags when notified of DOM changes in colSpanOrRowSpanChanged() + // so we need to set their initial values here in case something asks for colSpan()/rowSpan() before then. + updateColAndRowSpanFlags(); } void RenderTableCell::willBeRemovedFromTree() @@ -60,90 +75,86 @@ void RenderTableCell::willBeRemovedFromTree() section()->removeCachedCollapsedBorders(this); } -unsigned RenderTableCell::colSpan() const +unsigned RenderTableCell::parseColSpanFromDOM() const { - if (UNLIKELY(!m_hasAssociatedTableCellElement)) - return 1; - - return toHTMLTableCellElement(node())->colSpan(); + ASSERT(node()); + if (node()->hasTagName(tdTag) || node()->hasTagName(thTag)) + return toHTMLTableCellElement(node())->colSpan(); +#if ENABLE(MATHML) + if (node()->hasTagName(MathMLNames::mtdTag)) + return toMathMLElement(node())->colSpan(); +#endif + return 1; } -unsigned RenderTableCell::rowSpan() const +unsigned RenderTableCell::parseRowSpanFromDOM() const { - if (UNLIKELY(!m_hasAssociatedTableCellElement)) - return 1; + ASSERT(node()); + if (node()->hasTagName(tdTag) || node()->hasTagName(thTag)) + return toHTMLTableCellElement(node())->rowSpan(); +#if ENABLE(MATHML) + if (node()->hasTagName(MathMLNames::mtdTag)) + return toMathMLElement(node())->rowSpan(); +#endif + return 1; +} - return toHTMLTableCellElement(node())->rowSpan(); +void RenderTableCell::updateColAndRowSpanFlags() +{ + // The vast majority of table cells do not have a colspan or rowspan, + // so we keep a bool to know if we need to bother reading from the DOM. + m_hasColSpan = node() && parseColSpanFromDOM() != 1; + m_hasRowSpan = node() && parseRowSpanFromDOM() != 1; } void RenderTableCell::colSpanOrRowSpanChanged() { - ASSERT(m_hasAssociatedTableCellElement); ASSERT(node()); +#if ENABLE(MATHML) + ASSERT(node()->hasTagName(tdTag) || node()->hasTagName(thTag) || node()->hasTagName(MathMLNames::mtdTag)); +#else ASSERT(node()->hasTagName(tdTag) || node()->hasTagName(thTag)); +#endif + + updateColAndRowSpanFlags(); + + // FIXME: I suspect that we could return early here if !m_hasColSpan && !m_hasRowSpan. setNeedsLayoutAndPrefWidthsRecalc(); if (parent() && section()) section()->setNeedsCellRecalc(); } -LayoutUnit RenderTableCell::logicalHeightForRowSizing() const -{ - LayoutUnit adjustedLogicalHeight = logicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter()); - - LayoutUnit styleLogicalHeight = valueForLength(style()->logicalHeight(), 0, view()); - if (document()->inQuirksMode() || style()->boxSizing() == BORDER_BOX) { - // Explicit heights use the border box in quirks mode. - // Don't adjust height. - } else { - // In strict mode, box-sizing: content-box do the right - // thing and actually add in the border and padding. - LayoutUnit adjustedPaddingBefore = paddingBefore() - intrinsicPaddingBefore(); - LayoutUnit adjustedPaddingAfter = paddingAfter() - intrinsicPaddingAfter(); - styleLogicalHeight += adjustedPaddingBefore + adjustedPaddingAfter + borderBefore() + borderAfter(); - } - - return max(styleLogicalHeight, adjustedLogicalHeight); -} - -Length RenderTableCell::styleOrColLogicalWidth() const +Length RenderTableCell::logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const { - Length w = style()->logicalWidth(); - if (!w.isAuto()) - return w; - - if (RenderTableCol* tableCol = table()->colElement(col())) { - unsigned colSpanCount = colSpan(); - - Length colWidthSum = Length(0, Fixed); - for (unsigned i = 1; i <= colSpanCount; i++) { - Length colWidth = tableCol->style()->logicalWidth(); - - // Percentage value should be returned only for colSpan == 1. - // Otherwise we return original width for the cell. - if (!colWidth.isFixed()) { - if (colSpanCount > 1) - return w; - return colWidth; - } + ASSERT(firstColForThisCell && firstColForThisCell == table()->colElement(col())); + RenderTableCol* tableCol = firstColForThisCell; - colWidthSum = Length(colWidthSum.value() + colWidth.value(), Fixed); + unsigned colSpanCount = colSpan(); + int colWidthSum = 0; + for (unsigned i = 1; i <= colSpanCount; i++) { + Length colWidth = tableCol->style()->logicalWidth(); - tableCol = tableCol->nextColumn(); - // If no next <col> tag found for the span we just return what we have for now. - if (!tableCol) - break; + // Percentage value should be returned only for colSpan == 1. + // Otherwise we return original width for the cell. + if (!colWidth.isFixed()) { + if (colSpanCount > 1) + return widthFromStyle; + return colWidth; } - // Column widths specified on <col> apply to the border box of the cell. - // Percentages don't need to be handled since they're always treated this way (even when specified on the cells). - // See Bugzilla bug 8126 for details. - if (colWidthSum.isFixed() && colWidthSum.value() > 0) - colWidthSum = Length(max(0.0f, colWidthSum.value() - borderAndPaddingLogicalWidth()), Fixed); - return colWidthSum; + colWidthSum += colWidth.value(); + tableCol = tableCol->nextColumn(); + // If no next <col> tag found for the span we just return what we have for now. + if (!tableCol) + break; } - return w; + // Column widths specified on <col> apply to the border box of the cell, see bug 8126. + // FIXME: Why is border/padding ignored in the negative width case? + if (colWidthSum > 0) + return Length(max(0, colWidthSum - borderAndPaddingLogicalWidth().ceil()), Fixed); + return Length(colWidthSum, Fixed); } void RenderTableCell::computePreferredLogicalWidths() @@ -168,16 +179,63 @@ void RenderTableCell::computePreferredLogicalWidths() } } +void RenderTableCell::computeIntrinsicPadding(int rowHeight) +{ + int oldIntrinsicPaddingBefore = intrinsicPaddingBefore(); + int oldIntrinsicPaddingAfter = intrinsicPaddingAfter(); + int logicalHeightWithoutIntrinsicPadding = pixelSnappedLogicalHeight() - oldIntrinsicPaddingBefore - oldIntrinsicPaddingAfter; + + int intrinsicPaddingBefore = 0; + switch (style()->verticalAlign()) { + case SUB: + case SUPER: + case TEXT_TOP: + case TEXT_BOTTOM: + case LENGTH: + case BASELINE: { + LayoutUnit baseline = cellBaselinePosition(); + if (baseline > borderBefore() + paddingBefore()) + intrinsicPaddingBefore = section()->rowBaseline(rowIndex()) - (baseline - oldIntrinsicPaddingBefore); + break; + } + case TOP: + break; + case MIDDLE: + intrinsicPaddingBefore = (rowHeight - logicalHeightWithoutIntrinsicPadding) / 2; + break; + case BOTTOM: + intrinsicPaddingBefore = rowHeight - logicalHeightWithoutIntrinsicPadding; + break; + case BASELINE_MIDDLE: + break; + } + + int intrinsicPaddingAfter = rowHeight - logicalHeightWithoutIntrinsicPadding - intrinsicPaddingBefore; + setIntrinsicPaddingBefore(intrinsicPaddingBefore); + setIntrinsicPaddingAfter(intrinsicPaddingAfter); + + // FIXME: Changing an intrinsic padding shouldn't trigger a relayout as it only shifts the cell inside the row but + // doesn't change the logical height. + if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter) + setNeedsLayout(true, MarkOnlyThis); +} + void RenderTableCell::updateLogicalWidth() { } -void RenderTableCell::setCellLogicalWidth(LayoutUnit w) +void RenderTableCell::setCellLogicalWidth(int tableLayoutLogicalWidth) { - if (w == logicalWidth()) + if (tableLayoutLogicalWidth == logicalWidth()) return; - setLogicalWidth(w); + setNeedsLayout(true, MarkOnlyThis); + row()->setChildNeedsLayout(true, MarkOnlyThis); + + if (!table()->selfNeedsLayout() && checkForRepaintDuringLayout()) + repaint(); + + setLogicalWidth(tableLayoutLogicalWidth); setCellWidthChanged(true); } @@ -247,7 +305,7 @@ LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoi return offset; } -LayoutRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const +LayoutRect RenderTableCell::clippedOverflowRectForRepaint(RenderLayerModelObject* repaintContainer) const { // If the table grid is dirty, we cannot get reliable information about adjoining cells, // so we ignore outside borders. This should not be a problem because it means that @@ -298,7 +356,7 @@ LayoutRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* return r; } -void RenderTableCell::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& r, bool fixed) const +void RenderTableCell::computeRectForRepaint(RenderLayerModelObject* repaintContainer, LayoutRect& r, bool fixed) const { if (repaintContainer == this) return; |
