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             , rowWithOnlySpanningCells(false)
    133         {
    134         }
    135 
    136         Vector<int> rowHeight;
    137         int totalRowsHeight;
    138         int spanningCellHeightIgnoringBorderSpacing;
    139         bool rowWithOnlySpanningCells;
    140     };
    141 
    142     const BorderValue& borderAdjoiningTableStart() const
    143     {
    144         if (hasSameDirectionAs(table()))
    145             return style()->borderStart();
    146 
    147         return style()->borderEnd();
    148     }
    149 
    150     const BorderValue& borderAdjoiningTableEnd() const
    151     {
    152         if (hasSameDirectionAs(table()))
    153             return style()->borderEnd();
    154 
    155         return style()->borderStart();
    156     }
    157 
    158     const BorderValue& borderAdjoiningStartCell(const RenderTableCell*) const;
    159     const BorderValue& borderAdjoiningEndCell(const RenderTableCell*) const;
    160 
    161     const RenderTableCell* firstRowCellAdjoiningTableStart() const;
    162     const RenderTableCell* firstRowCellAdjoiningTableEnd() const;
    163 
    164     CellStruct& cellAt(unsigned row,  unsigned col) { return m_grid[row].row[col]; }
    165     const CellStruct& cellAt(unsigned row, unsigned col) const { return m_grid[row].row[col]; }
    166     RenderTableCell* primaryCellAt(unsigned row, unsigned col)
    167     {
    168         CellStruct& c = m_grid[row].row[col];
    169         return c.primaryCell();
    170     }
    171 
    172     RenderTableRow* rowRendererAt(unsigned row) const { return m_grid[row].rowRenderer; }
    173 
    174     void appendColumn(unsigned pos);
    175     void splitColumn(unsigned pos, unsigned first);
    176 
    177     int calcOuterBorderBefore() const;
    178     int calcOuterBorderAfter() const;
    179     int calcOuterBorderStart() const;
    180     int calcOuterBorderEnd() const;
    181     void recalcOuterBorder();
    182 
    183     int outerBorderBefore() const { return m_outerBorderBefore; }
    184     int outerBorderAfter() const { return m_outerBorderAfter; }
    185     int outerBorderStart() const { return m_outerBorderStart; }
    186     int outerBorderEnd() const { return m_outerBorderEnd; }
    187 
    188     unsigned numRows() const { return m_grid.size(); }
    189     unsigned numColumns() const;
    190     void recalcCells();
    191     void recalcCellsIfNeeded()
    192     {
    193         if (m_needsCellRecalc)
    194             recalcCells();
    195     }
    196 
    197     bool needsCellRecalc() const { return m_needsCellRecalc; }
    198     void setNeedsCellRecalc();
    199 
    200     LayoutUnit rowBaseline(unsigned row) { return m_grid[row].baseline; }
    201 
    202     void rowLogicalHeightChanged(unsigned rowIndex);
    203 
    204     void removeCachedCollapsedBorders(const RenderTableCell*);
    205     void setCachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide, CollapsedBorderValue);
    206     CollapsedBorderValue& cachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide);
    207 
    208     // distributeExtraLogicalHeightToRows methods return the *consumed* extra logical height.
    209     // FIXME: We may want to introduce a structure holding the in-flux layout information.
    210     int distributeExtraLogicalHeightToRows(int extraLogicalHeight);
    211 
    212     static RenderTableSection* createAnonymousWithParentRenderer(const RenderObject*);
    213     virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
    214     {
    215         return createAnonymousWithParentRenderer(parent);
    216     }
    217 
    218     virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
    219 
    220 protected:
    221     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
    222 
    223 private:
    224     virtual RenderObjectChildList* virtualChildren() { return children(); }
    225     virtual const RenderObjectChildList* virtualChildren() const { return children(); }
    226 
    227     virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
    228 
    229     virtual bool isTableSection() const { return true; }
    230 
    231     virtual void willBeRemovedFromTree() OVERRIDE;
    232 
    233     virtual void layout();
    234 
    235     virtual void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&);
    236     virtual void paintObject(PaintInfo&, const LayoutPoint&);
    237 
    238     virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
    239 
    240     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
    241 
    242     int borderSpacingForRow(unsigned row) const { return m_grid[row].rowRenderer ? table()->vBorderSpacing() : 0; }
    243 
    244     void ensureRows(unsigned);
    245 
    246     bool rowHasOnlySpanningCells(unsigned);
    247     unsigned calcRowHeightHavingOnlySpanningCells(unsigned);
    248     void updateRowsHeightHavingOnlySpanningCells(RenderTableCell*, struct SpanningRowsHeight&);
    249     bool isHeightNeededForRowHavingOnlySpanningCells(unsigned);
    250 
    251     void populateSpanningRowsHeightFromCell(RenderTableCell*, struct SpanningRowsHeight&);
    252     void distributeExtraRowSpanHeightToPercentRows(RenderTableCell*, int, int&, Vector<int>&);
    253     void distributeExtraRowSpanHeightToAutoRows(RenderTableCell*, int, int&, Vector<int>&);
    254     void distributeExtraRowSpanHeightToRemainingRows(RenderTableCell*, int, int&, Vector<int>&);
    255     void distributeRowSpanHeightToRows(SpanningRenderTableCells& rowSpanCells);
    256 
    257     void distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent);
    258     void distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount);
    259     void distributeRemainingExtraLogicalHeight(int& extraLogicalHeight);
    260 
    261     void updateBaselineForCell(RenderTableCell*, unsigned row, LayoutUnit& baselineDescent);
    262 
    263     bool hasOverflowingCell() const { return m_overflowingCells.size() || m_forceSlowPaintPathWithOverflowingCell; }
    264     void computeOverflowFromCells(unsigned totalRows, unsigned nEffCols);
    265 
    266     CellSpan fullTableRowSpan() const { return CellSpan(0, m_grid.size()); }
    267     CellSpan fullTableColumnSpan() const { return CellSpan(0, table()->columns().size()); }
    268 
    269     // Flip the rect so it aligns with the coordinates used by the rowPos and columnPos vectors.
    270     LayoutRect logicalRectForWritingModeAndDirection(const LayoutRect&) const;
    271 
    272     CellSpan dirtiedRows(const LayoutRect& repaintRect) const;
    273     CellSpan dirtiedColumns(const LayoutRect& repaintRect) const;
    274 
    275     // These two functions take a rectangle as input that has been flipped by logicalRectForWritingModeAndDirection.
    276     // The returned span of rows or columns is end-exclusive, and empty if start==end.
    277     CellSpan spannedRows(const LayoutRect& flippedRect) const;
    278     CellSpan spannedColumns(const LayoutRect& flippedRect) const;
    279 
    280     void setLogicalPositionForCell(RenderTableCell*, unsigned effectiveColumn) const;
    281 
    282     RenderObjectChildList m_children;
    283 
    284     Vector<RowStruct> m_grid;
    285     Vector<int> m_rowPos;
    286 
    287     // the current insertion position
    288     unsigned m_cCol;
    289     unsigned m_cRow;
    290 
    291     int m_outerBorderStart;
    292     int m_outerBorderEnd;
    293     int m_outerBorderBefore;
    294     int m_outerBorderAfter;
    295 
    296     bool m_needsCellRecalc;
    297 
    298     // This HashSet holds the overflowing cells for faster painting.
    299     // If we have more than gMaxAllowedOverflowingCellRatio * total cells, it will be empty
    300     // and m_forceSlowPaintPathWithOverflowingCell will be set to save memory.
    301     HashSet<RenderTableCell*> m_overflowingCells;
    302     bool m_forceSlowPaintPathWithOverflowingCell;
    303 
    304     bool m_hasMultipleCellLevels;
    305 
    306     // This map holds the collapsed border values for cells with collapsed borders.
    307     // It is held at RenderTableSection level to spare memory consumption by table cells.
    308     HashMap<pair<const RenderTableCell*, int>, CollapsedBorderValue > m_cellsCollapsedBorders;
    309 };
    310 
    311 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTableSection, isTableSection());
    312 
    313 } // namespace WebCore
    314 
    315 #endif // RenderTableSection_h
    316