1 /* 2 * Copyright (C) 1997 Martin Jones (mjones (at) kde.org) 3 * (C) 1997 Torben Weis (weis (at) kde.org) 4 * (C) 1998 Waldo Bastian (bastian (at) kde.org) 5 * (C) 1999 Lars Knoll (knoll (at) kde.org) 6 * (C) 1999 Antti Koivisto (koivisto (at) 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 45 unsigned colSpan() const 46 { 47 if (!m_hasColSpan) 48 return 1; 49 return parseColSpanFromDOM(); 50 } 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 61 void setCol(unsigned column) 62 { 63 if (UNLIKELY(column > maxColumnIndex)) 64 CRASH(); 65 66 m_column = column; 67 } 68 69 unsigned col() const 70 { 71 ASSERT(m_column != unsetColumnIndex); 72 return m_column; 73 } 74 75 RenderTableRow* row() const { return toRenderTableRow(parent()); } 76 RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); } 77 RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); } 78 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 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 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 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; 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&); 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); 159 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*); 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. 175 const RenderStyle* styleForCellFlow() const 176 { 177 return row()->style(); 178 } 179 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 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 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 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 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: 225 virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; } 226 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 252 void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; } 253 void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; } 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