Make no-column table-layout cases a little faster with inlining
[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 RenderTableCaption;
37 class RenderTableCell;
38 class RenderTableSection;
39 class TableLayout;
40
41 enum SkipEmptySectionsValue { DoNotSkipEmptySections, SkipEmptySections };
42
43 class RenderTable : public RenderBlock {
44 public:
45     explicit RenderTable(Node*);
46     virtual ~RenderTable();
47
48     int getColumnPos(unsigned col) const { return m_columnPos[col]; }
49
50     // Per CSS 3 writing-mode: "The first and second values of the 'border-spacing' property represent spacing between columns
51     // and rows respectively, not necessarily the horizontal and vertical spacing respectively".
52     int hBorderSpacing() const { return m_hSpacing; }
53     int vBorderSpacing() const { return m_vSpacing; }
54     
55     bool collapseBorders() const { return style()->borderCollapse(); }
56
57     int borderStart() const { return m_borderStart; }
58     int borderEnd() const { return m_borderEnd; }
59     int borderBefore() const;
60     int borderAfter() const;
61
62     int borderLeft() const
63     {
64         if (style()->isHorizontalWritingMode())
65             return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
66         return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
67     }
68
69     int borderRight() const
70     {
71         if (style()->isHorizontalWritingMode())
72             return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
73         return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
74     }
75
76     int borderTop() const
77     {
78         if (style()->isHorizontalWritingMode())
79             return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
80         return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
81     }
82
83     int borderBottom() const
84     {
85         if (style()->isHorizontalWritingMode())
86             return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
87         return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
88     }
89
90     Color bgColor() const { return style()->visitedDependentColor(CSSPropertyBackgroundColor); }
91
92     int outerBorderBefore() const;
93     int outerBorderAfter() const;
94     int outerBorderStart() const;
95     int outerBorderEnd() const;
96
97     int outerBorderLeft() const
98     {
99         if (style()->isHorizontalWritingMode())
100             return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
101         return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
102     }
103
104     int outerBorderRight() const
105     {
106         if (style()->isHorizontalWritingMode())
107             return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
108         return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
109     }
110
111     int outerBorderTop() const
112     {
113         if (style()->isHorizontalWritingMode())
114             return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
115         return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
116     }
117
118     int outerBorderBottom() const
119     {
120         if (style()->isHorizontalWritingMode())
121             return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
122         return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
123     }
124
125     int calcBorderStart() const;
126     int calcBorderEnd() const;
127     void recalcBordersInRowDirection();
128
129     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
130
131     struct ColumnStruct {
132         ColumnStruct()
133             : span(1)
134         {
135         }
136
137         unsigned span;
138     };
139
140     void forceSectionsRecalc()
141     {
142         setNeedsSectionRecalc();
143         recalcSections();
144     }
145
146     Vector<ColumnStruct>& columns() { return m_columns; }
147     Vector<int>& columnPositions() { return m_columnPos; }
148     RenderTableSection* header() const { return m_head; }
149     RenderTableSection* footer() const { return m_foot; }
150     RenderTableSection* firstBody() const { return m_firstBody; }
151
152     // This function returns 0 if the table has no section.
153     RenderTableSection* topSection() const;
154     RenderTableSection* bottomSection() const;
155
156     // This function returns 0 if the table has no non-empty sections.
157     RenderTableSection* topNonEmptySection() const;
158
159     unsigned lastColumnIndex() const { return numEffCols() - 1; }
160
161     void splitColumn(unsigned position, unsigned firstSpan);
162     void appendColumn(unsigned span);
163     unsigned numEffCols() const { return m_columns.size(); }
164     unsigned spanOfEffCol(unsigned effCol) const { return m_columns[effCol].span; }
165     
166     unsigned colToEffCol(unsigned column) const
167     {
168         unsigned effColumn = 0;
169         unsigned numColumns = numEffCols();
170         for (unsigned c = 0; effColumn < numColumns && c + m_columns[effColumn].span - 1 < column; ++effColumn)
171             c += m_columns[effColumn].span;
172         return effColumn;
173     }
174     
175     unsigned effColToCol(unsigned effCol) const
176     {
177         unsigned c = 0;
178         for (unsigned i = 0; i < effCol; i++)
179             c += m_columns[i].span;
180         return c;
181     }
182
183     LayoutUnit borderSpacingInRowDirection() const
184     {
185         if (unsigned effectiveColumnCount = numEffCols())
186             return static_cast<LayoutUnit>(effectiveColumnCount + 1) * hBorderSpacing();
187
188         return ZERO_LAYOUT_UNIT;
189     }
190
191     LayoutUnit bordersPaddingAndSpacingInRowDirection() const
192     {
193         // 'border-spacing' only applies to separate borders (see 17.6.1 The separated borders model).
194         return borderStart() + borderEnd() +
195                (collapseBorders() ? ZERO_LAYOUT_UNIT : (paddingStart() + paddingEnd() + borderSpacingInRowDirection()));
196     }
197
198     // Return the first column or column-group.
199     RenderTableCol* firstColumn() const;
200
201     RenderTableCol* colElement(unsigned col, bool* startEdge = 0, bool* endEdge = 0) const
202     {
203         // The common case is to not have columns, make that case fast.
204         if (!m_hasColElements)
205             return 0;
206         return slowColElement(col, startEdge, endEdge);
207     }
208
209     bool needsSectionRecalc() const { return m_needsSectionRecalc; }
210     void setNeedsSectionRecalc()
211     {
212         if (documentBeingDestroyed())
213             return;
214         m_needsSectionRecalc = true;
215         setNeedsLayout(true);
216     }
217
218     RenderTableSection* sectionAbove(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
219     RenderTableSection* sectionBelow(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
220
221     RenderTableCell* cellAbove(const RenderTableCell*) const;
222     RenderTableCell* cellBelow(const RenderTableCell*) const;
223     RenderTableCell* cellBefore(const RenderTableCell*) const;
224     RenderTableCell* cellAfter(const RenderTableCell*) const;
225  
226     typedef Vector<CollapsedBorderValue> CollapsedBorderValues;
227     void invalidateCollapsedBorders()
228     {
229         m_collapsedBordersValid = false;
230         m_collapsedBorders.clear();
231     }
232     const CollapsedBorderValue* currentBorderValue() const { return m_currentBorder; }
233     
234     bool hasSections() const { return m_head || m_foot || m_firstBody; }
235
236     void recalcSectionsIfNeeded() const
237     {
238         if (m_needsSectionRecalc)
239             recalcSections();
240     }
241
242     static RenderTable* createAnonymousWithParentRenderer(const RenderObject*);
243     virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
244     {
245         return createAnonymousWithParentRenderer(parent);
246     }
247
248     const BorderValue& tableStartBorderAdjoiningCell(const RenderTableCell*) const;
249     const BorderValue& tableEndBorderAdjoiningCell(const RenderTableCell*) const;
250
251     void addCaption(const RenderTableCaption*);
252     void removeCaption(const RenderTableCaption*);
253
254 protected:
255     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
256
257 private:
258     virtual const char* renderName() const { return "RenderTable"; }
259
260     virtual bool isTable() const { return true; }
261
262     virtual bool avoidsFloats() const { return true; }
263
264     virtual void paint(PaintInfo&, const LayoutPoint&);
265     virtual void paintObject(PaintInfo&, const LayoutPoint&);
266     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
267     virtual void paintMask(PaintInfo&, const LayoutPoint&);
268     virtual void layout();
269     virtual void computePreferredLogicalWidths();
270     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
271
272     virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
273     virtual LayoutUnit firstLineBoxBaseline() const OVERRIDE;
274     virtual LayoutUnit lastLineBoxBaseline() const OVERRIDE;
275
276     RenderTableCol* slowColElement(unsigned col, bool* startEdge, bool* endEdge) const;
277
278     virtual RenderBlock* firstLineBlock() const;
279     virtual void updateFirstLetter();
280     
281     virtual void setCellLogicalWidths();
282
283     virtual void updateLogicalWidth() OVERRIDE;
284
285     LayoutUnit convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth);
286
287     virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
288
289     virtual void addOverflowFromChildren();
290
291     void subtractCaptionRect(LayoutRect&) const;
292
293     void recalcCollapsedBorders();
294     void recalcSections() const;
295     void layoutCaption(RenderTableCaption*);
296
297     void distributeExtraLogicalHeight(int extraLogicalHeight);
298
299     mutable Vector<int> m_columnPos;
300     mutable Vector<ColumnStruct> m_columns;
301     mutable Vector<RenderTableCaption*> m_captions;
302
303     mutable RenderTableSection* m_head;
304     mutable RenderTableSection* m_foot;
305     mutable RenderTableSection* m_firstBody;
306
307     OwnPtr<TableLayout> m_tableLayout;
308
309     CollapsedBorderValues m_collapsedBorders;
310     const CollapsedBorderValue* m_currentBorder;
311     bool m_collapsedBordersValid : 1;
312     
313     mutable bool m_hasColElements : 1;
314     mutable bool m_needsSectionRecalc : 1;
315     
316     short m_hSpacing;
317     short m_vSpacing;
318     int m_borderStart;
319     int m_borderEnd;
320 };
321
322 inline RenderTableSection* RenderTable::topSection() const
323 {
324     ASSERT(!needsSectionRecalc());
325     if (m_head)
326         return m_head;
327     if (m_firstBody)
328         return m_firstBody;
329     return m_foot;
330 }
331
332 inline RenderTable* toRenderTable(RenderObject* object)
333 {
334     ASSERT(!object || object->isTable());
335     return static_cast<RenderTable*>(object);
336 }
337
338 inline const RenderTable* toRenderTable(const RenderObject* object)
339 {
340     ASSERT(!object || object->isTable());
341     return static_cast<const RenderTable*>(object);
342 }
343
344 // This will catch anyone doing an unnecessary cast.
345 void toRenderTable(const RenderTable*);
346
347 } // namespace WebCore
348
349 #endif // RenderTable_h