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