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 |