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 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 RenderTableSection_h 26#define RenderTableSection_h 27 28#include "RenderTable.h" 29#include <wtf/Vector.h> 30 31namespace WebCore { 32 33class RenderTableRow; 34 35enum CollapsedBorderSide { 36 CBSBefore, 37 CBSAfter, 38 CBSStart, 39 CBSEnd 40}; 41 42// Helper class for paintObject. 43class CellSpan { 44public: 45 CellSpan(unsigned start, unsigned end) 46 : m_start(start) 47 , m_end(end) 48 { 49 } 50 51 unsigned start() const { return m_start; } 52 unsigned end() const { return m_end; } 53 54 unsigned& start() { return m_start; } 55 unsigned& end() { return m_end; } 56 57private: 58 unsigned m_start; 59 unsigned m_end; 60}; 61 62class RenderTableCell; 63class RenderTableRow; 64 65class RenderTableSection final : public RenderBox { 66public: 67 RenderTableSection(Element&, PassRef<RenderStyle>); 68 RenderTableSection(Document&, PassRef<RenderStyle>); 69 virtual ~RenderTableSection(); 70 71 RenderTableRow* firstRow() const; 72 RenderTableRow* lastRow() const; 73 74 virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) override; 75 76 virtual int firstLineBaseline() const override; 77 78 void addCell(RenderTableCell*, RenderTableRow* row); 79 80 int calcRowLogicalHeight(); 81 void layoutRows(); 82 void computeOverflowFromCells(); 83 84 RenderTable* table() const { return toRenderTable(parent()); } 85 86 struct CellStruct { 87 Vector<RenderTableCell*, 1> cells; 88 bool inColSpan; // true for columns after the first in a colspan 89 90 CellStruct() 91 : inColSpan(false) 92 { 93 } 94 95 RenderTableCell* primaryCell() 96 { 97 return hasCells() ? cells[cells.size() - 1] : 0; 98 } 99 100 const RenderTableCell* primaryCell() const 101 { 102 return hasCells() ? cells[cells.size() - 1] : 0; 103 } 104 105 bool hasCells() const { return cells.size() > 0; } 106 }; 107 108 typedef Vector<CellStruct> Row; 109 110 struct RowStruct { 111 RowStruct() 112 : rowRenderer(0) 113 , baseline() 114 { 115 } 116 117 Row row; 118 RenderTableRow* rowRenderer; 119 LayoutUnit baseline; 120 Length logicalHeight; 121 }; 122 123 const BorderValue& borderAdjoiningTableStart() const 124 { 125 if (hasSameDirectionAs(table())) 126 return style().borderStart(); 127 128 return style().borderEnd(); 129 } 130 131 const BorderValue& borderAdjoiningTableEnd() const 132 { 133 if (hasSameDirectionAs(table())) 134 return style().borderEnd(); 135 136 return style().borderStart(); 137 } 138 139 const BorderValue& borderAdjoiningStartCell(const RenderTableCell*) const; 140 const BorderValue& borderAdjoiningEndCell(const RenderTableCell*) const; 141 142 const RenderTableCell* firstRowCellAdjoiningTableStart() const; 143 const RenderTableCell* firstRowCellAdjoiningTableEnd() const; 144 145 CellStruct& cellAt(unsigned row, unsigned col) 146 { 147 recalcCellsIfNeeded(); 148 return m_grid[row].row[col]; 149 } 150 151 const CellStruct& cellAt(unsigned row, unsigned col) const 152 { 153 ASSERT(!m_needsCellRecalc); 154 return m_grid[row].row[col]; 155 } 156 157 RenderTableCell* primaryCellAt(unsigned row, unsigned col) 158 { 159 recalcCellsIfNeeded(); 160 CellStruct& c = m_grid[row].row[col]; 161 return c.primaryCell(); 162 } 163 164 RenderTableRow* rowRendererAt(unsigned row) const 165 { 166 ASSERT(!m_needsCellRecalc); 167 return m_grid[row].rowRenderer; 168 } 169 170 void appendColumn(unsigned pos); 171 void splitColumn(unsigned pos, unsigned first); 172 173 int calcOuterBorderBefore() const; 174 int calcOuterBorderAfter() const; 175 int calcOuterBorderStart() const; 176 int calcOuterBorderEnd() const; 177 void recalcOuterBorder(); 178 179 int outerBorderBefore() const { return m_outerBorderBefore; } 180 int outerBorderAfter() const { return m_outerBorderAfter; } 181 int outerBorderStart() const { return m_outerBorderStart; } 182 int outerBorderEnd() const { return m_outerBorderEnd; } 183 184 int outerBorderLeft(const RenderStyle* styleForCellFlow) const 185 { 186 if (styleForCellFlow->isHorizontalWritingMode()) 187 return styleForCellFlow->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd(); 188 return styleForCellFlow->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore(); 189 } 190 191 int outerBorderRight(const RenderStyle* styleForCellFlow) const 192 { 193 if (styleForCellFlow->isHorizontalWritingMode()) 194 return styleForCellFlow->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart(); 195 return styleForCellFlow->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter(); 196 } 197 198 int outerBorderTop(const RenderStyle* styleForCellFlow) const 199 { 200 if (styleForCellFlow->isHorizontalWritingMode()) 201 return styleForCellFlow->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore(); 202 return styleForCellFlow->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd(); 203 } 204 205 int outerBorderBottom(const RenderStyle* styleForCellFlow) const 206 { 207 if (styleForCellFlow->isHorizontalWritingMode()) 208 return styleForCellFlow->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter(); 209 return styleForCellFlow->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart(); 210 } 211 212 unsigned numRows() const 213 { 214 ASSERT(!m_needsCellRecalc); 215 return m_grid.size(); 216 } 217 218 unsigned numColumns() const; 219 void recalcCells(); 220 void recalcCellsIfNeeded() 221 { 222 if (m_needsCellRecalc) 223 recalcCells(); 224 } 225 226 bool needsCellRecalc() const { return m_needsCellRecalc; } 227 void setNeedsCellRecalc(); 228 229 LayoutUnit rowBaseline(unsigned row) 230 { 231 recalcCellsIfNeeded(); 232 return m_grid[row].baseline; 233 } 234 235 void rowLogicalHeightChanged(unsigned rowIndex); 236 237 void removeCachedCollapsedBorders(const RenderTableCell*); 238 void setCachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide, CollapsedBorderValue); 239 CollapsedBorderValue& cachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide); 240 241 // distributeExtraLogicalHeightToRows methods return the *consumed* extra logical height. 242 // FIXME: We may want to introduce a structure holding the in-flux layout information. 243 int distributeExtraLogicalHeightToRows(int extraLogicalHeight); 244 245 static RenderTableSection* createAnonymousWithParentRenderer(const RenderObject*); 246 virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const override 247 { 248 return createAnonymousWithParentRenderer(parent); 249 } 250 251 virtual void paint(PaintInfo&, const LayoutPoint&) override; 252 253protected: 254 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override; 255 256private: 257 enum ShouldIncludeAllIntersectingCells { 258 IncludeAllIntersectingCells, 259 DoNotIncludeAllIntersectingCells 260 }; 261 262 virtual const char* renderName() const override { return (isAnonymous() || isPseudoElement()) ? "RenderTableSection (anonymous)" : "RenderTableSection"; } 263 264 virtual bool canHaveChildren() const override { return true; } 265 266 virtual bool isTableSection() const override { return true; } 267 268 virtual void willBeRemovedFromTree() override; 269 270 virtual void layout() override; 271 272 void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&); 273 virtual void paintObject(PaintInfo&, const LayoutPoint&) override; 274 void paintRowGroupBorder(const PaintInfo&, bool antialias, LayoutRect, BoxSide, CSSPropertyID borderColor, EBorderStyle, EBorderStyle tableBorderStyle); 275 void paintRowGroupBorderIfRequired(const PaintInfo&, const LayoutPoint& paintOffset, unsigned row, unsigned col, BoxSide, RenderTableCell* = 0); 276 int offsetLeftForRowGroupBorder(RenderTableCell*, const LayoutRect& rowGroupRect, unsigned row); 277 278 int offsetTopForRowGroupBorder(RenderTableCell*, BoxSide borderSide, unsigned row); 279 int verticalRowGroupBorderHeight(RenderTableCell*, const LayoutRect& rowGroupRect, unsigned row); 280 int horizontalRowGroupBorderWidth(RenderTableCell*, const LayoutRect& rowGroupRect, unsigned row, unsigned column); 281 282 virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) override; 283 284 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override; 285 286 void ensureRows(unsigned); 287 288 void distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent); 289 void distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount); 290 void distributeRemainingExtraLogicalHeight(int& extraLogicalHeight); 291 292 bool hasOverflowingCell() const { return m_overflowingCells.size() || m_forceSlowPaintPathWithOverflowingCell; } 293 void computeOverflowFromCells(unsigned totalRows, unsigned nEffCols); 294 295 CellSpan fullTableRowSpan() const 296 { 297 ASSERT(!m_needsCellRecalc); 298 return CellSpan(0, m_grid.size()); 299 } 300 301 CellSpan fullTableColumnSpan() const { return CellSpan(0, table()->columns().size()); } 302 303 // Flip the rect so it aligns with the coordinates used by the rowPos and columnPos vectors. 304 LayoutRect logicalRectForWritingModeAndDirection(const LayoutRect&) const; 305 306 CellSpan dirtiedRows(const LayoutRect& repaintRect) const; 307 CellSpan dirtiedColumns(const LayoutRect& repaintRect) const; 308 309 // These two functions take a rectangle as input that has been flipped by logicalRectForWritingModeAndDirection. 310 // The returned span of rows or columns is end-exclusive, and empty if start==end. 311 // The IncludeAllIntersectingCells argument is used to determine which cells to include when 312 // an edge of the flippedRect lies exactly on a cell boundary. Using IncludeAllIntersectingCells 313 // will return both cells, and using DoNotIncludeAllIntersectingCells will return only the cell 314 // that hittesting should return. 315 CellSpan spannedRows(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells) const; 316 CellSpan spannedColumns(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells) const; 317 318 void setLogicalPositionForCell(RenderTableCell*, unsigned effectiveColumn) const; 319 320 void firstChild() const = delete; 321 void lastChild() const = delete; 322 323 Vector<RowStruct> m_grid; 324 Vector<int> m_rowPos; 325 326 // the current insertion position 327 unsigned m_cCol; 328 unsigned m_cRow; 329 330 int m_outerBorderStart; 331 int m_outerBorderEnd; 332 int m_outerBorderBefore; 333 int m_outerBorderAfter; 334 335 bool m_needsCellRecalc; 336 337 // This HashSet holds the overflowing cells for faster painting. 338 // If we have more than gMaxAllowedOverflowingCellRatio * total cells, it will be empty 339 // and m_forceSlowPaintPathWithOverflowingCell will be set to save memory. 340 HashSet<RenderTableCell*> m_overflowingCells; 341 bool m_forceSlowPaintPathWithOverflowingCell; 342 343 bool m_hasMultipleCellLevels; 344 345 // This map holds the collapsed border values for cells with collapsed borders. 346 // It is held at RenderTableSection level to spare memory consumption by table cells. 347 HashMap<std::pair<const RenderTableCell*, int>, CollapsedBorderValue > m_cellsCollapsedBorders; 348}; 349 350RENDER_OBJECT_TYPE_CASTS(RenderTableSection, isTableSection()) 351 352} // namespace WebCore 353 354#endif // RenderTableSection_h 355