• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/rendering/RenderBlockFlow.h"
29 #include "core/rendering/RenderTableRow.h"
30 #include "core/rendering/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 SubtreeLayoutScope;
40 
41 class RenderTableCell FINAL : public RenderBlockFlow {
42 public:
43     explicit RenderTableCell(Element*);
44 
colSpan()45     unsigned colSpan() const
46     {
47         if (!m_hasColSpan)
48             return 1;
49         return parseColSpanFromDOM();
50     }
rowSpan()51     unsigned rowSpan() const
52     {
53         if (!m_hasRowSpan)
54             return 1;
55         return parseRowSpanFromDOM();
56     }
57 
58     // Called from HTMLTableCellElement.
59     void colSpanOrRowSpanChanged();
60 
setCol(unsigned column)61     void setCol(unsigned column)
62     {
63         if (UNLIKELY(column > maxColumnIndex))
64             CRASH();
65 
66         m_column = column;
67     }
68 
col()69     unsigned col() const
70     {
71         ASSERT(m_column != unsetColumnIndex);
72         return m_column;
73     }
74 
row()75     RenderTableRow* row() const { return toRenderTableRow(parent()); }
section()76     RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
table()77     RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
78 
rowIndex()79     unsigned rowIndex() const
80     {
81         // This function shouldn't be called on a detached cell.
82         ASSERT(row());
83         return row()->rowIndex();
84     }
85 
styleOrColLogicalWidth()86     Length styleOrColLogicalWidth() const
87     {
88         Length styleWidth = style()->logicalWidth();
89         if (!styleWidth.isAuto())
90             return styleWidth;
91         if (RenderTableCol* firstColumn = table()->colElement(col()))
92             return logicalWidthFromColumns(firstColumn, styleWidth);
93         return styleWidth;
94     }
95 
logicalHeightForRowSizing()96     int logicalHeightForRowSizing() const
97     {
98         // FIXME: This function does too much work, and is very hot during table layout!
99         int adjustedLogicalHeight = pixelSnappedLogicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
100         int styleLogicalHeight = valueForLength(style()->logicalHeight(), 0, view());
101         // In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
102         // Call computedCSSPadding* directly to avoid including implicitPadding.
103         if (!document().inQuirksMode() && style()->boxSizing() != BORDER_BOX)
104             styleLogicalHeight += (computedCSSPaddingBefore() + computedCSSPaddingAfter()).floor() + borderBefore() + borderAfter();
105         return max(styleLogicalHeight, adjustedLogicalHeight);
106     }
107 
108 
109     void setCellLogicalWidth(int constrainedLogicalWidth, SubtreeLayoutScope&);
110 
111     virtual int borderLeft() const;
112     virtual int borderRight() const;
113     virtual int borderTop() const;
114     virtual int borderBottom() const;
115     virtual int borderStart() const;
116     virtual int borderEnd() const;
117     virtual int borderBefore() const;
118     virtual int borderAfter() const;
119 
120     void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
121     static void sortBorderValues(RenderTable::CollapsedBorderValues&);
122 
123     virtual void layout();
124 
supportsPartialLayout()125     virtual bool supportsPartialLayout() const OVERRIDE { return false; }
126 
127     virtual void paint(PaintInfo&, const LayoutPoint&);
128 
129     void paintCollapsedBorders(PaintInfo&, const LayoutPoint&);
130     void paintBackgroundsBehindCell(PaintInfo&, const LayoutPoint&, RenderObject* backgroundObject);
131 
132     LayoutUnit cellBaselinePosition() const;
isBaselineAligned()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, SubtreeLayoutScope&);
clearIntrinsicPadding()140     void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); }
141 
intrinsicPaddingBefore()142     int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
intrinsicPaddingAfter()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);
159 
cellWidthChanged()160     bool cellWidthChanged() const { return m_cellWidthChanged; }
161     void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
162 
163     static RenderTableCell* createAnonymous(Document*);
164     static RenderTableCell* createAnonymousWithParentRenderer(const RenderObject*);
createAnonymousBoxWithSameTypeAs(const RenderObject * parent)165     virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
166     {
167         return createAnonymousWithParentRenderer(parent);
168     }
169 
170     // This function is used to unify which table part's style we use for computing direction and
171     // writing mode. Writing modes are not allowed on row group and row but direction is.
172     // This means we can safely use the same style in all cases to simplify our code.
173     // FIXME: Eventually this function should replaced by style() once we support direction
174     // on all table parts and writing-mode on cells.
styleForCellFlow()175     const RenderStyle* styleForCellFlow() const
176     {
177         return row()->style();
178     }
179 
borderAdjoiningTableStart()180     const BorderValue& borderAdjoiningTableStart() const
181     {
182         ASSERT(isFirstOrLastCellInRow());
183         if (section()->hasSameDirectionAs(table()))
184             return style()->borderStart();
185 
186         return style()->borderEnd();
187     }
188 
borderAdjoiningTableEnd()189     const BorderValue& borderAdjoiningTableEnd() const
190     {
191         ASSERT(isFirstOrLastCellInRow());
192         if (section()->hasSameDirectionAs(table()))
193             return style()->borderEnd();
194 
195         return style()->borderStart();
196     }
197 
borderAdjoiningCellBefore(const RenderTableCell * cell)198     const BorderValue& borderAdjoiningCellBefore(const RenderTableCell* cell)
199     {
200         ASSERT_UNUSED(cell, table()->cellAfter(cell) == this);
201         // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
202         return style()->borderStart();
203     }
204 
borderAdjoiningCellAfter(const RenderTableCell * cell)205     const BorderValue& borderAdjoiningCellAfter(const RenderTableCell* cell)
206     {
207         ASSERT_UNUSED(cell, table()->cellBefore(cell) == this);
208         // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
209         return style()->borderEnd();
210     }
211 
212 #ifndef NDEBUG
isFirstOrLastCellInRow()213     bool isFirstOrLastCellInRow() const
214     {
215         return !table()->cellAfter(this) || !table()->cellBefore(this);
216     }
217 #endif
218 protected:
219     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
220     virtual void computePreferredLogicalWidths();
221 
222     virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE;
223 
224 private:
renderName()225     virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
226 
isTableCell()227     virtual bool isTableCell() const { return true; }
228 
229     virtual void willBeRemovedFromTree() OVERRIDE;
230 
231     virtual void updateLogicalWidth() OVERRIDE;
232 
233     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
234     virtual void paintMask(PaintInfo&, const LayoutPoint&);
235 
236     virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE;
237 
238     virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
239     virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
240     virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
241 
242     int borderHalfLeft(bool outer) const;
243     int borderHalfRight(bool outer) const;
244     int borderHalfTop(bool outer) const;
245     int borderHalfBottom(bool outer) const;
246 
247     int borderHalfStart(bool outer) const;
248     int borderHalfEnd(bool outer) const;
249     int borderHalfBefore(bool outer) const;
250     int borderHalfAfter(bool outer) const;
251 
setIntrinsicPaddingBefore(int p)252     void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; }
setIntrinsicPaddingAfter(int p)253     void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; }
setIntrinsicPadding(int before,int after)254     void setIntrinsicPadding(int before, int after) { setIntrinsicPaddingBefore(before); setIntrinsicPaddingAfter(after); }
255 
256     bool hasStartBorderAdjoiningTable() const;
257     bool hasEndBorderAdjoiningTable() const;
258 
259     CollapsedBorderValue collapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
260     CollapsedBorderValue collapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
261     CollapsedBorderValue collapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
262     CollapsedBorderValue collapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
263 
264     CollapsedBorderValue cachedCollapsedLeftBorder(const RenderStyle*) const;
265     CollapsedBorderValue cachedCollapsedRightBorder(const RenderStyle*) const;
266     CollapsedBorderValue cachedCollapsedTopBorder(const RenderStyle*) const;
267     CollapsedBorderValue cachedCollapsedBottomBorder(const RenderStyle*) const;
268 
269     CollapsedBorderValue computeCollapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
270     CollapsedBorderValue computeCollapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
271     CollapsedBorderValue computeCollapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
272     CollapsedBorderValue computeCollapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
273 
274     Length logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const;
275 
276     void updateColAndRowSpanFlags();
277 
278     unsigned parseRowSpanFromDOM() const;
279     unsigned parseColSpanFromDOM() const;
280 
281     // Note MSVC will only pack members if they have identical types, hence we use unsigned instead of bool here.
282     unsigned m_column : 29;
283     unsigned m_cellWidthChanged : 1;
284     unsigned m_hasColSpan: 1;
285     unsigned m_hasRowSpan: 1;
286     int m_intrinsicPaddingBefore;
287     int m_intrinsicPaddingAfter;
288 };
289 
290 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTableCell, isTableCell());
291 
292 } // namespace WebCore
293 
294 #endif // RenderTableCell_h
295