Tighten our checks for needsSectionRecalc in RenderTable
[WebKit-https.git] / Source / WebCore / rendering / RenderTable.h
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. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #ifndef RenderTable_h
26 #define RenderTable_h
27
28 #include "CSSPropertyNames.h"
29 #include "CollapsedBorderValue.h"
30 #include "RenderBlock.h"
31 #include <wtf/Vector.h>
32
33 namespace WebCore {
34
35 class RenderTableCol;
36 class RenderTableCell;
37 class RenderTableSection;
38 class TableLayout;
39
40 enum SkipEmptySectionsValue { DoNotSkipEmptySections, SkipEmptySections };
41
42 class RenderTable : public RenderBlock {
43 public:
44     explicit RenderTable(Node*);
45     virtual ~RenderTable();
46
47     LayoutUnit getColumnPos(unsigned col) const { return m_columnPos[col]; }
48
49     int hBorderSpacing() const { return m_hSpacing; }
50     int vBorderSpacing() const { return m_vSpacing; }
51     
52     bool collapseBorders() const { return style()->borderCollapse(); }
53
54     LayoutUnit borderStart() const { return m_borderStart; }
55     LayoutUnit borderEnd() const { return m_borderEnd; }
56     LayoutUnit borderBefore() const;
57     LayoutUnit borderAfter() const;
58
59     LayoutUnit borderLeft() const
60     {
61         if (style()->isHorizontalWritingMode())
62             return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
63         return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
64     }
65
66     LayoutUnit borderRight() const
67     {
68         if (style()->isHorizontalWritingMode())
69             return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
70         return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
71     }
72
73     LayoutUnit borderTop() const
74     {
75         if (style()->isHorizontalWritingMode())
76             return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
77         return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
78     }
79
80     LayoutUnit borderBottom() const
81     {
82         if (style()->isHorizontalWritingMode())
83             return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
84         return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
85     }
86
87     Color bgColor() const { return style()->visitedDependentColor(CSSPropertyBackgroundColor); }
88
89     LayoutUnit outerBorderBefore() const;
90     LayoutUnit outerBorderAfter() const;
91     LayoutUnit outerBorderStart() const;
92     LayoutUnit outerBorderEnd() const;
93
94     LayoutUnit outerBorderLeft() const
95     {
96         if (style()->isHorizontalWritingMode())
97             return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
98         return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
99     }
100
101     LayoutUnit outerBorderRight() const
102     {
103         if (style()->isHorizontalWritingMode())
104             return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
105         return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
106     }
107
108     LayoutUnit outerBorderTop() const
109     {
110         if (style()->isHorizontalWritingMode())
111             return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
112         return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
113     }
114
115     LayoutUnit outerBorderBottom() const
116     {
117         if (style()->isHorizontalWritingMode())
118             return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
119         return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
120     }
121
122     LayoutUnit calcBorderStart() const;
123     LayoutUnit calcBorderEnd() const;
124     void recalcBordersInRowDirection();
125
126     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
127
128     struct ColumnStruct {
129         ColumnStruct()
130             : span(1)
131         {
132         }
133
134         unsigned span;
135     };
136
137     Vector<ColumnStruct>& columns() { return m_columns; }
138     Vector<LayoutUnit>& columnPositions() { return m_columnPos; }
139     RenderTableSection* header() const { ASSERT(!needsSectionRecalc()); return m_header; }
140     RenderTableSection* footer() const { ASSERT(!needsSectionRecalc()); return m_footer; }
141     RenderTableSection* firstBody() const { ASSERT(!needsSectionRecalc()); return m_firstBody; }
142
143     // This function returns 0 if the table has no section.
144     RenderTableSection* topSection() const;
145
146     // This function returns 0 if the table has no non-empty sections.
147     RenderTableSection* topNonEmptySection() const;
148
149     void splitColumn(unsigned position, unsigned firstSpan);
150     void appendColumn(unsigned span);
151     unsigned numEffCols() const { return m_columns.size(); }
152     unsigned spanOfEffCol(unsigned effCol) const { return m_columns[effCol].span; }
153     
154     unsigned colToEffCol(unsigned column) const
155     {
156         unsigned effColumn = 0;
157         unsigned numColumns = numEffCols();
158         for (unsigned c = 0; effColumn < numColumns && c + m_columns[effColumn].span - 1 < column; ++effColumn)
159             c += m_columns[effColumn].span;
160         return effColumn;
161     }
162     
163     unsigned effColToCol(unsigned effCol) const
164     {
165         unsigned c = 0;
166         for (unsigned i = 0; i < effCol; i++)
167             c += m_columns[i].span;
168         return c;
169     }
170
171     LayoutUnit bordersPaddingAndSpacingInRowDirection() const
172     {
173         return borderStart() + borderEnd() +
174                (collapseBorders() ? 0 : (paddingStart() + paddingEnd() + (numEffCols() + 1) * hBorderSpacing()));
175     }
176
177     RenderTableCol* colElement(unsigned col, bool* startEdge = 0, bool* endEdge = 0) const;
178     RenderTableCol* nextColElement(RenderTableCol* current) const;
179
180     bool needsSectionRecalc() const { return m_needsSectionRecalc; }
181     void setNeedsSectionRecalc()
182     {
183         if (documentBeingDestroyed())
184             return;
185         m_needsSectionRecalc = true;
186         setNeedsLayout(true);
187     }
188
189     RenderTableSection* sectionAbove(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
190     RenderTableSection* sectionBelow(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
191
192     RenderTableCell* cellAbove(const RenderTableCell*) const;
193     RenderTableCell* cellBelow(const RenderTableCell*) const;
194     RenderTableCell* cellBefore(const RenderTableCell*) const;
195     RenderTableCell* cellAfter(const RenderTableCell*) const;
196  
197     typedef Vector<CollapsedBorderValue> CollapsedBorderValues;
198     void invalidateCollapsedBorders()
199     {
200         m_collapsedBordersValid = false;
201         m_collapsedBorders.clear();
202     }
203     const CollapsedBorderValue* currentBorderValue() const { return m_currentBorder; }
204     
205     bool hasSections() const { return header() || footer() || firstBody(); }
206
207     void recalcSectionsIfNeeded() const
208     {
209         if (m_needsSectionRecalc)
210             recalcSections();
211     }
212
213 protected:
214     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
215
216 private:
217     virtual const char* renderName() const { return "RenderTable"; }
218
219     virtual bool isTable() const { return true; }
220
221     virtual bool avoidsFloats() const { return true; }
222
223     virtual void removeChild(RenderObject* oldChild);
224
225     virtual void paint(PaintInfo&, const LayoutPoint&);
226     virtual void paintObject(PaintInfo&, const LayoutPoint&);
227     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
228     virtual void paintMask(PaintInfo&, const LayoutPoint&);
229     virtual void layout();
230     virtual void computePreferredLogicalWidths();
231     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
232     
233     virtual LayoutUnit firstLineBoxBaseline() const;
234
235     virtual RenderBlock* firstLineBlock() const;
236     virtual void updateFirstLetter();
237     
238     virtual void setCellLogicalWidths();
239
240     virtual void computeLogicalWidth();
241
242     virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
243
244     virtual void addOverflowFromChildren();
245
246     void subtractCaptionRect(LayoutRect&) const;
247
248     void recalcCollapsedBorders();
249     void recalcSections() const;
250     void adjustLogicalHeightForCaption(RenderBlock*);
251
252     mutable Vector<LayoutUnit> m_columnPos;
253     mutable Vector<ColumnStruct> m_columns;
254
255     mutable Vector<RenderBlock*> m_captions;
256     mutable RenderTableSection* m_header;
257     mutable RenderTableSection* m_footer;
258     mutable RenderTableSection* m_firstBody;
259
260     OwnPtr<TableLayout> m_tableLayout;
261
262     CollapsedBorderValues m_collapsedBorders;
263     const CollapsedBorderValue* m_currentBorder;
264     bool m_collapsedBordersValid : 1;
265     
266     mutable bool m_hasColElements : 1;
267     mutable bool m_needsSectionRecalc : 1;
268     
269     short m_hSpacing;
270     short m_vSpacing;
271     LayoutUnit m_borderStart;
272     LayoutUnit m_borderEnd;
273 };
274
275 inline RenderTableSection* RenderTable::topSection() const
276 {
277     if (header())
278         return header();
279     if (firstBody())
280         return firstBody();
281     return footer();
282 }
283
284 inline RenderTable* toRenderTable(RenderObject* object)
285 {
286     ASSERT(!object || object->isTable());
287     return static_cast<RenderTable*>(object);
288 }
289
290 inline const RenderTable* toRenderTable(const RenderObject* object)
291 {
292     ASSERT(!object || object->isTable());
293     return static_cast<const RenderTable*>(object);
294 }
295
296 // This will catch anyone doing an unnecessary cast.
297 void toRenderTable(const RenderTable*);
298
299 } // namespace WebCore
300
301 #endif // RenderTable_h