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 has_col_elements_(false), | |
62 needs_section_recalc_(false), | 61 needs_section_recalc_(false), |
63 column_logical_width_changed_(false), | 62 column_logical_width_changed_(false), |
64 column_layout_objects_valid_(false), | 63 // This is initially true because we don't have column elements initially. |
| 64 cols_at_effective_columns_valid_(true), |
65 no_cell_colspan_at_least_(0), | 65 no_cell_colspan_at_least_(0), |
66 h_spacing_(0), | 66 h_spacing_(0), |
67 v_spacing_(0), | 67 v_spacing_(0), |
68 border_start_(0), | 68 border_start_(0), |
69 border_end_(0) { | 69 border_end_(0) { |
70 DCHECK(!ChildrenInline()); | 70 DCHECK(!ChildrenInline()); |
71 effective_column_positions_.Fill(0, 1); | 71 effective_column_positions_.Fill(0, 1); |
72 } | 72 } |
73 | 73 |
74 LayoutTable::~LayoutTable() {} | 74 LayoutTable::~LayoutTable() {} |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 // wrapped in a table section box. | 129 // wrapped in a table section box. |
130 EDisplay display = object->Style()->Display(); | 130 EDisplay display = object->Style()->Display(); |
131 return display != EDisplay::kTableCaption && | 131 return display != EDisplay::kTableCaption && |
132 display != EDisplay::kTableColumnGroup && | 132 display != EDisplay::kTableColumnGroup && |
133 display != EDisplay::kTableColumn; | 133 display != EDisplay::kTableColumn; |
134 } | 134 } |
135 | 135 |
136 void LayoutTable::AddChild(LayoutObject* child, LayoutObject* before_child) { | 136 void LayoutTable::AddChild(LayoutObject* child, LayoutObject* before_child) { |
137 bool wrap_in_anonymous_section = !child->IsOutOfFlowPositioned(); | 137 bool wrap_in_anonymous_section = !child->IsOutOfFlowPositioned(); |
138 | 138 |
139 if (child->IsTableCaption()) { | 139 if (child->IsTableCaption() || child->IsLayoutTableCol()) { |
140 wrap_in_anonymous_section = false; | |
141 } else if (child->IsLayoutTableCol()) { | |
142 has_col_elements_ = true; | |
143 wrap_in_anonymous_section = false; | 140 wrap_in_anonymous_section = false; |
144 } else if (child->IsTableSection()) { | 141 } else if (child->IsTableSection()) { |
145 switch (child->Style()->Display()) { | 142 switch (child->Style()->Display()) { |
146 case EDisplay::kTableHeaderGroup: | 143 case EDisplay::kTableHeaderGroup: |
147 ResetSectionPointerIfNotBefore(head_, before_child); | 144 ResetSectionPointerIfNotBefore(head_, before_child); |
148 if (!head_) { | 145 if (!head_) { |
149 head_ = ToLayoutTableSection(child); | 146 head_ = ToLayoutTableSection(child); |
150 } else { | 147 } else { |
151 ResetSectionPointerIfNotBefore(first_body_, before_child); | 148 ResetSectionPointerIfNotBefore(first_body_, before_child); |
152 if (!first_body_) | 149 if (!first_body_) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 226 |
230 void LayoutTable::RemoveCaption(const LayoutTableCaption* old_caption) { | 227 void LayoutTable::RemoveCaption(const LayoutTableCaption* old_caption) { |
231 size_t index = captions_.Find(old_caption); | 228 size_t index = captions_.Find(old_caption); |
232 DCHECK_NE(index, kNotFound); | 229 DCHECK_NE(index, kNotFound); |
233 if (index == kNotFound) | 230 if (index == kNotFound) |
234 return; | 231 return; |
235 | 232 |
236 captions_.erase(index); | 233 captions_.erase(index); |
237 } | 234 } |
238 | 235 |
239 void LayoutTable::InvalidateCachedColumns() { | 236 void LayoutTable::InvalidateColsAtEffectiveColumns() const { |
240 column_layout_objects_valid_ = false; | 237 cols_at_effective_columns_valid_ = false; |
241 column_layout_objects_.resize(0); | 238 cols_at_effective_columns_ = nullptr; |
242 } | 239 } |
243 | 240 |
244 void LayoutTable::AddColumn(const LayoutTableCol*) { | 241 void LayoutTable::AddColumn(const LayoutTableCol*) { |
245 InvalidateCachedColumns(); | 242 InvalidateColsAtEffectiveColumns(); |
246 } | 243 } |
247 | 244 |
248 void LayoutTable::RemoveColumn(const LayoutTableCol*) { | 245 void LayoutTable::RemoveColumn(const LayoutTableCol*) { |
249 InvalidateCachedColumns(); | 246 InvalidateColsAtEffectiveColumns(); |
250 // We don't really need to recompute our sections, but we need to update our | |
251 // column count and whether we have a column. Currently, we only have one | |
252 // size-fit-all flag but we may have to consider splitting it. | |
253 SetNeedsSectionRecalc(); | |
254 } | 247 } |
255 | 248 |
256 bool LayoutTable::IsLogicalWidthAuto() const { | 249 bool LayoutTable::IsLogicalWidthAuto() const { |
257 Length style_logical_width = Style()->LogicalWidth(); | 250 Length style_logical_width = Style()->LogicalWidth(); |
258 return (!style_logical_width.IsSpecified() || | 251 return (!style_logical_width.IsSpecified() || |
259 !style_logical_width.IsPositive()) && | 252 !style_logical_width.IsPositive()) && |
260 !style_logical_width.IsIntrinsic(); | 253 !style_logical_width.IsIntrinsic(); |
261 } | 254 } |
262 | 255 |
263 void LayoutTable::UpdateLogicalWidth() { | 256 void LayoutTable::UpdateLogicalWidth() { |
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 continue; | 995 continue; |
1003 | 996 |
1004 LayoutTableSection* section = ToLayoutTableSection(child); | 997 LayoutTableSection* section = ToLayoutTableSection(child); |
1005 if (section->NeedsCellRecalc()) | 998 if (section->NeedsCellRecalc()) |
1006 continue; | 999 continue; |
1007 | 1000 |
1008 section->SplitEffectiveColumn(index, first_span); | 1001 section->SplitEffectiveColumn(index, first_span); |
1009 } | 1002 } |
1010 | 1003 |
1011 effective_column_positions_.Grow(NumEffectiveColumns() + 1); | 1004 effective_column_positions_.Grow(NumEffectiveColumns() + 1); |
| 1005 |
| 1006 InvalidateColsAtEffectiveColumns(); |
1012 } | 1007 } |
1013 | 1008 |
1014 void LayoutTable::AppendEffectiveColumn(unsigned span) { | 1009 void LayoutTable::AppendEffectiveColumn(unsigned span) { |
1015 unsigned new_column_index = effective_columns_.size(); | 1010 unsigned new_column_index = effective_columns_.size(); |
1016 effective_columns_.push_back(span); | 1011 effective_columns_.push_back(span); |
1017 | 1012 |
1018 // Unless the table has cell(s) with colspan that exceed the number of columns | 1013 // Unless the table has cell(s) with colspan that exceed the number of columns |
1019 // afforded by the other rows in the table we can use the fast path when | 1014 // afforded by the other rows in the table we can use the fast path when |
1020 // mapping columns to effective columns. | 1015 // mapping columns to effective columns. |
1021 if (span == 1 && no_cell_colspan_at_least_ + 1 == NumEffectiveColumns()) { | 1016 if (span == 1 && no_cell_colspan_at_least_ + 1 == NumEffectiveColumns()) { |
1022 no_cell_colspan_at_least_++; | 1017 no_cell_colspan_at_least_++; |
1023 } | 1018 } |
1024 | 1019 |
1025 // Propagate the change in our columns representation to the sections that | 1020 // Propagate the change in our columns representation to the sections that |
1026 // don't need cell recalc. If they do, they will be synced up directly with | 1021 // don't need cell recalc. If they do, they will be synced up directly with |
1027 // m_columns later. | 1022 // m_columns later. |
1028 for (LayoutObject* child = FirstChild(); child; | 1023 for (LayoutObject* child = FirstChild(); child; |
1029 child = child->NextSibling()) { | 1024 child = child->NextSibling()) { |
1030 if (!child->IsTableSection()) | 1025 if (!child->IsTableSection()) |
1031 continue; | 1026 continue; |
1032 | 1027 |
1033 LayoutTableSection* section = ToLayoutTableSection(child); | 1028 LayoutTableSection* section = ToLayoutTableSection(child); |
1034 if (section->NeedsCellRecalc()) | 1029 if (section->NeedsCellRecalc()) |
1035 continue; | 1030 continue; |
1036 | 1031 |
1037 section->AppendEffectiveColumn(new_column_index); | 1032 section->AppendEffectiveColumn(new_column_index); |
1038 } | 1033 } |
1039 | 1034 |
1040 effective_column_positions_.Grow(NumEffectiveColumns() + 1); | 1035 effective_column_positions_.Grow(NumEffectiveColumns() + 1); |
| 1036 |
| 1037 InvalidateColsAtEffectiveColumns(); |
1041 } | 1038 } |
1042 | 1039 |
1043 LayoutTableCol* LayoutTable::FirstColumn() const { | 1040 LayoutTableCol* LayoutTable::FirstColumn() const { |
1044 for (LayoutObject* child = FirstChild(); child; | 1041 for (LayoutObject* child = FirstChild(); child; |
1045 child = child->NextSibling()) { | 1042 child = child->NextSibling()) { |
1046 if (child->IsLayoutTableCol()) | 1043 if (child->IsLayoutTableCol()) |
1047 return ToLayoutTableCol(child); | 1044 return ToLayoutTableCol(child); |
1048 } | 1045 } |
1049 | 1046 |
1050 return nullptr; | 1047 return nullptr; |
1051 } | 1048 } |
1052 | 1049 |
1053 void LayoutTable::UpdateColumnCache() const { | 1050 LayoutTableCol* LayoutTable::FirstInnermostColumn() const { |
1054 DCHECK(has_col_elements_); | 1051 auto* col = FirstColumn(); |
1055 DCHECK(column_layout_objects_.IsEmpty()); | 1052 return !col || col->IsInnermost() ? col : col->NextInnermostColumn(); |
1056 DCHECK(!column_layout_objects_valid_); | |
1057 | |
1058 for (LayoutTableCol* column_layout_object = FirstColumn(); | |
1059 column_layout_object; | |
1060 column_layout_object = column_layout_object->NextColumn()) { | |
1061 if (column_layout_object->IsTableColumnGroupWithColumnChildren()) | |
1062 continue; | |
1063 column_layout_objects_.push_back(column_layout_object); | |
1064 } | |
1065 column_layout_objects_valid_ = true; | |
1066 } | 1053 } |
1067 | 1054 |
1068 LayoutTable::ColAndColGroup LayoutTable::SlowColElementAtAbsoluteColumn( | 1055 void LayoutTable::UpdateColsAtEffectiveColumns() const { |
1069 unsigned absolute_column_index) const { | 1056 DCHECK(!NeedsSectionRecalc()); |
1070 DCHECK(has_col_elements_); | 1057 DCHECK(!cols_at_effective_columns_valid_); |
| 1058 DCHECK(!cols_at_effective_columns_); |
1071 | 1059 |
1072 if (!column_layout_objects_valid_) | 1060 cols_at_effective_columns_valid_ = true; |
1073 UpdateColumnCache(); | 1061 auto* col = FirstInnermostColumn(); |
| 1062 if (!col) |
| 1063 return; |
1074 | 1064 |
1075 unsigned column_count = 0; | 1065 cols_at_effective_columns_ = WTF::MakeUnique<Vector<ColAndColGroup>>(); |
1076 for (unsigned i = 0; i < column_layout_objects_.size(); i++) { | 1066 |
1077 LayoutTableCol* column_layout_object = column_layout_objects_[i]; | 1067 unsigned absolute_column_index = 0; |
1078 DCHECK(!column_layout_object->IsTableColumnGroupWithColumnChildren()); | 1068 unsigned col_absolute_column_index = 0; |
1079 unsigned span = column_layout_object->Span(); | 1069 unsigned next_col_absolute_column_index = col->Span(); |
1080 unsigned start_col = column_count; | 1070 for (unsigned effective_column_index = 0; |
1081 DCHECK_GE(span, 1u); | 1071 col && effective_column_index < effective_columns_.size(); |
1082 unsigned end_col = column_count + span - 1; | 1072 effective_column_index++) { |
1083 column_count += span; | 1073 unsigned next_absolute_column_index = |
1084 if (column_count > absolute_column_index) { | 1074 absolute_column_index + effective_columns_[effective_column_index].span; |
1085 ColAndColGroup col_and_col_group; | 1075 bool is_at_start_edge = absolute_column_index == col_absolute_column_index; |
1086 bool is_at_start_edge = start_col == absolute_column_index; | 1076 bool is_at_end_edge = |
1087 bool is_at_end_edge = end_col == absolute_column_index; | 1077 next_absolute_column_index == next_col_absolute_column_index; |
1088 if (column_layout_object->IsTableColumnGroup()) { | 1078 ColAndColGroup col_and_col_group; |
1089 col_and_col_group.colgroup = column_layout_object; | 1079 if (col->IsTableColumnGroup()) { |
1090 col_and_col_group.adjoins_start_border_of_col_group = is_at_start_edge; | 1080 col_and_col_group.colgroup = col; |
1091 col_and_col_group.adjoins_end_border_of_col_group = is_at_end_edge; | 1081 col_and_col_group.adjoins_start_border_of_col_group = is_at_start_edge; |
1092 } else { | 1082 col_and_col_group.adjoins_end_border_of_col_group = is_at_end_edge; |
1093 col_and_col_group.col = column_layout_object; | 1083 } else { |
1094 col_and_col_group.colgroup = | 1084 col_and_col_group.col = col; |
1095 column_layout_object->EnclosingColumnGroup(); | 1085 col_and_col_group.colgroup = col->EnclosingColumnGroup(); |
1096 if (col_and_col_group.colgroup) { | 1086 if (col_and_col_group.colgroup) { |
1097 col_and_col_group.adjoins_start_border_of_col_group = | 1087 col_and_col_group.adjoins_start_border_of_col_group = |
1098 is_at_start_edge && !col_and_col_group.col->PreviousSibling(); | 1088 is_at_start_edge && !col->PreviousSibling(); |
1099 col_and_col_group.adjoins_end_border_of_col_group = | 1089 col_and_col_group.adjoins_end_border_of_col_group = |
1100 is_at_end_edge && !col_and_col_group.col->NextSibling(); | 1090 is_at_end_edge && !col->NextSibling(); |
1101 } | |
1102 } | 1091 } |
1103 return col_and_col_group; | |
1104 } | 1092 } |
| 1093 |
| 1094 // Skip useless col objects that don't generate effective columns. |
| 1095 while (next_absolute_column_index >= next_col_absolute_column_index) { |
| 1096 if (next_col_absolute_column_index == next_absolute_column_index && |
| 1097 !col_and_col_group.adjoins_end_border_of_col_group && |
| 1098 col_and_col_group.colgroup == col->EnclosingColumnGroup()) { |
| 1099 // Special case: the effective column adjoins the end border of |
| 1100 // col_and_col_group.colgroup though it doesn't adjoin the end border of |
| 1101 // col_and_col_group.col. All subsequent cols of col_and_col_group.col |
| 1102 // don't generate new effective columns. |
| 1103 col_and_col_group.adjoins_end_border_of_col_group = true; |
| 1104 } |
| 1105 |
| 1106 col_absolute_column_index = next_col_absolute_column_index; |
| 1107 col = col->NextInnermostColumn(); |
| 1108 if (!col) |
| 1109 break; |
| 1110 next_col_absolute_column_index += col->Span(); |
| 1111 } |
| 1112 |
| 1113 absolute_column_index = next_absolute_column_index; |
| 1114 cols_at_effective_columns_->push_back(col_and_col_group); |
1105 } | 1115 } |
1106 return ColAndColGroup(); | |
1107 } | 1116 } |
1108 | 1117 |
1109 void LayoutTable::RecalcSections() const { | 1118 void LayoutTable::RecalcSections() const { |
1110 DCHECK(needs_section_recalc_); | 1119 DCHECK(needs_section_recalc_); |
1111 | 1120 |
1112 head_ = nullptr; | 1121 head_ = nullptr; |
1113 foot_ = nullptr; | 1122 foot_ = nullptr; |
1114 first_body_ = nullptr; | 1123 first_body_ = nullptr; |
1115 has_col_elements_ = false; | |
1116 | 1124 |
1117 // We need to get valid pointers to caption, head, foot and first body again | 1125 // We need to get valid pointers to caption, head, foot and first body again |
1118 LayoutObject* next_sibling; | 1126 LayoutObject* next_sibling; |
1119 for (LayoutObject* child = FirstChild(); child; child = next_sibling) { | 1127 for (LayoutObject* child = FirstChild(); child; child = next_sibling) { |
1120 next_sibling = child->NextSibling(); | 1128 next_sibling = child->NextSibling(); |
1121 switch (child->Style()->Display()) { | 1129 switch (child->Style()->Display()) { |
1122 case EDisplay::kTableColumn: | |
1123 case EDisplay::kTableColumnGroup: | |
1124 has_col_elements_ = true; | |
1125 break; | |
1126 case EDisplay::kTableHeaderGroup: | 1130 case EDisplay::kTableHeaderGroup: |
1127 if (child->IsTableSection()) { | 1131 if (child->IsTableSection()) { |
1128 LayoutTableSection* section = ToLayoutTableSection(child); | 1132 LayoutTableSection* section = ToLayoutTableSection(child); |
1129 if (!head_) | 1133 if (!head_) |
1130 head_ = section; | 1134 head_ = section; |
1131 else if (!first_body_) | 1135 else if (!first_body_) |
1132 first_body_ = section; | 1136 first_body_ = section; |
1133 section->RecalcCellsIfNeeded(); | 1137 section->RecalcCellsIfNeeded(); |
1134 } | 1138 } |
1135 break; | 1139 break; |
(...skipping 20 matching lines...) Expand all Loading... |
1156 } | 1160 } |
1157 } | 1161 } |
1158 | 1162 |
1159 // repair column count (addChild can grow it too much, because it always adds | 1163 // repair column count (addChild can grow it too much, because it always adds |
1160 // elements to the last row of a section) | 1164 // elements to the last row of a section) |
1161 unsigned max_cols = 0; | 1165 unsigned max_cols = 0; |
1162 for (LayoutObject* child = FirstChild(); child; | 1166 for (LayoutObject* child = FirstChild(); child; |
1163 child = child->NextSibling()) { | 1167 child = child->NextSibling()) { |
1164 if (child->IsTableSection()) { | 1168 if (child->IsTableSection()) { |
1165 LayoutTableSection* section = ToLayoutTableSection(child); | 1169 LayoutTableSection* section = ToLayoutTableSection(child); |
1166 unsigned section_cols = section->NumEffectiveColumns(); | 1170 unsigned section_cols = section->MaxNumEffectiveColumnsOfRows(); |
1167 if (section_cols > max_cols) | 1171 if (section_cols > max_cols) |
1168 max_cols = section_cols; | 1172 max_cols = section_cols; |
1169 } | 1173 } |
1170 } | 1174 } |
1171 | 1175 |
1172 effective_columns_.resize(max_cols); | 1176 effective_columns_.resize(max_cols); |
1173 effective_column_positions_.resize(max_cols + 1); | 1177 effective_column_positions_.resize(max_cols + 1); |
1174 no_cell_colspan_at_least_ = CalcNoCellColspanAtLeast(); | 1178 no_cell_colspan_at_least_ = CalcNoCellColspanAtLeast(); |
1175 | 1179 |
| 1180 InvalidateColsAtEffectiveColumns(); |
| 1181 |
1176 DCHECK(SelfNeedsLayout()); | 1182 DCHECK(SelfNeedsLayout()); |
1177 | 1183 |
1178 needs_section_recalc_ = false; | 1184 needs_section_recalc_ = false; |
1179 } | 1185 } |
1180 | 1186 |
1181 int LayoutTable::CalcBorderStart() const { | 1187 int LayoutTable::CalcBorderStart() const { |
1182 if (!ShouldCollapseBorders()) | 1188 if (!ShouldCollapseBorders()) |
1183 return LayoutBlock::BorderStart().ToInt(); | 1189 return LayoutBlock::BorderStart().ToInt(); |
1184 | 1190 |
1185 // Determined by the first cell of the first row. See the CSS 2.1 spec, | 1191 // Determined by the first cell of the first row. See the CSS 2.1 spec, |
1186 // section 17.6.2. | 1192 // section 17.6.2. |
1187 if (!NumEffectiveColumns()) | 1193 if (!NumEffectiveColumns()) |
1188 return 0; | 1194 return 0; |
1189 | 1195 |
1190 int border_width = 0; | 1196 int border_width = 0; |
1191 | 1197 |
1192 const BorderValue& table_start_border = Style()->BorderStart(); | 1198 const BorderValue& table_start_border = Style()->BorderStart(); |
1193 if (table_start_border.Style() == EBorderStyle::kHidden) | 1199 if (table_start_border.Style() == EBorderStyle::kHidden) |
1194 return 0; | 1200 return 0; |
1195 if (table_start_border.Style() > EBorderStyle::kHidden) | 1201 if (table_start_border.Style() > EBorderStyle::kHidden) |
1196 border_width = table_start_border.Width(); | 1202 border_width = table_start_border.Width(); |
1197 | 1203 |
1198 // TODO(dgrogan): This logic doesn't properly account for the first column in | 1204 // TODO(dgrogan): This logic doesn't properly account for the first column in |
1199 // the first column-group case. | 1205 // the first column-group case. |
1200 if (LayoutTableCol* column = | 1206 if (LayoutTableCol* column = |
1201 ColElementAtAbsoluteColumn(0).InnermostColOrColGroup()) { | 1207 ColAndColGroupAtEffectiveColumn(0).InnermostColOrColGroup()) { |
1202 // FIXME: We don't account for direction on columns and column groups. | 1208 // FIXME: We don't account for direction on columns and column groups. |
1203 const BorderValue& column_adjoining_border = column->Style()->BorderStart(); | 1209 const BorderValue& column_adjoining_border = column->Style()->BorderStart(); |
1204 if (column_adjoining_border.Style() == EBorderStyle::kHidden) | 1210 if (column_adjoining_border.Style() == EBorderStyle::kHidden) |
1205 return 0; | 1211 return 0; |
1206 if (column_adjoining_border.Style() > EBorderStyle::kHidden) | 1212 if (column_adjoining_border.Style() > EBorderStyle::kHidden) |
1207 border_width = | 1213 border_width = |
1208 std::max<int>(border_width, column_adjoining_border.Width()); | 1214 std::max<int>(border_width, column_adjoining_border.Width()); |
1209 } | 1215 } |
1210 | 1216 |
1211 if (const LayoutTableSection* top_non_empty_section = | 1217 if (const LayoutTableSection* top_non_empty_section = |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1259 const BorderValue& table_end_border = Style()->BorderEnd(); | 1265 const BorderValue& table_end_border = Style()->BorderEnd(); |
1260 if (table_end_border.Style() == EBorderStyle::kHidden) | 1266 if (table_end_border.Style() == EBorderStyle::kHidden) |
1261 return 0; | 1267 return 0; |
1262 if (table_end_border.Style() > EBorderStyle::kHidden) | 1268 if (table_end_border.Style() > EBorderStyle::kHidden) |
1263 border_width = table_end_border.Width(); | 1269 border_width = table_end_border.Width(); |
1264 | 1270 |
1265 unsigned end_column = NumEffectiveColumns() - 1; | 1271 unsigned end_column = NumEffectiveColumns() - 1; |
1266 | 1272 |
1267 // TODO(dgrogan): This logic doesn't properly account for the last column in | 1273 // TODO(dgrogan): This logic doesn't properly account for the last column in |
1268 // the last column-group case. | 1274 // the last column-group case. |
1269 if (LayoutTableCol* column = | 1275 if (LayoutTableCol* column = ColAndColGroupAtEffectiveColumn(end_column) |
1270 ColElementAtAbsoluteColumn(end_column).InnermostColOrColGroup()) { | 1276 .InnermostColOrColGroup()) { |
1271 // FIXME: We don't account for direction on columns and column groups. | 1277 // FIXME: We don't account for direction on columns and column groups. |
1272 const BorderValue& column_adjoining_border = column->Style()->BorderEnd(); | 1278 const BorderValue& column_adjoining_border = column->Style()->BorderEnd(); |
1273 if (column_adjoining_border.Style() == EBorderStyle::kHidden) | 1279 if (column_adjoining_border.Style() == EBorderStyle::kHidden) |
1274 return 0; | 1280 return 0; |
1275 if (column_adjoining_border.Style() > EBorderStyle::kHidden) | 1281 if (column_adjoining_border.Style() > EBorderStyle::kHidden) |
1276 border_width = | 1282 border_width = |
1277 std::max<int>(border_width, column_adjoining_border.Width()); | 1283 std::max<int>(border_width, column_adjoining_border.Width()); |
1278 } | 1284 } |
1279 | 1285 |
1280 if (const LayoutTableSection* top_non_empty_section = | 1286 if (const LayoutTableSection* top_non_empty_section = |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 r_above = r - 1; | 1510 r_above = r - 1; |
1505 } else { | 1511 } else { |
1506 section = SectionAbove(cell->Section(), kSkipEmptySections); | 1512 section = SectionAbove(cell->Section(), kSkipEmptySections); |
1507 if (section) { | 1513 if (section) { |
1508 DCHECK(section->NumRows()); | 1514 DCHECK(section->NumRows()); |
1509 r_above = section->NumRows() - 1; | 1515 r_above = section->NumRows() - 1; |
1510 } | 1516 } |
1511 } | 1517 } |
1512 | 1518 |
1513 // Look up the cell in the section's grid, which requires effective col index | 1519 // Look up the cell in the section's grid, which requires effective col index |
1514 if (section) { | 1520 if (section) |
1515 unsigned eff_col = | 1521 return section->PrimaryCellAt(r_above, cell->EffectiveColumnIndex()); |
1516 AbsoluteColumnToEffectiveColumn(cell->AbsoluteColumnIndex()); | |
1517 return section->PrimaryCellAt(r_above, eff_col); | |
1518 } | |
1519 return nullptr; | 1522 return nullptr; |
1520 } | 1523 } |
1521 | 1524 |
1522 LayoutTableCell* LayoutTable::CellBelow(const LayoutTableCell* cell) const { | 1525 LayoutTableCell* LayoutTable::CellBelow(const LayoutTableCell* cell) const { |
1523 RecalcSectionsIfNeeded(); | 1526 RecalcSectionsIfNeeded(); |
1524 | 1527 |
1525 // Find the section and row to look in | 1528 // Find the section and row to look in |
1526 unsigned r = cell->RowIndex() + cell->RowSpan() - 1; | 1529 unsigned r = cell->RowIndex() + cell->RowSpan() - 1; |
1527 LayoutTableSection* section = nullptr; | 1530 LayoutTableSection* section = nullptr; |
1528 unsigned r_below = 0; | 1531 unsigned r_below = 0; |
1529 if (r < cell->Section()->NumRows() - 1) { | 1532 if (r < cell->Section()->NumRows() - 1) { |
1530 // The cell is not in the last row, so use the next row in the section. | 1533 // The cell is not in the last row, so use the next row in the section. |
1531 section = cell->Section(); | 1534 section = cell->Section(); |
1532 r_below = r + 1; | 1535 r_below = r + 1; |
1533 } else { | 1536 } else { |
1534 section = SectionBelow(cell->Section(), kSkipEmptySections); | 1537 section = SectionBelow(cell->Section(), kSkipEmptySections); |
1535 if (section) | 1538 if (section) |
1536 r_below = 0; | 1539 r_below = 0; |
1537 } | 1540 } |
1538 | 1541 |
1539 // Look up the cell in the section's grid, which requires effective col index | 1542 // Look up the cell in the section's grid, which requires effective col index |
1540 if (section) { | 1543 if (section) |
1541 unsigned eff_col = | 1544 return section->PrimaryCellAt(r_below, cell->EffectiveColumnIndex()); |
1542 AbsoluteColumnToEffectiveColumn(cell->AbsoluteColumnIndex()); | |
1543 return section->PrimaryCellAt(r_below, eff_col); | |
1544 } | |
1545 return nullptr; | 1545 return nullptr; |
1546 } | 1546 } |
1547 | 1547 |
1548 LayoutTableCell* LayoutTable::CellBefore(const LayoutTableCell* cell) const { | 1548 LayoutTableCell* LayoutTable::CellBefore(const LayoutTableCell* cell) const { |
1549 RecalcSectionsIfNeeded(); | 1549 RecalcSectionsIfNeeded(); |
1550 | 1550 |
1551 LayoutTableSection* section = cell->Section(); | 1551 unsigned eff_col = cell->EffectiveColumnIndex(); |
1552 unsigned eff_col = | |
1553 AbsoluteColumnToEffectiveColumn(cell->AbsoluteColumnIndex()); | |
1554 if (!eff_col) | 1552 if (!eff_col) |
1555 return nullptr; | 1553 return nullptr; |
1556 | 1554 |
1557 // If we hit a colspan back up to a real cell. | 1555 // If we hit a colspan back up to a real cell. |
1558 return section->PrimaryCellAt(cell->RowIndex(), eff_col - 1); | 1556 return cell->Section()->PrimaryCellAt(cell->RowIndex(), eff_col - 1); |
1559 } | 1557 } |
1560 | 1558 |
1561 LayoutTableCell* LayoutTable::CellAfter(const LayoutTableCell* cell) const { | 1559 LayoutTableCell* LayoutTable::CellAfter(const LayoutTableCell* cell) const { |
1562 RecalcSectionsIfNeeded(); | 1560 RecalcSectionsIfNeeded(); |
1563 | 1561 |
1564 unsigned eff_col = AbsoluteColumnToEffectiveColumn( | 1562 return cell->Section()->PrimaryCellAt( |
1565 cell->AbsoluteColumnIndex() + cell->ColSpan()); | 1563 cell->RowIndex(), cell->EffectiveColumnIndexOfCellAfter()); |
1566 return cell->Section()->PrimaryCellAt(cell->RowIndex(), eff_col); | |
1567 } | 1564 } |
1568 | 1565 |
1569 int LayoutTable::BaselinePosition(FontBaseline baseline_type, | 1566 int LayoutTable::BaselinePosition(FontBaseline baseline_type, |
1570 bool first_line, | 1567 bool first_line, |
1571 LineDirectionMode direction, | 1568 LineDirectionMode direction, |
1572 LinePositionMode line_position_mode) const { | 1569 LinePositionMode line_position_mode) const { |
1573 DCHECK_EQ(line_position_mode, kPositionOnContainingLine); | 1570 DCHECK_EQ(line_position_mode, kPositionOnContainingLine); |
1574 int baseline = FirstLineBoxBaseline(); | 1571 int baseline = FirstLineBoxBaseline(); |
1575 if (baseline != -1) { | 1572 if (baseline != -1) { |
1576 if (IsInline()) | 1573 if (IsInline()) |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1760 } | 1757 } |
1761 | 1758 |
1762 LayoutUnit LayoutTable::PaddingRight() const { | 1759 LayoutUnit LayoutTable::PaddingRight() const { |
1763 if (ShouldCollapseBorders()) | 1760 if (ShouldCollapseBorders()) |
1764 return LayoutUnit(); | 1761 return LayoutUnit(); |
1765 | 1762 |
1766 return LayoutBlock::PaddingRight(); | 1763 return LayoutBlock::PaddingRight(); |
1767 } | 1764 } |
1768 | 1765 |
1769 } // namespace blink | 1766 } // namespace blink |
OLD | NEW |