summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderTable.cpp')
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp115
1 files changed, 82 insertions, 33 deletions
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 7d5cfe94f..3249afb8a 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -28,12 +28,12 @@
#include "AutoTableLayout.h"
#include "CollapsedBorderValue.h"
-#include "DeleteButtonController.h"
#include "Document.h"
#include "FixedTableLayout.h"
#include "FrameView.h"
#include "HitTestResult.h"
#include "HTMLNames.h"
+#include "HTMLTableElement.h"
#include "LayoutRepainter.h"
#include "RenderLayer.h"
#include "RenderTableCaption.h"
@@ -42,6 +42,7 @@
#include "RenderTableSection.h"
#include "RenderView.h"
#include "StyleInheritedData.h"
+#include <wtf/StackStats.h>
using namespace std;
@@ -49,8 +50,8 @@ namespace WebCore {
using namespace HTMLNames;
-RenderTable::RenderTable(Node* node)
- : RenderBlock(node)
+RenderTable::RenderTable(Element* element)
+ : RenderBlock(element)
, m_head(0)
, m_foot(0)
, m_firstBody(0)
@@ -113,10 +114,6 @@ static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, Rend
void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
{
- // Make sure we don't append things after :after-generated content if we have it.
- if (!beforeChild)
- beforeChild = afterPseudoElementRenderer();
-
bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
if (child->isTableCaption())
@@ -159,6 +156,9 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
else
wrapInAnonymousSection = true;
+ if (child->isTableSection())
+ setNeedsSectionRecalc();
+
if (!wrapInAnonymousSection) {
if (beforeChild && beforeChild->parent() != this)
beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
@@ -255,7 +255,7 @@ void RenderTable::updateLogicalWidth()
LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
Length styleLogicalWidth = style()->logicalWidth();
- if (styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive())
+ if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic())
setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
else {
// Subtract out any fixed margins from our available width for auto width tables.
@@ -267,7 +267,7 @@ void RenderTable::updateLogicalWidth()
LayoutUnit availableContentLogicalWidth = max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
// FIXME: Work with regions someday.
- availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0, 0);
+ availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0);
}
// Ensure we aren't bigger than our available width.
@@ -280,14 +280,14 @@ void RenderTable::updateLogicalWidth()
// Ensure we aren't bigger than our max-width style.
Length styleMaxLogicalWidth = style()->logicalMaxWidth();
- if (styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) {
+ if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
setLogicalWidth(min<int>(logicalWidth(), computedMaxLogicalWidth));
}
// Ensure we aren't smaller than our min-width style.
Length styleMinLogicalWidth = style()->logicalMinWidth();
- if (styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) {
+ if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
setLogicalWidth(max<int>(logicalWidth(), computedMinLogicalWidth));
}
@@ -298,7 +298,7 @@ void RenderTable::updateLogicalWidth()
if (!hasPerpendicularContainingBlock) {
LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
if (avoidsFloats() && cb->containsFloats())
- containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0, 0); // FIXME: Work with regions someday.
+ containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0); // FIXME: Work with regions someday.
ComputedMarginValues marginValues;
bool hasInvertedDirection = cb->style()->isLeftToRightDirection() == style()->isLeftToRightDirection();
computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth(),
@@ -315,14 +315,15 @@ void RenderTable::updateLogicalWidth()
// This method takes a RenderStyle's logical width, min-width, or max-width length and computes its actual value.
LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
{
+ if (styleLogicalWidth.isIntrinsic())
+ return computeIntrinsicLogicalWidthUsing(styleLogicalWidth, availableWidth, bordersPaddingAndSpacingInRowDirection());
+
// HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
LayoutUnit borders = 0;
- bool isCSSTable = !node() || !node()->hasTagName(tableTag);
- if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) {
- recalcBordersInRowDirection();
- if (style()->boxSizing() == CONTENT_BOX)
- borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
- }
+ bool isCSSTable = !node() || !isHTMLTableElement(node());
+ if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style()->boxSizing() == CONTENT_BOX)
+ borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
+
return minimumValueForLength(styleLogicalWidth, availableWidth, view()) + borders;
}
@@ -333,7 +334,7 @@ LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length&
// HTML tables size as though CSS height includes border/padding, CSS tables do not.
LayoutUnit borders = LayoutUnit();
// FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
- if ((node() && node()->hasTagName(tableTag)) || style()->boxSizing() == BORDER_BOX) {
+ if ((node() && isHTMLTableElement(node())) || style()->boxSizing() == BORDER_BOX) {
LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
borders = borderAndPaddingBefore + borderAndPaddingAfter;
@@ -382,6 +383,14 @@ void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
// ASSERT(!topSection() || !extraLogicalHeight);
}
+void RenderTable::simplifiedNormalFlowLayout()
+{
+ for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
+ section->layoutIfNeeded();
+ section->computeOverflowFromCells();
+ }
+}
+
void RenderTable::layout()
{
StackStats::LayoutCheckPoint layoutCheckPoint;
@@ -391,12 +400,14 @@ void RenderTable::layout()
return;
recalcSectionsIfNeeded();
+ // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
+ // to call this before we call borderStart/borderEnd to avoid getting a stale value.
+ recalcBordersInRowDirection();
LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+ LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
setLogicalHeight(0);
- m_overflow.clear();
initMaxMarginValues();
@@ -643,7 +654,7 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
PaintInfo info(paintInfo);
info.phase = paintPhase;
- info.updatePaintingRootForChildren(this);
+ info.updateSubtreePaintRootForChildren(this);
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
@@ -670,7 +681,7 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// Paint outline.
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
- paintOutline(paintInfo.context, LayoutRect(paintOffset, size()));
+ paintOutline(paintInfo, LayoutRect(paintOffset, size()));
}
void RenderTable::subtractCaptionRect(LayoutRect& rect) const
@@ -698,9 +709,10 @@ void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& p
LayoutRect rect(paintOffset, size());
subtractCaptionRect(rect);
- if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
+ BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
+ if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
paintBoxShadow(paintInfo, rect, style(), Normal);
- paintBackground(paintInfo, rect);
+ paintBackground(paintInfo, rect, bleedAvoidance);
paintBoxShadow(paintInfo, rect, style(), Inset);
if (style()->hasBorder() && !collapseBorders())
@@ -718,18 +730,49 @@ void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset
paintMaskImages(paintInfo, rect);
}
+void RenderTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
+{
+ recalcSectionsIfNeeded();
+ // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast this call.
+ // Then m_borderStart/m_borderEnd will be transparent a cache and it removes the possibility
+ // of reading out stale values.
+ const_cast<RenderTable*>(this)->recalcBordersInRowDirection();
+ // FIXME: Restructure the table layout code so that we can make this method const.
+ const_cast<RenderTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths(minWidth, maxWidth);
+
+ // FIXME: We should include captions widths here like we do in computePreferredLogicalWidths.
+}
+
void RenderTable::computePreferredLogicalWidths()
{
ASSERT(preferredLogicalWidthsDirty());
- recalcSectionsIfNeeded();
- recalcBordersInRowDirection();
+ computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+ int bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
+ m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
+ m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
- m_tableLayout->computePreferredLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+ m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
for (unsigned i = 0; i < m_captions.size(); i++)
m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
+ RenderStyle* styleToUse = style();
+ // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
+ if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+ m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+ }
+
+ // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
+ if (styleToUse->logicalMaxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+ m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+ }
+
+ // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
+ // so a bunch of tests break doing this naively.
setPreferredLogicalWidthsDirty(false);
}
@@ -762,7 +805,6 @@ void RenderTable::splitColumn(unsigned position, unsigned firstSpan)
}
m_columnPos.grow(numEffCols() + 1);
- setNeedsLayoutAndPrefWidthsRecalc();
}
void RenderTable::appendColumn(unsigned span)
@@ -784,7 +826,6 @@ void RenderTable::appendColumn(unsigned span)
}
m_columnPos.grow(numEffCols() + 1);
- setNeedsLayoutAndPrefWidthsRecalc();
}
RenderTableCol* RenderTable::firstColumn() const
@@ -1314,9 +1355,16 @@ int RenderTable::firstLineBoxBaseline() const
return -1;
}
-LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy, PaintPhase phase)
{
- LayoutRect rect = RenderBlock::overflowClipRect(location, region, relevancy);
+ LayoutRect rect;
+ // Don't clip out the table's side of the collapsed borders if we're in the paint phase that will ask the sections to paint them.
+ // Likewise, if we're self-painting we avoid clipping them out as the clip rect that will be passed down to child layers from RenderLayer will do that instead.
+ if (phase == PaintPhaseChildBlockBackgrounds || layer()->isSelfPaintingLayer()) {
+ rect = borderBoxRectInRegion(region);
+ rect.setLocation(location + rect.location());
+ } else
+ rect = RenderBox::overflowClipRect(location, region, relevancy);
// If we have a caption, expand the clip to include the caption.
// FIXME: Technically this is wrong, but it's virtually impossible to fix this
@@ -1368,7 +1416,8 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
{
RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE);
- RenderTable* newTable = new (parent->renderArena()) RenderTable(parent->document() /* is anonymous */);
+ RenderTable* newTable = new (parent->renderArena()) RenderTable(0);
+ newTable->setDocumentForAnonymous(parent->document());
newTable->setStyle(newStyle.release());
return newTable;
}