77c92b990b8db5cacccdbde012482b83d3859c25
[WebKit-https.git] / Source / WebCore / rendering / RenderTableCell.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, 2007, 2009 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 RenderTableCell_h
26 #define RenderTableCell_h
27
28 #include "RenderBlockFlow.h"
29 #include "RenderTableRow.h"
30 #include "RenderTableSection.h"
31
32 namespace WebCore {
33
34 static const unsigned unsetColumnIndex = 0x1FFFFFFF;
35 static const unsigned maxColumnIndex = 0x1FFFFFFE; // 536,870,910
36
37 enum IncludeBorderColorOrNot { DoNotIncludeBorderColor, IncludeBorderColor };
38
39 class RenderTableCell final : public RenderBlockFlow {
40 public:
41     RenderTableCell(Element&, PassRef<RenderStyle>);
42     RenderTableCell(Document&, PassRef<RenderStyle>);
43     
44     unsigned colSpan() const
45     {
46         if (!m_hasColSpan)
47             return 1;
48         return parseColSpanFromDOM();
49     }
50     unsigned rowSpan() const
51     {
52         if (!m_hasRowSpan)
53             return 1;
54         return parseRowSpanFromDOM();
55     }
56
57     // Called from HTMLTableCellElement.
58     void colSpanOrRowSpanChanged();
59
60     void setCol(unsigned column)
61     {
62         if (UNLIKELY(column > maxColumnIndex))
63             CRASH();
64
65         m_column = column;
66     }
67
68     unsigned col() const
69     {
70         ASSERT(m_column != unsetColumnIndex);
71         return m_column;
72     }
73
74     RenderTableCell* nextCell() const;
75     RenderTableCell* previousCell() const;
76
77     RenderTableRow* row() const { return toRenderTableRow(parent()); }
78     RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
79     RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
80
81     unsigned rowIndex() const
82     {
83         // This function shouldn't be called on a detached cell.
84         ASSERT(row());
85         return row()->rowIndex();
86     }
87
88     Length styleOrColLogicalWidth() const
89     {
90         Length styleWidth = style().logicalWidth();
91         if (!styleWidth.isAuto())
92             return styleWidth;
93         if (RenderTableCol* firstColumn = table()->colElement(col()))
94             return logicalWidthFromColumns(firstColumn, styleWidth);
95         return styleWidth;
96     }
97
98     int logicalHeightForRowSizing() const
99     {
100         // FIXME: This function does too much work, and is very hot during table layout!
101         int adjustedLogicalHeight = pixelSnappedLogicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
102         int styleLogicalHeight = valueForLength(style().logicalHeight(), 0);
103         // In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
104         // Call computedCSSPadding* directly to avoid including implicitPadding.
105         if (!document().inQuirksMode() && style().boxSizing() != BORDER_BOX)
106             styleLogicalHeight += (computedCSSPaddingBefore() + computedCSSPaddingAfter()).floor() + (borderBefore() + borderAfter()).floor();
107         return std::max(styleLogicalHeight, adjustedLogicalHeight);
108     }
109
110
111     void setCellLogicalWidth(int constrainedLogicalWidth);
112
113     virtual LayoutUnit borderLeft() const override;
114     virtual LayoutUnit borderRight() const override;
115     virtual LayoutUnit borderTop() const override;
116     virtual LayoutUnit borderBottom() const override;
117     virtual LayoutUnit borderStart() const override;
118     virtual LayoutUnit borderEnd() const override;
119     virtual LayoutUnit borderBefore() const override;
120     virtual LayoutUnit borderAfter() const override;
121
122     void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
123     static void sortBorderValues(RenderTable::CollapsedBorderValues&);
124
125     virtual void layout() override;
126
127     virtual void paint(PaintInfo&, const LayoutPoint&) override;
128
129     void paintCollapsedBorders(PaintInfo&, const LayoutPoint&);
130     void paintBackgroundsBehindCell(PaintInfo&, const LayoutPoint&, RenderElement* backgroundObject);
131
132     LayoutUnit cellBaselinePosition() const;
133     bool isBaselineAligned() const 
134     { 
135         EVerticalAlign va = style().verticalAlign();
136         return va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH; 
137     }
138
139     void computeIntrinsicPadding(int rowHeight);
140     void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); }
141
142     int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
143     int intrinsicPaddingAfter() const { return m_intrinsicPaddingAfter; }
144
145     virtual LayoutUnit paddingTop() const override;
146     virtual LayoutUnit paddingBottom() const override;
147     virtual LayoutUnit paddingLeft() const override;
148     virtual LayoutUnit paddingRight() const override;
149     
150     // FIXME: For now we just assume the cell has the same block flow direction as the table. It's likely we'll
151     // create an extra anonymous RenderBlock to handle mixing directionality anyway, in which case we can lock
152     // the block flow directionality of the cells to the table's directionality.
153     virtual LayoutUnit paddingBefore() const override;
154     virtual LayoutUnit paddingAfter() const override;
155
156     void setOverrideLogicalContentHeightFromRowHeight(LayoutUnit);
157
158     virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged) override;
159
160     bool cellWidthChanged() const { return m_cellWidthChanged; }
161     void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
162
163     static RenderTableCell* createAnonymousWithParentRenderer(const RenderObject*);
164     virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const override
165     {
166         return createAnonymousWithParentRenderer(parent);
167     }
168
169     // This function is used to unify which table part's style we use for computing direction and
170     // writing mode. Writing modes are not allowed on row group and row but direction is.
171     // This means we can safely use the same style in all cases to simplify our code.
172     // FIXME: Eventually this function should replaced by style() once we support direction
173     // on all table parts and writing-mode on cells.
174     const RenderStyle& styleForCellFlow() const
175     {
176         return row()->style();
177     }
178
179     const BorderValue& borderAdjoiningTableStart() const
180     {
181         ASSERT(isFirstOrLastCellInRow());
182         if (section()->hasSameDirectionAs(table()))
183             return style().borderStart();
184
185         return style().borderEnd();
186     }
187
188     const BorderValue& borderAdjoiningTableEnd() const
189     {
190         ASSERT(isFirstOrLastCellInRow());
191         if (section()->hasSameDirectionAs(table()))
192             return style().borderEnd();
193
194         return style().borderStart();
195     }
196
197     const BorderValue& borderAdjoiningCellBefore(const RenderTableCell* cell)
198     {
199         ASSERT_UNUSED(cell, table()->cellAfter(cell) == this);
200         // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
201         return style().borderStart();
202     }
203
204     const BorderValue& borderAdjoiningCellAfter(const RenderTableCell* cell)
205     {
206         ASSERT_UNUSED(cell, table()->cellBefore(cell) == this);
207         // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
208         return style().borderEnd();
209     }
210
211     using RenderBlockFlow::nodeAtPoint;
212
213 #ifndef NDEBUG
214     bool isFirstOrLastCellInRow() const
215     {
216         return !table()->cellAfter(this) || !table()->cellBefore(this);
217     }
218 #endif
219 protected:
220     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
221     virtual void computePreferredLogicalWidths() override;
222
223 private:
224     virtual const char* renderName() const override { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
225
226     virtual bool isTableCell() const override { return true; }
227
228     virtual void willBeRemovedFromTree() override;
229
230     virtual void updateLogicalWidth() override;
231
232     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) override;
233     virtual void paintMask(PaintInfo&, const LayoutPoint&) override;
234
235     virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const override;
236
237     virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const override;
238     virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
239     virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const override;
240
241     int borderHalfLeft(bool outer) const;
242     int borderHalfRight(bool outer) const;
243     int borderHalfTop(bool outer) const;
244     int borderHalfBottom(bool outer) const;
245
246     int borderHalfStart(bool outer) const;
247     int borderHalfEnd(bool outer) const;
248     int borderHalfBefore(bool outer) const;
249     int borderHalfAfter(bool outer) const;
250
251     void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; }
252     void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; }
253     void setIntrinsicPadding(int before, int after) { setIntrinsicPaddingBefore(before); setIntrinsicPaddingAfter(after); }
254
255     bool hasStartBorderAdjoiningTable() const;
256     bool hasEndBorderAdjoiningTable() const;
257
258     CollapsedBorderValue collapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
259     CollapsedBorderValue collapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
260     CollapsedBorderValue collapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
261     CollapsedBorderValue collapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
262
263     CollapsedBorderValue cachedCollapsedLeftBorder(const RenderStyle*) const;
264     CollapsedBorderValue cachedCollapsedRightBorder(const RenderStyle*) const;
265     CollapsedBorderValue cachedCollapsedTopBorder(const RenderStyle*) const;
266     CollapsedBorderValue cachedCollapsedBottomBorder(const RenderStyle*) const;
267
268     CollapsedBorderValue computeCollapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
269     CollapsedBorderValue computeCollapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
270     CollapsedBorderValue computeCollapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
271     CollapsedBorderValue computeCollapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
272
273     RenderTableCell* cellAtLeft(const RenderStyle*) const;
274     RenderTableCell* cellAtRight(const RenderStyle*) const;
275     RenderTableCell* cellAtTop(const RenderStyle*) const;
276     RenderTableCell* cellAtBottom(const RenderStyle*) const;
277
278     Length logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const;
279
280     void updateColAndRowSpanFlags();
281
282     unsigned parseRowSpanFromDOM() const;
283     unsigned parseColSpanFromDOM() const;
284
285     void nextSibling() const = delete;
286     void previousSibling() const = delete;
287
288     // Note MSVC will only pack members if they have identical types, hence we use unsigned instead of bool here.
289     unsigned m_column : 29;
290     unsigned m_cellWidthChanged : 1;
291     unsigned m_hasColSpan: 1;
292     unsigned m_hasRowSpan: 1;
293     int m_intrinsicPaddingBefore;
294     int m_intrinsicPaddingAfter;
295 };
296
297 RENDER_OBJECT_TYPE_CASTS(RenderTableCell, isTableCell())
298
299 inline RenderTableCell* RenderTableCell::nextCell() const
300 {
301     return toRenderTableCell(RenderBlockFlow::nextSibling());
302 }
303
304 inline RenderTableCell* RenderTableCell::previousCell() const
305 {
306     return toRenderTableCell(RenderBlockFlow::previousSibling());
307 }
308
309 inline RenderTableCell* RenderTableRow::firstCell() const
310 {
311     return toRenderTableCell(RenderBox::firstChild());
312 }
313
314 inline RenderTableCell* RenderTableRow::lastCell() const
315 {
316     return toRenderTableCell(RenderBox::lastChild());
317 }
318
319 } // namespace WebCore
320
321 SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderTableCell, isTableCell())
322
323 #endif // RenderTableCell_h