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, 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