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, 2009, 2010 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 RenderTable_h 26 #define RenderTable_h 27 28 #include "CSSPropertyNames.h" 29 #include "core/rendering/RenderBlock.h" 30 #include "core/rendering/style/CollapsedBorderValue.h" 31 #include "wtf/Vector.h" 32 33 namespace WebCore { 34 35 class RenderTableCol; 36 class RenderTableCaption; 37 class RenderTableCell; 38 class RenderTableSection; 39 class TableLayout; 40 41 enum SkipEmptySectionsValue { DoNotSkipEmptySections, SkipEmptySections }; 42 43 class RenderTable FINAL : public RenderBlock { 44 public: 45 explicit RenderTable(Element*); 46 virtual ~RenderTable(); 47 48 // Per CSS 3 writing-mode: "The first and second values of the 'border-spacing' property represent spacing between columns 49 // and rows respectively, not necessarily the horizontal and vertical spacing respectively". 50 int hBorderSpacing() const { return m_hSpacing; } 51 int vBorderSpacing() const { return m_vSpacing; } 52 53 bool collapseBorders() const { return style()->borderCollapse(); } 54 55 int borderStart() const { return m_borderStart; } 56 int borderEnd() const { return m_borderEnd; } 57 int borderBefore() const; 58 int borderAfter() const; 59 60 int borderLeft() const 61 { 62 if (style()->isHorizontalWritingMode()) 63 return style()->isLeftToRightDirection() ? borderStart() : borderEnd(); 64 return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore(); 65 } 66 67 int borderRight() const 68 { 69 if (style()->isHorizontalWritingMode()) 70 return style()->isLeftToRightDirection() ? borderEnd() : borderStart(); 71 return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter(); 72 } 73 74 int borderTop() const 75 { 76 if (style()->isHorizontalWritingMode()) 77 return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore(); 78 return style()->isLeftToRightDirection() ? borderStart() : borderEnd(); 79 } 80 81 int borderBottom() const 82 { 83 if (style()->isHorizontalWritingMode()) 84 return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter(); 85 return style()->isLeftToRightDirection() ? borderEnd() : borderStart(); 86 } 87 88 Color bgColor() const { return resolveColor(CSSPropertyBackgroundColor); } 89 90 int outerBorderBefore() const; 91 int outerBorderAfter() const; 92 int outerBorderStart() const; 93 int outerBorderEnd() const; 94 95 int outerBorderLeft() const 96 { 97 if (style()->isHorizontalWritingMode()) 98 return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd(); 99 return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore(); 100 } 101 102 int outerBorderRight() const 103 { 104 if (style()->isHorizontalWritingMode()) 105 return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart(); 106 return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter(); 107 } 108 109 int outerBorderTop() const 110 { 111 if (style()->isHorizontalWritingMode()) 112 return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore(); 113 return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd(); 114 } 115 116 int outerBorderBottom() const 117 { 118 if (style()->isHorizontalWritingMode()) 119 return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter(); 120 return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart(); 121 } 122 123 int calcBorderStart() const; 124 int calcBorderEnd() const; 125 void recalcBordersInRowDirection(); 126 127 virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); 128 129 struct ColumnStruct { 130 explicit ColumnStruct(unsigned initialSpan = 1) 131 : span(initialSpan) 132 { 133 } 134 135 unsigned span; 136 }; 137 138 void forceSectionsRecalc() 139 { 140 setNeedsSectionRecalc(); 141 recalcSections(); 142 } 143 144 const Vector<ColumnStruct>& columns() const { return m_columns; } 145 const Vector<int>& columnPositions() const { return m_columnPos; } 146 void setColumnPosition(unsigned index, int position) 147 { 148 // Note that if our horizontal border-spacing changed, our position will change but not 149 // our column's width. In practice, horizontal border-spacing won't change often. 150 m_columnLogicalWidthChanged |= m_columnPos[index] != position; 151 m_columnPos[index] = position; 152 } 153 154 RenderTableSection* header() const { return m_head; } 155 RenderTableSection* footer() const { return m_foot; } 156 RenderTableSection* firstBody() const { return m_firstBody; } 157 158 // This function returns 0 if the table has no section. 159 RenderTableSection* topSection() const; 160 RenderTableSection* bottomSection() const; 161 162 // This function returns 0 if the table has no non-empty sections. 163 RenderTableSection* topNonEmptySection() const; 164 165 unsigned lastColumnIndex() const { return numEffCols() - 1; } 166 167 void splitColumn(unsigned position, unsigned firstSpan); 168 void appendColumn(unsigned span); 169 unsigned numEffCols() const { return m_columns.size(); } 170 unsigned spanOfEffCol(unsigned effCol) const { return m_columns[effCol].span; } 171 172 unsigned colToEffCol(unsigned column) const 173 { 174 unsigned effColumn = 0; 175 unsigned numColumns = numEffCols(); 176 for (unsigned c = 0; effColumn < numColumns && c + m_columns[effColumn].span - 1 < column; ++effColumn) 177 c += m_columns[effColumn].span; 178 return effColumn; 179 } 180 181 unsigned effColToCol(unsigned effCol) const 182 { 183 unsigned c = 0; 184 for (unsigned i = 0; i < effCol; i++) 185 c += m_columns[i].span; 186 return c; 187 } 188 189 LayoutUnit borderSpacingInRowDirection() const 190 { 191 if (unsigned effectiveColumnCount = numEffCols()) 192 return static_cast<LayoutUnit>(effectiveColumnCount + 1) * hBorderSpacing(); 193 194 return 0; 195 } 196 197 // Override paddingStart/End to return pixel values to match behavor of RenderTableCell. 198 virtual LayoutUnit paddingEnd() const OVERRIDE { return static_cast<int>(RenderBlock::paddingEnd()); } 199 virtual LayoutUnit paddingStart() const OVERRIDE { return static_cast<int>(RenderBlock::paddingStart()); } 200 201 LayoutUnit bordersPaddingAndSpacingInRowDirection() const 202 { 203 // 'border-spacing' only applies to separate borders (see 17.6.1 The separated borders model). 204 return borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : (paddingStart() + paddingEnd() + borderSpacingInRowDirection())); 205 } 206 207 // Return the first column or column-group. 208 RenderTableCol* firstColumn() const; 209 210 RenderTableCol* colElement(unsigned col, bool* startEdge = 0, bool* endEdge = 0) const 211 { 212 // The common case is to not have columns, make that case fast. 213 if (!m_hasColElements) 214 return 0; 215 return slowColElement(col, startEdge, endEdge); 216 } 217 218 bool needsSectionRecalc() const { return m_needsSectionRecalc; } 219 void setNeedsSectionRecalc() 220 { 221 if (documentBeingDestroyed()) 222 return; 223 m_needsSectionRecalc = true; 224 setNeedsLayout(); 225 } 226 227 RenderTableSection* sectionAbove(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const; 228 RenderTableSection* sectionBelow(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const; 229 230 RenderTableCell* cellAbove(const RenderTableCell*) const; 231 RenderTableCell* cellBelow(const RenderTableCell*) const; 232 RenderTableCell* cellBefore(const RenderTableCell*) const; 233 RenderTableCell* cellAfter(const RenderTableCell*) const; 234 235 typedef Vector<CollapsedBorderValue> CollapsedBorderValues; 236 void invalidateCollapsedBorders() 237 { 238 m_collapsedBordersValid = false; 239 m_collapsedBorders.clear(); 240 } 241 const CollapsedBorderValue* currentBorderValue() const { return m_currentBorder; } 242 243 bool hasSections() const { return m_head || m_foot || m_firstBody; } 244 245 void recalcSectionsIfNeeded() const 246 { 247 if (m_needsSectionRecalc) 248 recalcSections(); 249 } 250 251 static RenderTable* createAnonymousWithParentRenderer(const RenderObject*); 252 virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE 253 { 254 return createAnonymousWithParentRenderer(parent); 255 } 256 257 const BorderValue& tableStartBorderAdjoiningCell(const RenderTableCell*) const; 258 const BorderValue& tableEndBorderAdjoiningCell(const RenderTableCell*) const; 259 260 void addCaption(const RenderTableCaption*); 261 void removeCaption(const RenderTableCaption*); 262 void addColumn(const RenderTableCol*); 263 void removeColumn(const RenderTableCol*); 264 265 protected: 266 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 267 virtual void simplifiedNormalFlowLayout(); 268 269 private: 270 virtual const char* renderName() const { return "RenderTable"; } 271 272 virtual bool isTable() const { return true; } 273 274 virtual bool avoidsFloats() const { return true; } 275 276 virtual void paint(PaintInfo&, const LayoutPoint&); 277 virtual void paintObject(PaintInfo&, const LayoutPoint&); 278 virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&); 279 virtual void paintMask(PaintInfo&, const LayoutPoint&); 280 virtual void layout(); 281 virtual bool supportsPartialLayout() const OVERRIDE { return false; } 282 virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const OVERRIDE; 283 virtual void computePreferredLogicalWidths() OVERRIDE; 284 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE; 285 286 virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE; 287 virtual int firstLineBoxBaseline() const OVERRIDE; 288 virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE; 289 290 RenderTableCol* slowColElement(unsigned col, bool* startEdge, bool* endEdge) const; 291 292 void updateColumnCache() const; 293 void invalidateCachedColumns(); 294 295 virtual RenderBlock* firstLineBlock() const; 296 virtual void updateFirstLetter(); 297 298 virtual void updateLogicalWidth() OVERRIDE; 299 300 LayoutUnit convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth); 301 LayoutUnit convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight); 302 303 virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize); 304 305 virtual void addOverflowFromChildren(); 306 307 void subtractCaptionRect(LayoutRect&) const; 308 309 void recalcCollapsedBorders(); 310 void recalcSections() const; 311 void layoutCaption(RenderTableCaption*); 312 313 void distributeExtraLogicalHeight(int extraLogicalHeight); 314 315 mutable Vector<int> m_columnPos; 316 mutable Vector<ColumnStruct> m_columns; 317 mutable Vector<RenderTableCaption*> m_captions; 318 mutable Vector<RenderTableCol*> m_columnRenderers; 319 320 mutable RenderTableSection* m_head; 321 mutable RenderTableSection* m_foot; 322 mutable RenderTableSection* m_firstBody; 323 324 OwnPtr<TableLayout> m_tableLayout; 325 326 CollapsedBorderValues m_collapsedBorders; 327 const CollapsedBorderValue* m_currentBorder; 328 bool m_collapsedBordersValid : 1; 329 330 mutable bool m_hasColElements : 1; 331 mutable bool m_needsSectionRecalc : 1; 332 333 bool m_columnLogicalWidthChanged : 1; 334 mutable bool m_columnRenderersValid: 1; 335 336 short m_hSpacing; 337 short m_vSpacing; 338 int m_borderStart; 339 int m_borderEnd; 340 }; 341 342 inline RenderTableSection* RenderTable::topSection() const 343 { 344 ASSERT(!needsSectionRecalc()); 345 if (m_head) 346 return m_head; 347 if (m_firstBody) 348 return m_firstBody; 349 return m_foot; 350 } 351 352 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTable, isTable()); 353 354 } // namespace WebCore 355 356 #endif // RenderTable_h 357