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