| 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
|
|
|