| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) |
| 3 * (C) 1997 Torben Weis (weis@kde.org) | 3 * (C) 1997 Torben Weis (weis@kde.org) |
| 4 * (C) 1998 Waldo Bastian (bastian@kde.org) | 4 * (C) 1998 Waldo Bastian (bastian@kde.org) |
| 5 * (C) 1999 Lars Knoll (knoll@kde.org) | 5 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. |
| 8 * All rights reserved. | 8 * All rights reserved. |
| 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 10 * | 10 * |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 using namespace HTMLNames; | 52 using namespace HTMLNames; |
| 53 | 53 |
| 54 LayoutTable::LayoutTable(Element* element) | 54 LayoutTable::LayoutTable(Element* element) |
| 55 : LayoutBlock(element), | 55 : LayoutBlock(element), |
| 56 head_(nullptr), | 56 head_(nullptr), |
| 57 foot_(nullptr), | 57 foot_(nullptr), |
| 58 first_body_(nullptr), | 58 first_body_(nullptr), |
| 59 collapsed_borders_valid_(false), | 59 collapsed_borders_valid_(false), |
| 60 needs_invalidate_collapsed_borders_for_all_cells_(false), | 60 needs_invalidate_collapsed_borders_for_all_cells_(false), |
| 61 collapsed_outer_borders_valid_(false), |
| 61 has_col_elements_(false), | 62 has_col_elements_(false), |
| 62 needs_section_recalc_(false), | 63 needs_section_recalc_(false), |
| 63 column_logical_width_changed_(false), | 64 column_logical_width_changed_(false), |
| 64 column_layout_objects_valid_(false), | 65 column_layout_objects_valid_(false), |
| 65 no_cell_colspan_at_least_(0), | 66 no_cell_colspan_at_least_(0), |
| 66 h_spacing_(0), | 67 h_spacing_(0), |
| 67 v_spacing_(0), | 68 v_spacing_(0), |
| 68 border_start_(0), | 69 collapsed_outer_border_start_(0), |
| 69 border_end_(0) { | 70 collapsed_outer_border_end_(0), |
| 71 collapsed_outer_border_before_(0), |
| 72 collapsed_outer_border_after_(0) { |
| 70 DCHECK(!ChildrenInline()); | 73 DCHECK(!ChildrenInline()); |
| 71 effective_column_positions_.Fill(0, 1); | 74 effective_column_positions_.Fill(0, 1); |
| 72 } | 75 } |
| 73 | 76 |
| 74 LayoutTable::~LayoutTable() {} | 77 LayoutTable::~LayoutTable() {} |
| 75 | 78 |
| 76 void LayoutTable::StyleDidChange(StyleDifference diff, | 79 void LayoutTable::StyleDidChange(StyleDifference diff, |
| 77 const ComputedStyle* old_style) { | 80 const ComputedStyle* old_style) { |
| 78 LayoutBlock::StyleDidChange(diff, old_style); | 81 LayoutBlock::StyleDidChange(diff, old_style); |
| 79 | 82 |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 | 576 |
| 574 if (SimplifiedLayout()) | 577 if (SimplifiedLayout()) |
| 575 return; | 578 return; |
| 576 | 579 |
| 577 // Note: LayoutTable is handled differently than other LayoutBlocks and the | 580 // Note: LayoutTable is handled differently than other LayoutBlocks and the |
| 578 // LayoutScope | 581 // LayoutScope |
| 579 // must be created before the table begins laying out. | 582 // must be created before the table begins laying out. |
| 580 TextAutosizer::LayoutScope text_autosizer_layout_scope(this); | 583 TextAutosizer::LayoutScope text_autosizer_layout_scope(this); |
| 581 | 584 |
| 582 RecalcSectionsIfNeeded(); | 585 RecalcSectionsIfNeeded(); |
| 583 // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we | |
| 584 // don't have to make sure to call this before we call borderStart/borderEnd | |
| 585 // to avoid getting a stale value. | |
| 586 RecalcBordersInRowDirection(); | |
| 587 | 586 |
| 588 SubtreeLayoutScope layouter(*this); | 587 SubtreeLayoutScope layouter(*this); |
| 589 | 588 |
| 590 { | 589 { |
| 591 LayoutState state(*this); | 590 LayoutState state(*this); |
| 592 LayoutUnit old_logical_width = LogicalWidth(); | 591 LayoutUnit old_logical_width = LogicalWidth(); |
| 593 LayoutUnit old_logical_height = LogicalHeight(); | 592 LayoutUnit old_logical_height = LogicalHeight(); |
| 594 | 593 |
| 595 SetLogicalHeight(LayoutUnit()); | 594 SetLogicalHeight(LayoutUnit()); |
| 596 UpdateLogicalWidth(); | 595 UpdateLogicalWidth(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 617 | 616 |
| 618 LayoutTableSection* top_section = this->TopSection(); | 617 LayoutTableSection* top_section = this->TopSection(); |
| 619 LayoutTableSection* bottom_section = this->BottomSection(); | 618 LayoutTableSection* bottom_section = this->BottomSection(); |
| 620 | 619 |
| 621 // This is the border-before edge of the "table box", relative to the "table | 620 // This is the border-before edge of the "table box", relative to the "table |
| 622 // wrapper box", i.e. right after all top captions. | 621 // wrapper box", i.e. right after all top captions. |
| 623 // https://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#model | 622 // https://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#model |
| 624 LayoutUnit table_box_logical_top = LogicalHeight(); | 623 LayoutUnit table_box_logical_top = LogicalHeight(); |
| 625 | 624 |
| 626 bool collapsing = ShouldCollapseBorders(); | 625 bool collapsing = ShouldCollapseBorders(); |
| 627 if (collapsing) { | |
| 628 // Need to set up the table borders before we can position the sections. | |
| 629 for (LayoutTableSection* section = top_section; section; | |
| 630 section = SectionBelow(section)) | |
| 631 section->RecalcOuterBorder(); | |
| 632 } | |
| 633 | |
| 634 LayoutUnit border_and_padding_before = | 626 LayoutUnit border_and_padding_before = |
| 635 BorderBefore() + (collapsing ? LayoutUnit() : PaddingBefore()); | 627 BorderBefore() + (collapsing ? LayoutUnit() : PaddingBefore()); |
| 636 LayoutUnit border_and_padding_after = | 628 LayoutUnit border_and_padding_after = |
| 637 BorderAfter() + (collapsing ? LayoutUnit() : PaddingAfter()); | 629 BorderAfter() + (collapsing ? LayoutUnit() : PaddingAfter()); |
| 638 | 630 |
| 639 SetLogicalHeight(table_box_logical_top + border_and_padding_before); | 631 SetLogicalHeight(table_box_logical_top + border_and_padding_before); |
| 640 | 632 |
| 641 LayoutUnit section_logical_left = LayoutUnit( | 633 LayoutUnit section_logical_left = LayoutUnit( |
| 642 Style()->IsLeftToRightDirection() ? BorderStart() : BorderEnd()); | 634 Style()->IsLeftToRightDirection() ? BorderStart() : BorderEnd()); |
| 643 if (!collapsing) { | 635 if (!collapsing) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 SetIntrinsicContentLogicalHeight(ContentLogicalHeight()); | 765 SetIntrinsicContentLogicalHeight(ContentLogicalHeight()); |
| 774 | 766 |
| 775 column_logical_width_changed_ = false; | 767 column_logical_width_changed_ = false; |
| 776 ClearNeedsLayout(); | 768 ClearNeedsLayout(); |
| 777 } | 769 } |
| 778 | 770 |
| 779 void LayoutTable::InvalidateCollapsedBorders() { | 771 void LayoutTable::InvalidateCollapsedBorders() { |
| 780 collapsed_borders_.clear(); | 772 collapsed_borders_.clear(); |
| 781 collapsed_borders_valid_ = false; | 773 collapsed_borders_valid_ = false; |
| 782 needs_invalidate_collapsed_borders_for_all_cells_ = true; | 774 needs_invalidate_collapsed_borders_for_all_cells_ = true; |
| 775 collapsed_outer_borders_valid_ = false; |
| 783 SetMayNeedPaintInvalidation(); | 776 SetMayNeedPaintInvalidation(); |
| 784 } | 777 } |
| 785 | 778 |
| 786 void LayoutTable::InvalidateCollapsedBordersForAllCellsIfNeeded() { | 779 void LayoutTable::InvalidateCollapsedBordersForAllCellsIfNeeded() { |
| 787 DCHECK(ShouldCollapseBorders()); | 780 DCHECK(ShouldCollapseBorders()); |
| 788 | 781 |
| 789 if (!needs_invalidate_collapsed_borders_for_all_cells_) | 782 if (!needs_invalidate_collapsed_borders_for_all_cells_) |
| 790 return; | 783 return; |
| 791 needs_invalidate_collapsed_borders_for_all_cells_ = false; | 784 needs_invalidate_collapsed_borders_for_all_cells_ = false; |
| 792 | 785 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 824 cell = cell->NextCell()) { | 817 cell = cell->NextCell()) { |
| 825 DCHECK_EQ(cell->Table(), this); | 818 DCHECK_EQ(cell->Table(), this); |
| 826 cell->CollectCollapsedBorderValues(collapsed_borders_); | 819 cell->CollectCollapsedBorderValues(collapsed_borders_); |
| 827 } | 820 } |
| 828 } | 821 } |
| 829 } | 822 } |
| 830 LayoutTableCell::SortCollapsedBorderValues(collapsed_borders_); | 823 LayoutTableCell::SortCollapsedBorderValues(collapsed_borders_); |
| 831 } | 824 } |
| 832 | 825 |
| 833 void LayoutTable::AddOverflowFromChildren() { | 826 void LayoutTable::AddOverflowFromChildren() { |
| 827 /* |
| 834 // Add overflow from borders. | 828 // Add overflow from borders. |
| 835 // Technically it's odd that we are incorporating the borders into layout | 829 // Technically it's odd that we are incorporating the borders into layout |
| 836 // overflow, which is only supposed to be about overflow from our | 830 // overflow, which is only supposed to be about overflow from our |
| 837 // descendant objects, but since tables don't support overflow:auto, this | 831 // descendant objects, but since tables don't support overflow:auto, this |
| 838 // works out fine. | 832 // works out fine. |
| 839 if (ShouldCollapseBorders()) { | 833 if (ShouldCollapseBorders()) { |
| 840 LayoutUnit right_border_overflow = | 834 LayoutUnit right_border_overflow = |
| 841 Size().Width() + OuterBorderRight() - BorderRight(); | 835 Size().Width() + CollapsedOuterBorderRight() - BorderRight(); |
| 842 LayoutUnit left_border_overflow = BorderLeft() - OuterBorderLeft(); | 836 LayoutUnit left_border_overflow = BorderLeft() - CollapsedOuterBorderLeft(); |
| 843 LayoutUnit bottom_border_overflow = | 837 LayoutUnit bottom_border_overflow = |
| 844 Size().Height() + OuterBorderBottom() - BorderBottom(); | 838 Size().Height() + CollapsedOuterBorderBottom() - BorderBottom(); |
| 845 LayoutUnit top_border_overflow = BorderTop() - OuterBorderTop(); | 839 LayoutUnit top_border_overflow = BorderTop() - CollapsedOuterBorderTop(); |
| 846 IntRect border_overflow_rect( | 840 IntRect border_overflow_rect( |
| 847 left_border_overflow.ToInt(), top_border_overflow.ToInt(), | 841 left_border_overflow.ToInt(), top_border_overflow.ToInt(), |
| 848 (right_border_overflow - left_border_overflow).ToInt(), | 842 (right_border_overflow - left_border_overflow).ToInt(), |
| 849 (bottom_border_overflow - top_border_overflow).ToInt()); | 843 (bottom_border_overflow - top_border_overflow).ToInt()); |
| 850 if (border_overflow_rect != PixelSnappedBorderBoxRect()) { | 844 if (border_overflow_rect != PixelSnappedBorderBoxRect()) { |
| 851 LayoutRect border_layout_rect(border_overflow_rect); | 845 LayoutRect border_layout_rect(border_overflow_rect); |
| 852 AddLayoutOverflow(border_layout_rect); | 846 AddLayoutOverflow(border_layout_rect); |
| 853 AddContentsVisualOverflow(border_layout_rect); | 847 AddContentsVisualOverflow(border_layout_rect); |
| 854 } | 848 } |
| 855 } | 849 }*/ |
| 850 // TODO: Add a test. |
| 856 | 851 |
| 857 // Add overflow from our caption. | 852 // Add overflow from our caption. |
| 858 for (unsigned i = 0; i < captions_.size(); i++) | 853 for (unsigned i = 0; i < captions_.size(); i++) |
| 859 AddOverflowFromChild(*captions_[i]); | 854 AddOverflowFromChild(*captions_[i]); |
| 860 | 855 |
| 861 // Add overflow from our sections. | 856 // Add overflow from our sections. |
| 862 for (LayoutTableSection* section = TopSection(); section; | 857 for (LayoutTableSection* section = TopSection(); section; |
| 863 section = SectionBelow(section)) | 858 section = SectionBelow(section)) |
| 864 AddOverflowFromChild(*section); | 859 AddOverflowFromChild(*section); |
| 865 } | 860 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 } | 902 } |
| 908 | 903 |
| 909 void LayoutTable::PaintMask(const PaintInfo& paint_info, | 904 void LayoutTable::PaintMask(const PaintInfo& paint_info, |
| 910 const LayoutPoint& paint_offset) const { | 905 const LayoutPoint& paint_offset) const { |
| 911 TablePainter(*this).PaintMask(paint_info, paint_offset); | 906 TablePainter(*this).PaintMask(paint_info, paint_offset); |
| 912 } | 907 } |
| 913 | 908 |
| 914 void LayoutTable::ComputeIntrinsicLogicalWidths(LayoutUnit& min_width, | 909 void LayoutTable::ComputeIntrinsicLogicalWidths(LayoutUnit& min_width, |
| 915 LayoutUnit& max_width) const { | 910 LayoutUnit& max_width) const { |
| 916 RecalcSectionsIfNeeded(); | 911 RecalcSectionsIfNeeded(); |
| 917 // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast | |
| 918 // this call. | |
| 919 // Then m_borderStart/m_borderEnd will be transparent a cache and it removes | |
| 920 // the possibility of reading out stale values. | |
| 921 const_cast<LayoutTable*>(this)->RecalcBordersInRowDirection(); | |
| 922 // FIXME: Restructure the table layout code so that we can make this method | 912 // FIXME: Restructure the table layout code so that we can make this method |
| 923 // const. | 913 // const. |
| 924 const_cast<LayoutTable*>(this)->table_layout_->ComputeIntrinsicLogicalWidths( | 914 const_cast<LayoutTable*>(this)->table_layout_->ComputeIntrinsicLogicalWidths( |
| 925 min_width, max_width); | 915 min_width, max_width); |
| 926 | 916 |
| 927 // FIXME: We should include captions widths here like we do in | 917 // FIXME: We should include captions widths here like we do in |
| 928 // computePreferredLogicalWidths. | 918 // computePreferredLogicalWidths. |
| 929 } | 919 } |
| 930 | 920 |
| 931 void LayoutTable::ComputePreferredLogicalWidths() { | 921 void LayoutTable::ComputePreferredLogicalWidths() { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 ClearPreferredLogicalWidthsDirty(); | 970 ClearPreferredLogicalWidthsDirty(); |
| 981 } | 971 } |
| 982 | 972 |
| 983 LayoutTableSection* LayoutTable::TopNonEmptySection() const { | 973 LayoutTableSection* LayoutTable::TopNonEmptySection() const { |
| 984 LayoutTableSection* section = TopSection(); | 974 LayoutTableSection* section = TopSection(); |
| 985 if (section && !section->NumRows()) | 975 if (section && !section->NumRows()) |
| 986 section = SectionBelow(section, kSkipEmptySections); | 976 section = SectionBelow(section, kSkipEmptySections); |
| 987 return section; | 977 return section; |
| 988 } | 978 } |
| 989 | 979 |
| 980 LayoutTableSection* LayoutTable::BottomNonEmptySection() const { |
| 981 LayoutTableSection* section = BottomSection(); |
| 982 if (section && !section->NumRows()) |
| 983 section = SectionAbove(section, kSkipEmptySections); |
| 984 return section; |
| 985 } |
| 986 |
| 990 void LayoutTable::SplitEffectiveColumn(unsigned index, unsigned first_span) { | 987 void LayoutTable::SplitEffectiveColumn(unsigned index, unsigned first_span) { |
| 991 // We split the column at |index|, taking |firstSpan| cells from the span. | 988 // We split the column at |index|, taking |firstSpan| cells from the span. |
| 992 DCHECK_GT(effective_columns_[index].span, first_span); | 989 DCHECK_GT(effective_columns_[index].span, first_span); |
| 993 effective_columns_.insert(index, first_span); | 990 effective_columns_.insert(index, first_span); |
| 994 effective_columns_[index + 1].span -= first_span; | 991 effective_columns_[index + 1].span -= first_span; |
| 995 | 992 |
| 996 // Propagate the change in our columns representation to the sections that | 993 // Propagate the change in our columns representation to the sections that |
| 997 // don't need cell recalc. If they do, they will be synced up directly with | 994 // don't need cell recalc. If they do, they will be synced up directly with |
| 998 // m_columns later. | 995 // m_columns later. |
| 999 for (LayoutObject* child = FirstChild(); child; | 996 for (LayoutObject* child = FirstChild(); child; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 | 1168 |
| 1172 effective_columns_.resize(max_cols); | 1169 effective_columns_.resize(max_cols); |
| 1173 effective_column_positions_.resize(max_cols + 1); | 1170 effective_column_positions_.resize(max_cols + 1); |
| 1174 no_cell_colspan_at_least_ = CalcNoCellColspanAtLeast(); | 1171 no_cell_colspan_at_least_ = CalcNoCellColspanAtLeast(); |
| 1175 | 1172 |
| 1176 DCHECK(SelfNeedsLayout()); | 1173 DCHECK(SelfNeedsLayout()); |
| 1177 | 1174 |
| 1178 needs_section_recalc_ = false; | 1175 needs_section_recalc_ = false; |
| 1179 } | 1176 } |
| 1180 | 1177 |
| 1181 int LayoutTable::CalcBorderStart() const { | |
| 1182 if (!ShouldCollapseBorders()) | |
| 1183 return LayoutBlock::BorderStart().ToInt(); | |
| 1184 | |
| 1185 // Determined by the first cell of the first row. See the CSS 2.1 spec, | |
| 1186 // section 17.6.2. | |
| 1187 if (!NumEffectiveColumns()) | |
| 1188 return 0; | |
| 1189 | |
| 1190 int border_width = 0; | |
| 1191 | |
| 1192 const BorderValue& table_start_border = Style()->BorderStart(); | |
| 1193 if (table_start_border.Style() == kBorderStyleHidden) | |
| 1194 return 0; | |
| 1195 if (table_start_border.Style() > kBorderStyleHidden) | |
| 1196 border_width = table_start_border.Width(); | |
| 1197 | |
| 1198 // TODO(dgrogan): This logic doesn't properly account for the first column in | |
| 1199 // the first column-group case. | |
| 1200 if (LayoutTableCol* column = | |
| 1201 ColElementAtEffectiveColumn(0).InnermostColOrColGroup()) { | |
| 1202 // FIXME: We don't account for direction on columns and column groups. | |
| 1203 const BorderValue& column_adjoining_border = column->Style()->BorderStart(); | |
| 1204 if (column_adjoining_border.Style() == kBorderStyleHidden) | |
| 1205 return 0; | |
| 1206 if (column_adjoining_border.Style() > kBorderStyleHidden) | |
| 1207 border_width = | |
| 1208 std::max<int>(border_width, column_adjoining_border.Width()); | |
| 1209 } | |
| 1210 | |
| 1211 if (const LayoutTableSection* top_non_empty_section = | |
| 1212 this->TopNonEmptySection()) { | |
| 1213 const BorderValue& section_adjoining_border = | |
| 1214 top_non_empty_section->BorderAdjoiningTableStart(); | |
| 1215 if (section_adjoining_border.Style() == kBorderStyleHidden) | |
| 1216 return 0; | |
| 1217 | |
| 1218 if (section_adjoining_border.Style() > kBorderStyleHidden) | |
| 1219 border_width = | |
| 1220 std::max<int>(border_width, section_adjoining_border.Width()); | |
| 1221 | |
| 1222 if (const LayoutTableCell* adjoining_start_cell = | |
| 1223 top_non_empty_section->FirstRowCellAdjoiningTableStart()) { | |
| 1224 // FIXME: Make this work with perpendicular and flipped cells. | |
| 1225 const BorderValue& start_cell_adjoining_border = | |
| 1226 adjoining_start_cell->BorderAdjoiningTableStart(); | |
| 1227 if (start_cell_adjoining_border.Style() == kBorderStyleHidden) | |
| 1228 return 0; | |
| 1229 | |
| 1230 const BorderValue& first_row_adjoining_border = | |
| 1231 adjoining_start_cell->Row()->BorderAdjoiningTableStart(); | |
| 1232 if (first_row_adjoining_border.Style() == kBorderStyleHidden) | |
| 1233 return 0; | |
| 1234 | |
| 1235 if (start_cell_adjoining_border.Style() > kBorderStyleHidden) { | |
| 1236 border_width = | |
| 1237 std::max<int>(border_width, start_cell_adjoining_border.Width()); | |
| 1238 } | |
| 1239 if (first_row_adjoining_border.Style() > kBorderStyleHidden) { | |
| 1240 border_width = | |
| 1241 std::max<int>(border_width, first_row_adjoining_border.Width()); | |
| 1242 } | |
| 1243 } | |
| 1244 } | |
| 1245 return (border_width + (Style()->IsLeftToRightDirection() ? 0 : 1)) / 2; | |
| 1246 } | |
| 1247 | |
| 1248 int LayoutTable::CalcBorderEnd() const { | |
| 1249 if (!ShouldCollapseBorders()) | |
| 1250 return LayoutBlock::BorderEnd().ToInt(); | |
| 1251 | |
| 1252 // Determined by the last cell of the first row. See the CSS 2.1 spec, section | |
| 1253 // 17.6.2. | |
| 1254 if (!NumEffectiveColumns()) | |
| 1255 return 0; | |
| 1256 | |
| 1257 int border_width = 0; | |
| 1258 | |
| 1259 const BorderValue& table_end_border = Style()->BorderEnd(); | |
| 1260 if (table_end_border.Style() == kBorderStyleHidden) | |
| 1261 return 0; | |
| 1262 if (table_end_border.Style() > kBorderStyleHidden) | |
| 1263 border_width = table_end_border.Width(); | |
| 1264 | |
| 1265 unsigned end_column = NumEffectiveColumns() - 1; | |
| 1266 | |
| 1267 // TODO(dgrogan): This logic doesn't properly account for the last column in | |
| 1268 // the last column-group case. | |
| 1269 if (LayoutTableCol* column = | |
| 1270 ColElementAtEffectiveColumn(end_column).InnermostColOrColGroup()) { | |
| 1271 // FIXME: We don't account for direction on columns and column groups. | |
| 1272 const BorderValue& column_adjoining_border = column->Style()->BorderEnd(); | |
| 1273 if (column_adjoining_border.Style() == kBorderStyleHidden) | |
| 1274 return 0; | |
| 1275 if (column_adjoining_border.Style() > kBorderStyleHidden) | |
| 1276 border_width = | |
| 1277 std::max<int>(border_width, column_adjoining_border.Width()); | |
| 1278 } | |
| 1279 | |
| 1280 if (const LayoutTableSection* top_non_empty_section = | |
| 1281 this->TopNonEmptySection()) { | |
| 1282 const BorderValue& section_adjoining_border = | |
| 1283 top_non_empty_section->BorderAdjoiningTableEnd(); | |
| 1284 if (section_adjoining_border.Style() == kBorderStyleHidden) | |
| 1285 return 0; | |
| 1286 | |
| 1287 if (section_adjoining_border.Style() > kBorderStyleHidden) | |
| 1288 border_width = | |
| 1289 std::max<int>(border_width, section_adjoining_border.Width()); | |
| 1290 | |
| 1291 if (const LayoutTableCell* adjoining_end_cell = | |
| 1292 top_non_empty_section->FirstRowCellAdjoiningTableEnd()) { | |
| 1293 // FIXME: Make this work with perpendicular and flipped cells. | |
| 1294 const BorderValue& end_cell_adjoining_border = | |
| 1295 adjoining_end_cell->BorderAdjoiningTableEnd(); | |
| 1296 if (end_cell_adjoining_border.Style() == kBorderStyleHidden) | |
| 1297 return 0; | |
| 1298 | |
| 1299 const BorderValue& first_row_adjoining_border = | |
| 1300 adjoining_end_cell->Row()->BorderAdjoiningTableEnd(); | |
| 1301 if (first_row_adjoining_border.Style() == kBorderStyleHidden) | |
| 1302 return 0; | |
| 1303 | |
| 1304 if (end_cell_adjoining_border.Style() > kBorderStyleHidden) { | |
| 1305 border_width = | |
| 1306 std::max<int>(border_width, end_cell_adjoining_border.Width()); | |
| 1307 } | |
| 1308 if (first_row_adjoining_border.Style() > kBorderStyleHidden) { | |
| 1309 border_width = | |
| 1310 std::max<int>(border_width, first_row_adjoining_border.Width()); | |
| 1311 } | |
| 1312 } | |
| 1313 } | |
| 1314 return (border_width + (Style()->IsLeftToRightDirection() ? 1 : 0)) / 2; | |
| 1315 } | |
| 1316 | |
| 1317 void LayoutTable::RecalcBordersInRowDirection() { | |
| 1318 // FIXME: We need to compute the collapsed before / after borders in the same | |
| 1319 // fashion. | |
| 1320 border_start_ = CalcBorderStart(); | |
| 1321 border_end_ = CalcBorderEnd(); | |
| 1322 } | |
| 1323 | |
| 1324 LayoutUnit LayoutTable::BorderBefore() const { | 1178 LayoutUnit LayoutTable::BorderBefore() const { |
| 1325 if (ShouldCollapseBorders()) { | 1179 if (ShouldCollapseBorders()) { |
| 1326 RecalcSectionsIfNeeded(); | 1180 UpdateCollapsedOuterBorders(); |
| 1327 return LayoutUnit(OuterBorderBefore()); | 1181 return LayoutUnit(collapsed_outer_border_before_); |
| 1328 } | 1182 } |
| 1329 return LayoutBlock::BorderBefore(); | 1183 return LayoutBlock::BorderBefore(); |
| 1330 } | 1184 } |
| 1331 | 1185 |
| 1332 LayoutUnit LayoutTable::BorderAfter() const { | 1186 LayoutUnit LayoutTable::BorderAfter() const { |
| 1333 if (ShouldCollapseBorders()) { | 1187 if (ShouldCollapseBorders()) { |
| 1334 RecalcSectionsIfNeeded(); | 1188 UpdateCollapsedOuterBorders(); |
| 1335 return LayoutUnit(OuterBorderAfter()); | 1189 return LayoutUnit(collapsed_outer_border_after_); |
| 1336 } | 1190 } |
| 1337 return LayoutBlock::BorderAfter(); | 1191 return LayoutBlock::BorderAfter(); |
| 1338 } | 1192 } |
| 1339 | 1193 |
| 1340 int LayoutTable::OuterBorderBefore() const { | 1194 LayoutUnit LayoutTable::BorderStart() const { |
| 1341 if (!ShouldCollapseBorders()) | 1195 if (ShouldCollapseBorders()) { |
| 1342 return 0; | 1196 UpdateCollapsedOuterBorders(); |
| 1343 int border_width = 0; | 1197 return LayoutUnit(collapsed_outer_border_start_); |
| 1344 if (LayoutTableSection* top_section = this->TopSection()) { | |
| 1345 border_width = top_section->OuterBorderBefore(); | |
| 1346 if (border_width < 0) | |
| 1347 return 0; // Overridden by hidden | |
| 1348 } | 1198 } |
| 1349 const BorderValue& tb = Style()->BorderBefore(); | 1199 return LayoutBlock::BorderStart(); |
| 1350 if (tb.Style() == kBorderStyleHidden) | |
| 1351 return 0; | |
| 1352 if (tb.Style() > kBorderStyleHidden) | |
| 1353 border_width = std::max<int>(border_width, tb.Width() / 2); | |
| 1354 return border_width; | |
| 1355 } | 1200 } |
| 1356 | 1201 |
| 1357 int LayoutTable::OuterBorderAfter() const { | 1202 LayoutUnit LayoutTable::BorderEnd() const { |
| 1358 if (!ShouldCollapseBorders()) | 1203 if (ShouldCollapseBorders()) { |
| 1359 return 0; | 1204 UpdateCollapsedOuterBorders(); |
| 1360 int border_width = 0; | 1205 return LayoutUnit(collapsed_outer_border_end_); |
| 1361 | |
| 1362 if (LayoutTableSection* section = BottomSection()) { | |
| 1363 border_width = section->OuterBorderAfter(); | |
| 1364 if (border_width < 0) | |
| 1365 return 0; // Overridden by hidden | |
| 1366 } | 1206 } |
| 1367 const BorderValue& tb = Style()->BorderAfter(); | 1207 return LayoutBlock::BorderEnd(); |
| 1368 if (tb.Style() == kBorderStyleHidden) | |
| 1369 return 0; | |
| 1370 if (tb.Style() > kBorderStyleHidden) | |
| 1371 border_width = std::max<int>(border_width, (tb.Width() + 1) / 2); | |
| 1372 return border_width; | |
| 1373 } | |
| 1374 | |
| 1375 int LayoutTable::OuterBorderStart() const { | |
| 1376 if (!ShouldCollapseBorders()) | |
| 1377 return 0; | |
| 1378 | |
| 1379 int border_width = 0; | |
| 1380 | |
| 1381 const BorderValue& tb = Style()->BorderStart(); | |
| 1382 if (tb.Style() == kBorderStyleHidden) | |
| 1383 return 0; | |
| 1384 if (tb.Style() > kBorderStyleHidden) | |
| 1385 border_width = | |
| 1386 (tb.Width() + (Style()->IsLeftToRightDirection() ? 0 : 1)) / 2; | |
| 1387 | |
| 1388 bool all_hidden = true; | |
| 1389 for (LayoutTableSection* section = TopSection(); section; | |
| 1390 section = SectionBelow(section)) { | |
| 1391 int sw = section->OuterBorderStart(); | |
| 1392 if (sw < 0) | |
| 1393 continue; | |
| 1394 all_hidden = false; | |
| 1395 border_width = std::max(border_width, sw); | |
| 1396 } | |
| 1397 if (all_hidden) | |
| 1398 return 0; | |
| 1399 | |
| 1400 return border_width; | |
| 1401 } | |
| 1402 | |
| 1403 int LayoutTable::OuterBorderEnd() const { | |
| 1404 if (!ShouldCollapseBorders()) | |
| 1405 return 0; | |
| 1406 | |
| 1407 int border_width = 0; | |
| 1408 | |
| 1409 const BorderValue& tb = Style()->BorderEnd(); | |
| 1410 if (tb.Style() == kBorderStyleHidden) | |
| 1411 return 0; | |
| 1412 if (tb.Style() > kBorderStyleHidden) | |
| 1413 border_width = | |
| 1414 (tb.Width() + (Style()->IsLeftToRightDirection() ? 1 : 0)) / 2; | |
| 1415 | |
| 1416 bool all_hidden = true; | |
| 1417 for (LayoutTableSection* section = TopSection(); section; | |
| 1418 section = SectionBelow(section)) { | |
| 1419 int sw = section->OuterBorderEnd(); | |
| 1420 if (sw < 0) | |
| 1421 continue; | |
| 1422 all_hidden = false; | |
| 1423 border_width = std::max(border_width, sw); | |
| 1424 } | |
| 1425 if (all_hidden) | |
| 1426 return 0; | |
| 1427 | |
| 1428 return border_width; | |
| 1429 } | 1208 } |
| 1430 | 1209 |
| 1431 LayoutTableSection* LayoutTable::SectionAbove( | 1210 LayoutTableSection* LayoutTable::SectionAbove( |
| 1432 const LayoutTableSection* section, | 1211 const LayoutTableSection* section, |
| 1433 SkipEmptySectionsValue skip_empty_sections) const { | 1212 SkipEmptySectionsValue skip_empty_sections) const { |
| 1434 RecalcSectionsIfNeeded(); | 1213 RecalcSectionsIfNeeded(); |
| 1435 | 1214 |
| 1436 if (section == head_) | 1215 if (section == head_) |
| 1437 return 0; | 1216 return 0; |
| 1438 | 1217 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 return LayoutBlock::PaddingLeft(); | 1529 return LayoutBlock::PaddingLeft(); |
| 1751 } | 1530 } |
| 1752 | 1531 |
| 1753 LayoutUnit LayoutTable::PaddingRight() const { | 1532 LayoutUnit LayoutTable::PaddingRight() const { |
| 1754 if (ShouldCollapseBorders()) | 1533 if (ShouldCollapseBorders()) |
| 1755 return LayoutUnit(); | 1534 return LayoutUnit(); |
| 1756 | 1535 |
| 1757 return LayoutBlock::PaddingRight(); | 1536 return LayoutBlock::PaddingRight(); |
| 1758 } | 1537 } |
| 1759 | 1538 |
| 1539 unsigned LayoutTable::ComputeCollapsedOuterBorderBefore() const { |
| 1540 DCHECK(ShouldCollapseBorders()); |
| 1541 |
| 1542 const auto* section = TopNonEmptySection(); |
| 1543 if (!section) |
| 1544 return 0; |
| 1545 |
| 1546 unsigned n_cols = section->NumEffectiveColumns(0); |
| 1547 unsigned result = 0; |
| 1548 for (unsigned col = 0; col < n_cols; ++col) { |
| 1549 if (const auto* cell = section->PrimaryCellAt(0, col)) |
| 1550 result = std::max(result, cell->CollapsedOuterBorderBefore()); |
| 1551 } |
| 1552 return result; |
| 1553 } |
| 1554 |
| 1555 unsigned LayoutTable::ComputeCollapsedOuterBorderAfter() const { |
| 1556 DCHECK(ShouldCollapseBorders()); |
| 1557 |
| 1558 const auto* section = BottomNonEmptySection(); |
| 1559 if (!section) |
| 1560 return 0; |
| 1561 |
| 1562 unsigned row = section->NumRows() - 1; |
| 1563 unsigned n_cols = section->NumEffectiveColumns(row); |
| 1564 unsigned result = 0; |
| 1565 for (unsigned col = 0; col < n_cols; ++col) { |
| 1566 if (const auto* cell = section->PrimaryCellAt(row, col)) |
| 1567 result = std::max(result, cell->CollapsedOuterBorderAfter()); |
| 1568 } |
| 1569 return result; |
| 1570 } |
| 1571 |
| 1572 unsigned LayoutTable::ComputeCollapsedOuterBorderStart() const { |
| 1573 DCHECK(ShouldCollapseBorders()); |
| 1574 |
| 1575 unsigned result = 0; |
| 1576 for (const auto* section = TopNonEmptySection(); section; |
| 1577 section = SectionBelow(section, kSkipEmptySections)) { |
| 1578 for (unsigned row = 0; row < section->NumRows(); ++row) { |
| 1579 if (const auto* cell = section->PrimaryCellAt(row, 0)) |
| 1580 result = std::max(result, cell->CollapsedOuterBorderStart()); |
| 1581 } |
| 1582 } |
| 1583 return result; |
| 1584 } |
| 1585 |
| 1586 unsigned LayoutTable::ComputeCollapsedOuterBorderEnd() const { |
| 1587 DCHECK(ShouldCollapseBorders()); |
| 1588 |
| 1589 unsigned n_cols = NumEffectiveColumns(); |
| 1590 if (!n_cols) |
| 1591 return 0; |
| 1592 |
| 1593 unsigned result = 0; |
| 1594 for (const auto* section = TopNonEmptySection(); section; |
| 1595 section = SectionBelow(section, kSkipEmptySections)) { |
| 1596 for (unsigned row = 0; row < section->NumRows(); ++row) { |
| 1597 if (const auto* cell = section->PrimaryCellAt(row, n_cols - 1)) |
| 1598 result = std::max(result, cell->CollapsedOuterBorderEnd()); |
| 1599 } |
| 1600 } |
| 1601 return result; |
| 1602 } |
| 1603 |
| 1604 void LayoutTable::UpdateCollapsedOuterBorders() const { |
| 1605 if (collapsed_outer_borders_valid_) |
| 1606 return; |
| 1607 |
| 1608 collapsed_outer_borders_valid_ = true; |
| 1609 if (ShouldCollapseBorders()) { |
| 1610 collapsed_outer_border_before_ = ComputeCollapsedOuterBorderBefore(); |
| 1611 collapsed_outer_border_after_ = ComputeCollapsedOuterBorderAfter(); |
| 1612 collapsed_outer_border_start_ = ComputeCollapsedOuterBorderStart(); |
| 1613 collapsed_outer_border_end_ = ComputeCollapsedOuterBorderEnd(); |
| 1614 } |
| 1615 } |
| 1616 |
| 1760 } // namespace blink | 1617 } // namespace blink |
| OLD | NEW |