1 /*
2  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3  *           (C) 1997 Torben Weis (weis@kde.org)
4  *           (C) 1998 Waldo Bastian (bastian@kde.org)
5  *           (C) 1999 Lars Knoll (knoll@kde.org)
6  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
7  * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010 Apple Inc.
8  *               All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 
26 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_H_
27 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_H_
28 
29 #include <memory>
30 #include "third_party/blink/renderer/core/core_export.h"
31 #include "third_party/blink/renderer/core/css/css_property_names.h"
32 #include "third_party/blink/renderer/core/layout/layout_block.h"
33 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
34 #include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h"
35 #include "third_party/blink/renderer/platform/wtf/vector.h"
36 
37 namespace blink {
38 
39 class LayoutNGTableSectionInterface;
40 class LayoutTableCol;
41 class LayoutTableCaption;
42 class LayoutTableCell;
43 class LayoutTableSection;
44 class TableLayoutAlgorithm;
45 
46 enum TableHeightChangingValue { kTableHeightNotChanging, kTableHeightChanging };
47 
48 // LayoutTable is the LayoutObject associated with
49 // display: table or inline-table.
50 //
51 // LayoutTable is the coordinator for determining the overall table structure.
52 // The reason is that LayoutTableSection children have a local view over what
53 // their structure is but don't account for other LayoutTableSection. Thus
54 // LayoutTable helps keep consistency across LayoutTableSection. See e.g.
55 // |m_effectiveColumns| below.
56 //
57 // LayoutTable expects only 3 types of children:
58 // - zero or more LayoutTableCol
59 // - zero or more LayoutTableCaption
60 // - zero or more LayoutTableSection
61 // This is aligned with what HTML5 expects:
62 // https://html.spec.whatwg.org/C/#the-table-element
63 // with one difference: we allow more than one caption as we follow what
64 // CSS expects (https://bugs.webkit.org/show_bug.cgi?id=69773).
65 // Those expectations are enforced by LayoutTable::addChild, that wraps unknown
66 // children into an anonymous LayoutTableSection. This is what the "generate
67 // missing child wrapper" step in CSS mandates in
68 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes.
69 //
70 // LayoutTable assumes a pretty strict structure that is mandated by CSS:
71 // (note that this structure in HTML is enforced by the HTML5 Parser).
72 //
73 //                 LayoutTable
74 //                 |        |
75 //  LayoutTableSection    LayoutTableCaption
76 //                 |
77 //      LayoutTableRow
78 //                 |
79 //     LayoutTableCell
80 //
81 // This means that we have to generate some anonymous table wrappers in order to
82 // satisfy the structure. See again
83 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes.
84 // The anonymous table wrappers are inserted in LayoutTable::addChild,
85 // LayoutTableSection::addChild, LayoutTableRow::addChild and
86 // LayoutObject::addChild.
87 //
88 // Note that this yields to interesting issues in the insertion code. The DOM
89 // code is unaware of the anonymous LayoutObjects and thus can insert
90 // LayoutObjects into a different part of the layout tree. An example is:
91 //
92 // <!DOCTYPE html>
93 // <style>
94 // tablerow { display: table-row; }
95 // tablecell { display: table-cell; border: 5px solid purple; }
96 // </style>
97 // <tablerow id="firstRow">
98 //     <tablecell>Short first row.</tablecell>
99 // </tablerow>
100 // <tablecell id="cell">Long second row, shows the table structure.</tablecell>
101 //
102 // The page generates a single anonymous table (LayoutTable) and table row group
103 // (LayoutTableSection) to wrap the <tablerow> (#firstRow) and an anonymous
104 // table row (LayoutTableRow) for the second <tablecell>.
105 // It is possible for JavaScript to insert a new element between these 2
106 // <tablecell> (using Node.insertBefore), requiring us to split the anonymous
107 // table (or the anonymous table row group) in 2. Also note that even
108 // though the second <tablecell> and <tablerow> are siblings in the DOM tree,
109 // they are not in the layout tree.
110 //
111 //
112 // Note about absolute column index vs effective column index:
113 //
114 // To save memory at the expense of massive code complexity, the code tries
115 // to coalesce columns. This means that we try to the wider column grouping
116 // seen over the LayoutTableSections.
117 //
118 // Note that this is also a defensive pattern as <td colspan="6666666666">
119 // only allocates a single entry in this Vector. This argument is weak
120 // though as we cap colspans in HTMLTableCellElement.
121 //
122 // The following example would have 2 entries [ 3, 2 ] in effectiveColumns():
123 // <table>
124 //   <tr>
125 //     <td colspan="3"></td>
126 //     <td colspan="2"></td>
127 //   </tr>
128 // </table>
129 //
130 // Columns can be split if we add a row with a different colspan structure.
131 // See splitEffectiveColumn() and appendEffectiveColumn() for operations
132 // over effectiveColumns() and effectiveColumnPositions().
133 //
134 // See absoluteColumnToEffectiveColumn() for converting an absolute column
135 // index into an index into effectiveColumns() and effectiveColumnPositions().
136 
137 class CORE_EXPORT LayoutTable final : public LayoutBlock,
138                                       public LayoutNGTableInterface {
139  public:
140   explicit LayoutTable(Element*);
141   ~LayoutTable() override;
142 
143   // Per CSS 3 writing-mode: "The first and second values of the
144   // 'border-spacing' property represent spacing between columns and rows
145   // respectively, not necessarily the horizontal and vertical spacing
146   // respectively".
HBorderSpacing()147   int16_t HBorderSpacing() const final {
148     NOT_DESTROYED();
149     return h_spacing_;
150   }
VBorderSpacing()151   int16_t VBorderSpacing() const final {
152     NOT_DESTROYED();
153     return v_spacing_;
154   }
155 
ShouldCollapseBorders()156   bool ShouldCollapseBorders() const final {
157     NOT_DESTROYED();
158     return StyleRef().BorderCollapse() == EBorderCollapse::kCollapse;
159   }
160 
161   LayoutUnit BorderLeft() const override;
162   LayoutUnit BorderRight() const override;
163   LayoutUnit BorderTop() const override;
164   LayoutUnit BorderBottom() const override;
165 
166   void AddChild(LayoutObject* child,
167                 LayoutObject* before_child = nullptr) override;
168 
169   struct ColumnStruct {
170     DISALLOW_NEW();
spanColumnStruct171     explicit ColumnStruct(unsigned initial_span = 1) : span(initial_span) {}
172 
173     unsigned span;
174   };
175 
ForceSectionsRecalc()176   void ForceSectionsRecalc() final {
177     NOT_DESTROYED();
178     SetNeedsSectionRecalc();
179     RecalcSections();
180   }
181 
EffectiveColumns()182   const Vector<ColumnStruct>& EffectiveColumns() const {
183     NOT_DESTROYED();
184     return effective_columns_;
185   }
EffectiveColumnPositions()186   const Vector<int>& EffectiveColumnPositions() const {
187     NOT_DESTROYED();
188     return effective_column_positions_;
189   }
SetEffectiveColumnPosition(unsigned index,int position)190   void SetEffectiveColumnPosition(unsigned index, int position) {
191     NOT_DESTROYED();
192     // Note that if our horizontal border-spacing changed, our position will
193     // change but not our column's width. In practice, horizontal border-spacing
194     // won't change often.
195     column_logical_width_changed_ |=
196         effective_column_positions_[index] != position;
197     effective_column_positions_[index] = position;
198   }
199 
Header()200   LayoutTableSection* Header() const {
201     NOT_DESTROYED();
202     DCHECK(!NeedsSectionRecalc());
203     return head_;
204   }
Footer()205   LayoutTableSection* Footer() const {
206     NOT_DESTROYED();
207     DCHECK(!NeedsSectionRecalc());
208     return foot_;
209   }
FirstBody()210   LayoutTableSection* FirstBody() const {
211     NOT_DESTROYED();
212     DCHECK(!NeedsSectionRecalc());
213     return first_body_;
214   }
215 
SetRowOffsetFromRepeatingHeader(LayoutUnit offset)216   void SetRowOffsetFromRepeatingHeader(LayoutUnit offset) {
217     NOT_DESTROYED();
218     row_offset_from_repeating_header_ = offset;
219   }
RowOffsetFromRepeatingHeader()220   LayoutUnit RowOffsetFromRepeatingHeader() const final {
221     NOT_DESTROYED();
222     return row_offset_from_repeating_header_;
223   }
224 
SetRowOffsetFromRepeatingFooter(LayoutUnit offset)225   void SetRowOffsetFromRepeatingFooter(LayoutUnit offset) {
226     NOT_DESTROYED();
227     row_offset_from_repeating_footer_ = offset;
228   }
RowOffsetFromRepeatingFooter()229   LayoutUnit RowOffsetFromRepeatingFooter() const final {
230     NOT_DESTROYED();
231     return row_offset_from_repeating_footer_;
232   }
233 
234   // These functions return nullptr if the table has no sections.
235   LayoutTableSection* TopSection() const;
236   LayoutTableSection* BottomSection() const;
237 
238   // These functions return nullptr if the table has no non-empty sections.
239   LayoutTableSection* TopNonEmptySection() const;
240   LayoutTableSection* BottomNonEmptySection() const;
241 
LastEffectiveColumnIndex()242   unsigned LastEffectiveColumnIndex() const {
243     NOT_DESTROYED();
244     return NumEffectiveColumns() - 1;
245   }
246 
247   void SplitEffectiveColumn(unsigned index, unsigned first_span);
248   void AppendEffectiveColumn(unsigned span);
NumEffectiveColumns()249   unsigned NumEffectiveColumns() const {
250     NOT_DESTROYED();
251     return effective_columns_.size();
252   }
SpanOfEffectiveColumn(unsigned effective_column_index)253   unsigned SpanOfEffectiveColumn(unsigned effective_column_index) const {
254     NOT_DESTROYED();
255     return effective_columns_[effective_column_index].span;
256   }
257 
AbsoluteColumnToEffectiveColumn(unsigned absolute_column_index)258   unsigned AbsoluteColumnToEffectiveColumn(
259       unsigned absolute_column_index) const final {
260     NOT_DESTROYED();
261     if (absolute_column_index < no_cell_colspan_at_least_)
262       return absolute_column_index;
263 
264     unsigned effective_column = no_cell_colspan_at_least_;
265     unsigned num_columns = NumEffectiveColumns();
266     for (unsigned c = no_cell_colspan_at_least_;
267          effective_column < num_columns &&
268          c + effective_columns_[effective_column].span - 1 <
269              absolute_column_index;
270          ++effective_column)
271       c += effective_columns_[effective_column].span;
272     return effective_column;
273   }
274 
EffectiveColumnToAbsoluteColumn(unsigned effective_column_index)275   unsigned EffectiveColumnToAbsoluteColumn(
276       unsigned effective_column_index) const {
277     NOT_DESTROYED();
278     if (effective_column_index < no_cell_colspan_at_least_)
279       return effective_column_index;
280 
281     unsigned c = no_cell_colspan_at_least_;
282     for (unsigned i = no_cell_colspan_at_least_; i < effective_column_index;
283          i++)
284       c += effective_columns_[i].span;
285     return c;
286   }
287 
BorderSpacingInRowDirection()288   LayoutUnit BorderSpacingInRowDirection() const {
289     NOT_DESTROYED();
290     if (unsigned effective_column_count = NumEffectiveColumns())
291       return static_cast<LayoutUnit>(effective_column_count + 1) *
292              HBorderSpacing();
293 
294     return LayoutUnit();
295   }
296 
297   // The collapsing border model dissallows paddings on table, which is why we
298   // override those functions.
299   // See http://www.w3.org/TR/CSS2/tables.html#collapsing-borders.
300   LayoutUnit PaddingTop() const override;
301   LayoutUnit PaddingBottom() const override;
302   LayoutUnit PaddingLeft() const override;
303   LayoutUnit PaddingRight() const override;
304 
BordersPaddingAndSpacingInRowDirection()305   LayoutUnit BordersPaddingAndSpacingInRowDirection() const {
306     NOT_DESTROYED();
307     // 'border-spacing' only applies to separate borders (see 17.6.1 The
308     // separated borders model).
309     return BorderStart() + BorderEnd() +
310            (ShouldCollapseBorders() ? LayoutUnit()
311                                     : (PaddingStart() + PaddingEnd() +
312                                        BorderSpacingInRowDirection()));
313   }
314 
315   // Return the first column or column-group.
316   LayoutTableCol* FirstColumn() const;
317 
318   struct ColAndColGroup {
ColAndColGroupColAndColGroup319     ColAndColGroup()
320         : col(nullptr),
321           colgroup(nullptr),
322           adjoins_start_border_of_col_group(false),
323           adjoins_end_border_of_col_group(false) {}
324     LayoutTableCol* col;
325     LayoutTableCol* colgroup;
326     bool adjoins_start_border_of_col_group;
327     bool adjoins_end_border_of_col_group;
InnermostColOrColGroupColAndColGroup328     LayoutTableCol* InnermostColOrColGroup() { return col ? col : colgroup; }
329   };
ColElementAtAbsoluteColumn(unsigned absolute_column_index)330   ColAndColGroup ColElementAtAbsoluteColumn(
331       unsigned absolute_column_index) const {
332     NOT_DESTROYED();
333     // The common case is to not have col/colgroup elements, make that case
334     // fast.
335     if (!has_col_elements_)
336       return ColAndColGroup();
337     return SlowColElementAtAbsoluteColumn(absolute_column_index);
338   }
HasColElements()339   bool HasColElements() const final {
340     NOT_DESTROYED();
341     return has_col_elements_;
342   }
343 
NeedsSectionRecalc()344   bool NeedsSectionRecalc() const {
345     NOT_DESTROYED();
346     return needs_section_recalc_;
347   }
SetNeedsSectionRecalc()348   void SetNeedsSectionRecalc() {
349     NOT_DESTROYED();
350     if (DocumentBeingDestroyed())
351       return;
352     // For all we know, sections may have been deleted at this point. Don't
353     // keep pointers dangling around.
354     head_ = nullptr;
355     foot_ = nullptr;
356     first_body_ = nullptr;
357 
358     needs_section_recalc_ = true;
359     SetNeedsLayoutAndFullPaintInvalidation(
360         layout_invalidation_reason::kTableChanged);
361 
362     // Grid structure affects cell adjacence relationships which affect
363     // conflict resolution of collapsed borders.
364     InvalidateCollapsedBorders();
365   }
366 
367   LayoutTableSection* SectionAbove(
368       const LayoutTableSection*,
369       SkipEmptySectionsValue = kDoNotSkipEmptySections) const;
370   LayoutTableSection* SectionBelow(
371       const LayoutTableSection*,
372       SkipEmptySectionsValue = kDoNotSkipEmptySections) const;
373 
374   // Returns the adjacent cell to the logical top, logical bottom, logical left
375   // and logical right, respectively, of the given cell, in the table's
376   // direction. If there are multiple adjacent cells in the direction due to row
377   // or col spans, returns the primary LayoutTableCell of the first (in DOM
378   // order) adjacent TableGridCell in the direction. Returns nullptr if there
379   // are no adjacent cells in the direction.
380   LayoutTableCell* CellAbove(const LayoutTableCell&) const;
381   LayoutTableCell* CellBelow(const LayoutTableCell&) const;
382   LayoutTableCell* CellPreceding(const LayoutTableCell&) const;
383   LayoutTableCell* CellFollowing(const LayoutTableCell&) const;
384 
385   void InvalidateCollapsedBorders();
386   void InvalidateCollapsedBordersForAllCellsIfNeeded();
387 
HasCollapsedBorders()388   bool HasCollapsedBorders() const final {
389     NOT_DESTROYED();
390     DCHECK(collapsed_borders_valid_);
391     return has_collapsed_borders_;
392   }
NeedsAdjustCollapsedBorderJoints()393   bool NeedsAdjustCollapsedBorderJoints() const {
394     NOT_DESTROYED();
395     DCHECK(collapsed_borders_valid_);
396     return needs_adjust_collapsed_border_joints_;
397   }
398 
HasSections()399   bool HasSections() const {
400     NOT_DESTROYED();
401     return Header() || Footer() || FirstBody();
402   }
403 
RecalcSectionsIfNeeded()404   void RecalcSectionsIfNeeded() const final {
405     NOT_DESTROYED();
406     if (needs_section_recalc_)
407       RecalcSections();
408   }
409 
410   LayoutBox* CreateAnonymousBoxWithSameTypeAs(
411       const LayoutObject* parent) const override;
412 
413   void AddCaption(const LayoutTableCaption*);
414   void RemoveCaption(const LayoutTableCaption*);
415   void AddColumn(const LayoutTableCol*);
416   void RemoveColumn(const LayoutTableCol*);
417 
418   void PaintBoxDecorationBackground(
419       const PaintInfo&,
420       const PhysicalOffset& paint_offset) const final;
421 
422   void PaintMask(const PaintInfo&,
423                  const PhysicalOffset& paint_offset) const final;
424 
425   void SubtractCaptionRect(PhysicalRect&) const;
426 
427   bool IsLogicalWidthAuto() const;
428 
GetName()429   const char* GetName() const override {
430     NOT_DESTROYED();
431     return "LayoutTable";
432   }
433 
434   // Whether a table has opaque foreground depends on many factors, e.g. border
435   // spacing, missing cells, etc. For simplicity, just conservatively assume
436   // foreground of all tables are not opaque.
ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect &,unsigned)437   bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&,
438                                          unsigned) const override {
439     NOT_DESTROYED();
440     return false;
441   }
442 
443   enum WhatToMarkAllCells { kMarkDirtyOnly, kMarkDirtyAndNeedsLayout };
444   void MarkAllCellsWidthsDirtyAndOrNeedsLayout(WhatToMarkAllCells);
445 
446   bool IsAbsoluteColumnCollapsed(unsigned absolute_column_index) const;
447 
IsAnyColumnEverCollapsed()448   bool IsAnyColumnEverCollapsed() const {
449     NOT_DESTROYED();
450     return is_any_column_ever_collapsed_;
451   }
452 
453   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
454   void SimplifiedNormalFlowLayout() override;
455 
456   RecalcLayoutOverflowResult RecalcLayoutOverflow() final;
457   void RecalcVisualOverflow() final;
458 
459   void EnsureIsReadyForPaintInvalidation() override;
460   void InvalidatePaint(const PaintInvalidatorContext&) const override;
461   void ColumnStructureChanged();
462 
463   // LayoutNGTableInterface methods start.
464 
ToLayoutNGTableInterface()465   const LayoutNGTableInterface* ToLayoutNGTableInterface() const final {
466     NOT_DESTROYED();
467     return this;
468   }
ToLayoutObject()469   const LayoutObject* ToLayoutObject() const final {
470     NOT_DESTROYED();
471     return this;
472   }
ToMutableLayoutObject()473   LayoutObject* ToMutableLayoutObject() final {
474     NOT_DESTROYED();
475     return this;
476   }
IsFixedTableLayout()477   bool IsFixedTableLayout() const final {
478     NOT_DESTROYED();
479     return StyleRef().IsFixedTableLayout();
480   }
481   LayoutNGTableSectionInterface* FirstBodyInterface() const final;
482   LayoutNGTableSectionInterface* TopSectionInterface() const final;
483   LayoutNGTableSectionInterface* TopNonEmptySectionInterface() const final;
484   LayoutNGTableSectionInterface* BottomSectionInterface() const final;
485   LayoutNGTableSectionInterface* BottomNonEmptySectionInterface() const final;
486   LayoutNGTableSectionInterface* SectionBelowInterface(
487       const LayoutNGTableSectionInterface*,
488       SkipEmptySectionsValue) const final;
489   bool IsFirstCell(const LayoutNGTableCellInterface&) const final;
490 
491   // LayoutNGTableInterface methods end.
492 
493  private:
IsOfType(LayoutObjectType type)494   bool IsOfType(LayoutObjectType type) const override {
495     NOT_DESTROYED();
496     return type == kLayoutObjectTable || LayoutBlock::IsOfType(type);
497   }
498 
499   void PaintObject(const PaintInfo&,
500                    const PhysicalOffset& paint_offset) const override;
501   void UpdateLayout() override;
502   MinMaxSizes ComputeIntrinsicLogicalWidths() const override;
503   MinMaxSizes PreferredLogicalWidths() const override;
504   bool NodeAtPoint(HitTestResult&,
505                    const HitTestLocation&,
506                    const PhysicalOffset& accumulated_offset,
507                    HitTestAction) override;
508 
509   LayoutUnit BaselinePosition(
510       FontBaseline,
511       bool first_line,
512       LineDirectionMode,
513       LinePositionMode = kPositionOnContainingLine) const override;
514   LayoutUnit FirstLineBoxBaseline() const override;
515   LayoutUnit InlineBlockBaseline(LineDirectionMode) const override;
516 
517   ColAndColGroup SlowColElementAtAbsoluteColumn(unsigned col) const;
518 
519   void UpdateColumnCache() const;
520   void InvalidateCachedColumns();
521 
522   void UpdateLogicalWidth() override;
523 
524   LayoutUnit ConvertStyleLogicalWidthToComputedWidth(
525       const Length& style_logical_width,
526       LayoutUnit available_width) const;
527   LayoutUnit ConvertStyleLogicalHeightToComputedHeight(
528       const Length& style_logical_height) const;
529 
530   PhysicalRect OverflowClipRect(const PhysicalOffset& location,
531                                 OverlayScrollbarClipBehavior =
532                                     kIgnoreOverlayScrollbarSize) const override;
533 
534   void ComputeVisualOverflow(bool recompute_floats) final;
535 
536   void AddVisualOverflowFromChildren();
537   void AddLayoutOverflowFromChildren() override;
538 
539   void RecalcSections() const;
540 
541   void UpdateCollapsedOuterBorders() const;
542 
543   void LayoutCaption(LayoutTableCaption&, SubtreeLayoutScope&);
544   void LayoutSection(LayoutTableSection&,
545                      SubtreeLayoutScope&,
546                      LayoutUnit logical_left,
547                      TableHeightChangingValue);
548 
549   // If any columns are collapsed, populates given vector with how much width is
550   // collapsed in each column. If no columns are collapsed, given vector remains
551   // empty. Logical width of table is adjusted.
552   void AdjustWidthsForCollapsedColumns(Vector<int>&);
553 
554   // Return the logical height based on the height, min-height and max-height
555   // properties from CSS. Will return 0 if auto.
556   LayoutUnit LogicalHeightFromStyle() const;
557 
558   void DistributeExtraLogicalHeight(int extra_logical_height);
559 
SetIsAnyColumnEverCollapsed()560   void SetIsAnyColumnEverCollapsed() {
561     NOT_DESTROYED();
562     is_any_column_ever_collapsed_ = true;
563   }
564 
565   // TODO(layout-dev): All mutables in this class are lazily updated by
566   // recalcSections() which is called by various getter methods (e.g.
567   // borderBefore(), borderAfter()).
568   // They allow dirty layout even after DocumentLifecycle::LayoutClean which
569   // seems not proper. crbug.com/538236.
570 
571   // Holds spans (number of absolute columns) of effective columns.
572   // See "absolute column index vs effective column index" in comments of
573   // LayoutTable.
574   mutable Vector<ColumnStruct> effective_columns_;
575 
576   // Holds the logical layout positions of effective columns, and the last item
577   // (whose index is numEffectiveColumns()) holds the position of the imaginary
578   // column after the last column.
579   // Because of the last item, m_effectiveColumnPositions.size() is always
580   // numEffectiveColumns() + 1.
581   mutable Vector<int> effective_column_positions_;
582 
583   // The captions associated with this object.
584   mutable Vector<LayoutTableCaption*> captions_;
585 
586   // Holds pointers to LayoutTableCol objects for <col>s and <colgroup>s under
587   // this table.
588   // There is no direct relationship between the size of and index into this
589   // vector and those of m_effectiveColumns because they hold different things.
590   mutable Vector<LayoutTableCol*> column_layout_objects_;
591 
592   mutable LayoutTableSection* head_;
593   mutable LayoutTableSection* foot_;
594   mutable LayoutTableSection* first_body_;
595 
596   // The layout algorithm used by this table.
597   //
598   // CSS 2.1 defines 2 types of table layouts toggled with 'table-layout':
599   // fixed (TableLayoutAlgorithmFixed) and auto (TableLayoutAlgorithmAuto).
600   // See http://www.w3.org/TR/CSS21/tables.html#width-layout.
601   //
602   // The layout algorithm is delegated to TableLayoutAlgorithm. This enables
603   // changing 'table-layout' without having to reattach the <table>.
604   //
605   // As the algorithm is dependent on the style, this field is nullptr before
606   // the first style is applied in styleDidChange().
607   std::unique_ptr<TableLayoutAlgorithm> table_layout_;
608 
609   // Collapsed borders are SUPER EXPENSIVE to compute. The reason is that we
610   // need to compare a cells border against all the adjoining cells, rows,
611   // row groups, column, column groups and table. Thus we cache the values in
612   // LayoutTableCells and some status here.
613   bool collapsed_borders_valid_ : 1;
614   bool has_collapsed_borders_ : 1;
615   bool needs_adjust_collapsed_border_joints_ : 1;
616   bool needs_invalidate_collapsed_borders_for_all_cells_ : 1;
617   mutable bool collapsed_outer_borders_valid_ : 1;
618 
619   // Whether any column in the table section is or has been collapsed.
620   bool is_any_column_ever_collapsed_ : 1;
621 
622   mutable bool has_col_elements_ : 1;
623   mutable bool needs_section_recalc_ : 1;
624 
625   bool column_logical_width_changed_ : 1;
626   // This flag indicates whether any columns (with or without fixed widths) have
627   // been added or removed since the last layout. If they have, then the true
628   // size of the cell contents needs to be determined with a full layout before
629   // the layout cache is updated. The layout cache can be invalid when layout is
630   // valid (e.g. if the table is being painted for the first time).
631   mutable bool column_structure_changed_ : 1;
632   mutable bool column_layout_objects_valid_ : 1;
633   mutable unsigned no_cell_colspan_at_least_;
CalcNoCellColspanAtLeast()634   unsigned CalcNoCellColspanAtLeast() const {
635     NOT_DESTROYED();
636     for (unsigned c = 0; c < NumEffectiveColumns(); c++) {
637       if (effective_columns_[c].span > 1)
638         return c;
639     }
640     return NumEffectiveColumns();
641   }
642 
LogicalCollapsedOuterBorderToPhysical()643   LogicalToPhysical<unsigned> LogicalCollapsedOuterBorderToPhysical() const {
644     NOT_DESTROYED();
645     return LogicalToPhysical<unsigned>(
646         StyleRef().GetWritingDirection(), collapsed_outer_border_start_,
647         collapsed_outer_border_end_, collapsed_outer_border_before_,
648         collapsed_outer_border_after_);
649   }
650 
651   int16_t h_spacing_;
652   int16_t v_spacing_;
653 
654   // See UpdateCollapsedOuterBorders().
655   mutable unsigned collapsed_outer_border_start_;
656   mutable unsigned collapsed_outer_border_end_;
657   mutable unsigned collapsed_outer_border_before_;
658   mutable unsigned collapsed_outer_border_after_;
659   mutable unsigned collapsed_outer_border_start_overflow_;
660   mutable unsigned collapsed_outer_border_end_overflow_;
661 
662   LayoutUnit row_offset_from_repeating_header_;
663   LayoutUnit row_offset_from_repeating_footer_;
664   LayoutUnit old_available_logical_height_;
665 };
666 
TopSection()667 inline LayoutTableSection* LayoutTable::TopSection() const {
668   DCHECK(!NeedsSectionRecalc());
669   if (head_)
670     return head_;
671   if (first_body_)
672     return first_body_;
673   return foot_;
674 }
675 
676 // To<LayoutTable>() helper.
677 template <>
678 struct DowncastTraits<LayoutTable> {
679   static bool AllowFrom(const LayoutObject& object) { return object.IsTable(); }
680 };
681 
682 }  // namespace blink
683 
684 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_H_
685