Index: third_party/WebKit/Source/core/layout/LayoutTable.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp |
index fe4bbbd9b5e7851b43a5d386697b4adbc4fd6ef8..f9d48407819b4fbdd4ae4813bed653a9818bee67 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp |
@@ -58,6 +58,7 @@ LayoutTable::LayoutTable(Element* element) |
first_body_(nullptr), |
collapsed_borders_valid_(false), |
needs_invalidate_collapsed_borders_for_all_cells_(false), |
+ collapsed_outer_borders_valid_(false), |
has_col_elements_(false), |
needs_section_recalc_(false), |
column_logical_width_changed_(false), |
@@ -65,8 +66,10 @@ LayoutTable::LayoutTable(Element* element) |
no_cell_colspan_at_least_(0), |
h_spacing_(0), |
v_spacing_(0), |
- border_start_(0), |
- border_end_(0) { |
+ collapsed_outer_border_start_(0), |
+ collapsed_outer_border_end_(0), |
+ collapsed_outer_border_before_(0), |
+ collapsed_outer_border_after_(0) { |
DCHECK(!ChildrenInline()); |
effective_column_positions_.Fill(0, 1); |
} |
@@ -580,10 +583,6 @@ void LayoutTable::UpdateLayout() { |
TextAutosizer::LayoutScope text_autosizer_layout_scope(this); |
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(); |
SubtreeLayoutScope layouter(*this); |
@@ -624,13 +623,6 @@ void LayoutTable::UpdateLayout() { |
LayoutUnit table_box_logical_top = LogicalHeight(); |
bool collapsing = ShouldCollapseBorders(); |
- if (collapsing) { |
- // Need to set up the table borders before we can position the sections. |
- for (LayoutTableSection* section = top_section; section; |
- section = SectionBelow(section)) |
- section->RecalcOuterBorder(); |
- } |
- |
LayoutUnit border_and_padding_before = |
BorderBefore() + (collapsing ? LayoutUnit() : PaddingBefore()); |
LayoutUnit border_and_padding_after = |
@@ -780,6 +772,7 @@ void LayoutTable::InvalidateCollapsedBorders() { |
collapsed_borders_.clear(); |
collapsed_borders_valid_ = false; |
needs_invalidate_collapsed_borders_for_all_cells_ = true; |
+ collapsed_outer_borders_valid_ = false; |
SetMayNeedPaintInvalidation(); |
} |
@@ -831,6 +824,7 @@ void LayoutTable::RecalcCollapsedBordersIfNeeded() { |
} |
void LayoutTable::AddOverflowFromChildren() { |
+ /* |
// Add overflow from borders. |
// Technically it's odd that we are incorporating the borders into layout |
// overflow, which is only supposed to be about overflow from our |
@@ -838,11 +832,11 @@ void LayoutTable::AddOverflowFromChildren() { |
// works out fine. |
if (ShouldCollapseBorders()) { |
LayoutUnit right_border_overflow = |
- Size().Width() + OuterBorderRight() - BorderRight(); |
- LayoutUnit left_border_overflow = BorderLeft() - OuterBorderLeft(); |
+ Size().Width() + CollapsedOuterBorderRight() - BorderRight(); |
+ LayoutUnit left_border_overflow = BorderLeft() - CollapsedOuterBorderLeft(); |
LayoutUnit bottom_border_overflow = |
- Size().Height() + OuterBorderBottom() - BorderBottom(); |
- LayoutUnit top_border_overflow = BorderTop() - OuterBorderTop(); |
+ Size().Height() + CollapsedOuterBorderBottom() - BorderBottom(); |
+ LayoutUnit top_border_overflow = BorderTop() - CollapsedOuterBorderTop(); |
IntRect border_overflow_rect( |
left_border_overflow.ToInt(), top_border_overflow.ToInt(), |
(right_border_overflow - left_border_overflow).ToInt(), |
@@ -852,7 +846,8 @@ void LayoutTable::AddOverflowFromChildren() { |
AddLayoutOverflow(border_layout_rect); |
AddContentsVisualOverflow(border_layout_rect); |
} |
- } |
+ }*/ |
+ // TODO: Add a test. |
// Add overflow from our caption. |
for (unsigned i = 0; i < captions_.size(); i++) |
@@ -914,11 +909,6 @@ void LayoutTable::PaintMask(const PaintInfo& paint_info, |
void LayoutTable::ComputeIntrinsicLogicalWidths(LayoutUnit& min_width, |
LayoutUnit& max_width) 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<LayoutTable*>(this)->RecalcBordersInRowDirection(); |
// FIXME: Restructure the table layout code so that we can make this method |
// const. |
const_cast<LayoutTable*>(this)->table_layout_->ComputeIntrinsicLogicalWidths( |
@@ -987,6 +977,13 @@ LayoutTableSection* LayoutTable::TopNonEmptySection() const { |
return section; |
} |
+LayoutTableSection* LayoutTable::BottomNonEmptySection() const { |
+ LayoutTableSection* section = BottomSection(); |
+ if (section && !section->NumRows()) |
+ section = SectionAbove(section, kSkipEmptySections); |
+ return section; |
+} |
+ |
void LayoutTable::SplitEffectiveColumn(unsigned index, unsigned first_span) { |
// We split the column at |index|, taking |firstSpan| cells from the span. |
DCHECK_GT(effective_columns_[index].span, first_span); |
@@ -1178,254 +1175,36 @@ void LayoutTable::RecalcSections() const { |
needs_section_recalc_ = false; |
} |
-int LayoutTable::CalcBorderStart() const { |
- if (!ShouldCollapseBorders()) |
- return LayoutBlock::BorderStart().ToInt(); |
- |
- // Determined by the first cell of the first row. See the CSS 2.1 spec, |
- // section 17.6.2. |
- if (!NumEffectiveColumns()) |
- return 0; |
- |
- int border_width = 0; |
- |
- const BorderValue& table_start_border = Style()->BorderStart(); |
- if (table_start_border.Style() == kBorderStyleHidden) |
- return 0; |
- if (table_start_border.Style() > kBorderStyleHidden) |
- border_width = table_start_border.Width(); |
- |
- // TODO(dgrogan): This logic doesn't properly account for the first column in |
- // the first column-group case. |
- if (LayoutTableCol* column = |
- ColElementAtEffectiveColumn(0).InnermostColOrColGroup()) { |
- // FIXME: We don't account for direction on columns and column groups. |
- const BorderValue& column_adjoining_border = column->Style()->BorderStart(); |
- if (column_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- if (column_adjoining_border.Style() > kBorderStyleHidden) |
- border_width = |
- std::max<int>(border_width, column_adjoining_border.Width()); |
- } |
- |
- if (const LayoutTableSection* top_non_empty_section = |
- this->TopNonEmptySection()) { |
- const BorderValue& section_adjoining_border = |
- top_non_empty_section->BorderAdjoiningTableStart(); |
- if (section_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- |
- if (section_adjoining_border.Style() > kBorderStyleHidden) |
- border_width = |
- std::max<int>(border_width, section_adjoining_border.Width()); |
- |
- if (const LayoutTableCell* adjoining_start_cell = |
- top_non_empty_section->FirstRowCellAdjoiningTableStart()) { |
- // FIXME: Make this work with perpendicular and flipped cells. |
- const BorderValue& start_cell_adjoining_border = |
- adjoining_start_cell->BorderAdjoiningTableStart(); |
- if (start_cell_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- |
- const BorderValue& first_row_adjoining_border = |
- adjoining_start_cell->Row()->BorderAdjoiningTableStart(); |
- if (first_row_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- |
- if (start_cell_adjoining_border.Style() > kBorderStyleHidden) { |
- border_width = |
- std::max<int>(border_width, start_cell_adjoining_border.Width()); |
- } |
- if (first_row_adjoining_border.Style() > kBorderStyleHidden) { |
- border_width = |
- std::max<int>(border_width, first_row_adjoining_border.Width()); |
- } |
- } |
- } |
- return (border_width + (Style()->IsLeftToRightDirection() ? 0 : 1)) / 2; |
-} |
- |
-int LayoutTable::CalcBorderEnd() const { |
- if (!ShouldCollapseBorders()) |
- return LayoutBlock::BorderEnd().ToInt(); |
- |
- // Determined by the last cell of the first row. See the CSS 2.1 spec, section |
- // 17.6.2. |
- if (!NumEffectiveColumns()) |
- return 0; |
- |
- int border_width = 0; |
- |
- const BorderValue& table_end_border = Style()->BorderEnd(); |
- if (table_end_border.Style() == kBorderStyleHidden) |
- return 0; |
- if (table_end_border.Style() > kBorderStyleHidden) |
- border_width = table_end_border.Width(); |
- |
- unsigned end_column = NumEffectiveColumns() - 1; |
- |
- // TODO(dgrogan): This logic doesn't properly account for the last column in |
- // the last column-group case. |
- if (LayoutTableCol* column = |
- ColElementAtEffectiveColumn(end_column).InnermostColOrColGroup()) { |
- // FIXME: We don't account for direction on columns and column groups. |
- const BorderValue& column_adjoining_border = column->Style()->BorderEnd(); |
- if (column_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- if (column_adjoining_border.Style() > kBorderStyleHidden) |
- border_width = |
- std::max<int>(border_width, column_adjoining_border.Width()); |
- } |
- |
- if (const LayoutTableSection* top_non_empty_section = |
- this->TopNonEmptySection()) { |
- const BorderValue& section_adjoining_border = |
- top_non_empty_section->BorderAdjoiningTableEnd(); |
- if (section_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- |
- if (section_adjoining_border.Style() > kBorderStyleHidden) |
- border_width = |
- std::max<int>(border_width, section_adjoining_border.Width()); |
- |
- if (const LayoutTableCell* adjoining_end_cell = |
- top_non_empty_section->FirstRowCellAdjoiningTableEnd()) { |
- // FIXME: Make this work with perpendicular and flipped cells. |
- const BorderValue& end_cell_adjoining_border = |
- adjoining_end_cell->BorderAdjoiningTableEnd(); |
- if (end_cell_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- |
- const BorderValue& first_row_adjoining_border = |
- adjoining_end_cell->Row()->BorderAdjoiningTableEnd(); |
- if (first_row_adjoining_border.Style() == kBorderStyleHidden) |
- return 0; |
- |
- if (end_cell_adjoining_border.Style() > kBorderStyleHidden) { |
- border_width = |
- std::max<int>(border_width, end_cell_adjoining_border.Width()); |
- } |
- if (first_row_adjoining_border.Style() > kBorderStyleHidden) { |
- border_width = |
- std::max<int>(border_width, first_row_adjoining_border.Width()); |
- } |
- } |
- } |
- return (border_width + (Style()->IsLeftToRightDirection() ? 1 : 0)) / 2; |
-} |
- |
-void LayoutTable::RecalcBordersInRowDirection() { |
- // FIXME: We need to compute the collapsed before / after borders in the same |
- // fashion. |
- border_start_ = CalcBorderStart(); |
- border_end_ = CalcBorderEnd(); |
-} |
- |
LayoutUnit LayoutTable::BorderBefore() const { |
if (ShouldCollapseBorders()) { |
- RecalcSectionsIfNeeded(); |
- return LayoutUnit(OuterBorderBefore()); |
+ UpdateCollapsedOuterBorders(); |
+ return LayoutUnit(collapsed_outer_border_before_); |
} |
return LayoutBlock::BorderBefore(); |
} |
LayoutUnit LayoutTable::BorderAfter() const { |
if (ShouldCollapseBorders()) { |
- RecalcSectionsIfNeeded(); |
- return LayoutUnit(OuterBorderAfter()); |
+ UpdateCollapsedOuterBorders(); |
+ return LayoutUnit(collapsed_outer_border_after_); |
} |
return LayoutBlock::BorderAfter(); |
} |
-int LayoutTable::OuterBorderBefore() const { |
- if (!ShouldCollapseBorders()) |
- return 0; |
- int border_width = 0; |
- if (LayoutTableSection* top_section = this->TopSection()) { |
- border_width = top_section->OuterBorderBefore(); |
- if (border_width < 0) |
- return 0; // Overridden by hidden |
- } |
- const BorderValue& tb = Style()->BorderBefore(); |
- if (tb.Style() == kBorderStyleHidden) |
- return 0; |
- if (tb.Style() > kBorderStyleHidden) |
- border_width = std::max<int>(border_width, tb.Width() / 2); |
- return border_width; |
-} |
- |
-int LayoutTable::OuterBorderAfter() const { |
- if (!ShouldCollapseBorders()) |
- return 0; |
- int border_width = 0; |
- |
- if (LayoutTableSection* section = BottomSection()) { |
- border_width = section->OuterBorderAfter(); |
- if (border_width < 0) |
- return 0; // Overridden by hidden |
- } |
- const BorderValue& tb = Style()->BorderAfter(); |
- if (tb.Style() == kBorderStyleHidden) |
- return 0; |
- if (tb.Style() > kBorderStyleHidden) |
- border_width = std::max<int>(border_width, (tb.Width() + 1) / 2); |
- return border_width; |
-} |
- |
-int LayoutTable::OuterBorderStart() const { |
- if (!ShouldCollapseBorders()) |
- return 0; |
- |
- int border_width = 0; |
- |
- const BorderValue& tb = Style()->BorderStart(); |
- if (tb.Style() == kBorderStyleHidden) |
- return 0; |
- if (tb.Style() > kBorderStyleHidden) |
- border_width = |
- (tb.Width() + (Style()->IsLeftToRightDirection() ? 0 : 1)) / 2; |
- |
- bool all_hidden = true; |
- for (LayoutTableSection* section = TopSection(); section; |
- section = SectionBelow(section)) { |
- int sw = section->OuterBorderStart(); |
- if (sw < 0) |
- continue; |
- all_hidden = false; |
- border_width = std::max(border_width, sw); |
+LayoutUnit LayoutTable::BorderStart() const { |
+ if (ShouldCollapseBorders()) { |
+ UpdateCollapsedOuterBorders(); |
+ return LayoutUnit(collapsed_outer_border_start_); |
} |
- if (all_hidden) |
- return 0; |
- |
- return border_width; |
+ return LayoutBlock::BorderStart(); |
} |
-int LayoutTable::OuterBorderEnd() const { |
- if (!ShouldCollapseBorders()) |
- return 0; |
- |
- int border_width = 0; |
- |
- const BorderValue& tb = Style()->BorderEnd(); |
- if (tb.Style() == kBorderStyleHidden) |
- return 0; |
- if (tb.Style() > kBorderStyleHidden) |
- border_width = |
- (tb.Width() + (Style()->IsLeftToRightDirection() ? 1 : 0)) / 2; |
- |
- bool all_hidden = true; |
- for (LayoutTableSection* section = TopSection(); section; |
- section = SectionBelow(section)) { |
- int sw = section->OuterBorderEnd(); |
- if (sw < 0) |
- continue; |
- all_hidden = false; |
- border_width = std::max(border_width, sw); |
+LayoutUnit LayoutTable::BorderEnd() const { |
+ if (ShouldCollapseBorders()) { |
+ UpdateCollapsedOuterBorders(); |
+ return LayoutUnit(collapsed_outer_border_end_); |
} |
- if (all_hidden) |
- return 0; |
- |
- return border_width; |
+ return LayoutBlock::BorderEnd(); |
} |
LayoutTableSection* LayoutTable::SectionAbove( |
@@ -1757,4 +1536,82 @@ LayoutUnit LayoutTable::PaddingRight() const { |
return LayoutBlock::PaddingRight(); |
} |
+unsigned LayoutTable::ComputeCollapsedOuterBorderBefore() const { |
+ DCHECK(ShouldCollapseBorders()); |
+ |
+ const auto* section = TopNonEmptySection(); |
+ if (!section) |
+ return 0; |
+ |
+ unsigned n_cols = section->NumEffectiveColumns(0); |
+ unsigned result = 0; |
+ for (unsigned col = 0; col < n_cols; ++col) { |
+ if (const auto* cell = section->PrimaryCellAt(0, col)) |
+ result = std::max(result, cell->CollapsedOuterBorderBefore()); |
+ } |
+ return result; |
+} |
+ |
+unsigned LayoutTable::ComputeCollapsedOuterBorderAfter() const { |
+ DCHECK(ShouldCollapseBorders()); |
+ |
+ const auto* section = BottomNonEmptySection(); |
+ if (!section) |
+ return 0; |
+ |
+ unsigned row = section->NumRows() - 1; |
+ unsigned n_cols = section->NumEffectiveColumns(row); |
+ unsigned result = 0; |
+ for (unsigned col = 0; col < n_cols; ++col) { |
+ if (const auto* cell = section->PrimaryCellAt(row, col)) |
+ result = std::max(result, cell->CollapsedOuterBorderAfter()); |
+ } |
+ return result; |
+} |
+ |
+unsigned LayoutTable::ComputeCollapsedOuterBorderStart() const { |
+ DCHECK(ShouldCollapseBorders()); |
+ |
+ unsigned result = 0; |
+ for (const auto* section = TopNonEmptySection(); section; |
+ section = SectionBelow(section, kSkipEmptySections)) { |
+ for (unsigned row = 0; row < section->NumRows(); ++row) { |
+ if (const auto* cell = section->PrimaryCellAt(row, 0)) |
+ result = std::max(result, cell->CollapsedOuterBorderStart()); |
+ } |
+ } |
+ return result; |
+} |
+ |
+unsigned LayoutTable::ComputeCollapsedOuterBorderEnd() const { |
+ DCHECK(ShouldCollapseBorders()); |
+ |
+ unsigned n_cols = NumEffectiveColumns(); |
+ if (!n_cols) |
+ return 0; |
+ |
+ unsigned result = 0; |
+ for (const auto* section = TopNonEmptySection(); section; |
+ section = SectionBelow(section, kSkipEmptySections)) { |
+ for (unsigned row = 0; row < section->NumRows(); ++row) { |
+ if (const auto* cell = section->PrimaryCellAt(row, n_cols - 1)) |
+ result = std::max(result, cell->CollapsedOuterBorderEnd()); |
+ } |
+ } |
+ return result; |
+} |
+ |
+void LayoutTable::UpdateCollapsedOuterBorders() const { |
+ if (collapsed_outer_borders_valid_) |
+ return; |
+ |
+ collapsed_outer_borders_valid_ = true; |
+ if (ShouldCollapseBorders()) { |
+ collapsed_outer_border_before_ = ComputeCollapsedOuterBorderBefore(); |
+ collapsed_outer_border_after_ = ComputeCollapsedOuterBorderAfter(); |
+ collapsed_outer_border_start_ = ComputeCollapsedOuterBorderStart(); |
+ collapsed_outer_border_end_ = ComputeCollapsedOuterBorderEnd(); |
+ } |
+} |
+ |
} // namespace blink |