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 "RenderBlock.h"
30 #include <wtf/Vector.h>
31
32 namespace WebCore {
33
34 class CollapsedBorderValue;
35 class RenderTableCol;
36 class RenderTableCell;
37 class RenderTableSection;
38 class TableLayout;
39
40 class RenderTable : public RenderBlock {
41 public:
42 explicit RenderTable(Node*);
43 virtual ~RenderTable();
44
getColumnPos(int col)45 int getColumnPos(int col) const { return m_columnPos[col]; }
46
hBorderSpacing()47 int hBorderSpacing() const { return m_hSpacing; }
vBorderSpacing()48 int vBorderSpacing() const { return m_vSpacing; }
49
collapseBorders()50 bool collapseBorders() const { return style()->borderCollapse(); }
51
borderStart()52 int borderStart() const { return m_borderStart; }
borderEnd()53 int borderEnd() const { return m_borderEnd; }
54 int borderBefore() const;
55 int borderAfter() const;
56
borderLeft()57 int borderLeft() const
58 {
59 if (style()->isHorizontalWritingMode())
60 return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
61 return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
62 }
63
borderRight()64 int borderRight() const
65 {
66 if (style()->isHorizontalWritingMode())
67 return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
68 return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
69 }
70
borderTop()71 int borderTop() const
72 {
73 if (style()->isHorizontalWritingMode())
74 return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
75 return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
76 }
77
borderBottom()78 int borderBottom() const
79 {
80 if (style()->isHorizontalWritingMode())
81 return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
82 return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
83 }
84
bgColor()85 const Color bgColor() const { return style()->visitedDependentColor(CSSPropertyBackgroundColor); }
86
87 int outerBorderBefore() const;
88 int outerBorderAfter() const;
89 int outerBorderStart() const;
90 int outerBorderEnd() const;
91
outerBorderLeft()92 int outerBorderLeft() const
93 {
94 if (style()->isHorizontalWritingMode())
95 return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
96 return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
97 }
98
outerBorderRight()99 int outerBorderRight() const
100 {
101 if (style()->isHorizontalWritingMode())
102 return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
103 return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
104 }
105
outerBorderTop()106 int outerBorderTop() const
107 {
108 if (style()->isHorizontalWritingMode())
109 return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
110 return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
111 }
112
outerBorderBottom()113 int outerBorderBottom() const
114 {
115 if (style()->isHorizontalWritingMode())
116 return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
117 return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
118 }
119
120 int calcBorderStart() const;
121 int calcBorderEnd() const;
122 void recalcBordersInRowDirection();
123
124 virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
125
126 struct ColumnStruct {
127 enum {
128 WidthUndefined = 0xffff
129 };
130
ColumnStructColumnStruct131 ColumnStruct()
132 : span(1)
133 , width(WidthUndefined)
134 {
135 }
136
137 unsigned span;
138 unsigned width; // the calculated position of the column
139 };
140
columns()141 Vector<ColumnStruct>& columns() { return m_columns; }
columnPositions()142 Vector<int>& columnPositions() { return m_columnPos; }
header()143 RenderTableSection* header() const { return m_head; }
footer()144 RenderTableSection* footer() const { return m_foot; }
firstBody()145 RenderTableSection* firstBody() const { return m_firstBody; }
146
147 void splitColumn(int pos, int firstSpan);
148 void appendColumn(int span);
numEffCols()149 int numEffCols() const { return m_columns.size(); }
spanOfEffCol(int effCol)150 int spanOfEffCol(int effCol) const { return m_columns[effCol].span; }
151
colToEffCol(int col)152 int colToEffCol(int col) const
153 {
154 int i = 0;
155 int effCol = numEffCols();
156 for (int c = 0; c < col && i < effCol; ++i)
157 c += m_columns[i].span;
158 return i;
159 }
160
effColToCol(int effCol)161 int effColToCol(int effCol) const
162 {
163 int c = 0;
164 for (int i = 0; i < effCol; i++)
165 c += m_columns[i].span;
166 return c;
167 }
168
bordersPaddingAndSpacingInRowDirection()169 int bordersPaddingAndSpacingInRowDirection() const
170 {
171 return borderStart() + borderEnd() +
172 (collapseBorders() ? 0 : (paddingStart() + paddingEnd() + (numEffCols() + 1) * hBorderSpacing()));
173 }
174
175 RenderTableCol* colElement(int col, bool* startEdge = 0, bool* endEdge = 0) const;
176 RenderTableCol* nextColElement(RenderTableCol* current) const;
177
needsSectionRecalc()178 bool needsSectionRecalc() const { return m_needsSectionRecalc; }
setNeedsSectionRecalc()179 void setNeedsSectionRecalc()
180 {
181 if (documentBeingDestroyed())
182 return;
183 m_needsSectionRecalc = true;
184 setNeedsLayout(true);
185 }
186
187 RenderTableSection* sectionAbove(const RenderTableSection*, bool skipEmptySections = false) const;
188 RenderTableSection* sectionBelow(const RenderTableSection*, bool skipEmptySections = false) const;
189
190 RenderTableCell* cellAbove(const RenderTableCell*) const;
191 RenderTableCell* cellBelow(const RenderTableCell*) const;
192 RenderTableCell* cellBefore(const RenderTableCell*) const;
193 RenderTableCell* cellAfter(const RenderTableCell*) const;
194
currentBorderStyle()195 const CollapsedBorderValue* currentBorderStyle() const { return m_currentBorder; }
196
hasSections()197 bool hasSections() const { return m_head || m_foot || m_firstBody; }
198
recalcSectionsIfNeeded()199 void recalcSectionsIfNeeded() const
200 {
201 if (m_needsSectionRecalc)
202 recalcSections();
203 }
204
205 #ifdef ANDROID_LAYOUT
clearSingleColumn()206 void clearSingleColumn() { m_singleColumn = false; }
isSingleColumn()207 bool isSingleColumn() const { return m_singleColumn; }
208 #endif
209
210 protected:
211 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
212
213 private:
renderName()214 virtual const char* renderName() const { return "RenderTable"; }
215
isTable()216 virtual bool isTable() const { return true; }
217
avoidsFloats()218 virtual bool avoidsFloats() const { return true; }
219
220 virtual void removeChild(RenderObject* oldChild);
221
222 virtual void paint(PaintInfo&, int tx, int ty);
223 virtual void paintObject(PaintInfo&, int tx, int ty);
224 virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
225 virtual void paintMask(PaintInfo&, int tx, int ty);
226 virtual void layout();
227 virtual void computePreferredLogicalWidths();
228 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int xPos, int yPos, int tx, int ty, HitTestAction);
229
230 virtual int firstLineBoxBaseline() const;
231
232 virtual RenderBlock* firstLineBlock() const;
233 virtual void updateFirstLetter();
234
235 virtual void setCellLogicalWidths();
236
237 virtual void computeLogicalWidth();
238
239 virtual IntRect overflowClipRect(int tx, int ty, OverlayScrollbarSizeRelevancy relevancy = IgnoreOverlayScrollbarSize);
240
241 virtual void addOverflowFromChildren();
242
243 void subtractCaptionRect(IntRect&) const;
244
245 void recalcCaption(RenderBlock*) const;
246 void recalcSections() const;
247 void adjustLogicalHeightForCaption();
248
249 mutable Vector<int> m_columnPos;
250 mutable Vector<ColumnStruct> m_columns;
251
252 mutable RenderBlock* m_caption;
253 mutable RenderTableSection* m_head;
254 mutable RenderTableSection* m_foot;
255 mutable RenderTableSection* m_firstBody;
256
257 OwnPtr<TableLayout> m_tableLayout;
258
259 const CollapsedBorderValue* m_currentBorder;
260
261 mutable bool m_hasColElements : 1;
262 mutable bool m_needsSectionRecalc : 1;
263
264 #ifdef ANDROID_LAYOUT
265 bool m_singleColumn; // BS(Grace): should I use compact version?
266 #endif
267 short m_hSpacing;
268 short m_vSpacing;
269 int m_borderStart;
270 int m_borderEnd;
271 };
272
toRenderTable(RenderObject * object)273 inline RenderTable* toRenderTable(RenderObject* object)
274 {
275 ASSERT(!object || object->isTable());
276 return static_cast<RenderTable*>(object);
277 }
278
toRenderTable(const RenderObject * object)279 inline const RenderTable* toRenderTable(const RenderObject* object)
280 {
281 ASSERT(!object || object->isTable());
282 return static_cast<const RenderTable*>(object);
283 }
284
285 // This will catch anyone doing an unnecessary cast.
286 void toRenderTable(const RenderTable*);
287
288 } // namespace WebCore
289
290 #endif // RenderTable_h
291