Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutTable.cpp

Issue 2890543002: Improve LayoutTable outer collapsed border calculation (Closed)
Patch Set: - Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutTable.h ('k') | third_party/WebKit/Source/core/layout/LayoutTableCell.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698