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