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, 2007, 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 RenderTableCell_h
     26 #define RenderTableCell_h
     27 
     28 #include "core/rendering/RenderTableRow.h"
     29 #include "core/rendering/RenderTableSection.h"
     30 
     31 namespace WebCore {
     32 
     33 static const unsigned unsetColumnIndex = 0x1FFFFFFF;
     34 static const unsigned maxColumnIndex = 0x1FFFFFFE; // 536,870,910
     35 
     36 enum IncludeBorderColorOrNot { DoNotIncludeBorderColor, IncludeBorderColor };
     37 
     38 class RenderTableCell FINAL : public RenderBlock {
     39 public:
     40     explicit RenderTableCell(Element*);
     41 
     42     unsigned colSpan() const
     43     {
     44         if (!m_hasColSpan)
     45             return 1;
     46         return parseColSpanFromDOM();
     47     }
     48     unsigned rowSpan() const
     49     {
     50         if (!m_hasRowSpan)
     51             return 1;
     52         return parseRowSpanFromDOM();
     53     }
     54 
     55     // Called from HTMLTableCellElement.
     56     void colSpanOrRowSpanChanged();
     57 
     58     void setCol(unsigned column)
     59     {
     60         if (UNLIKELY(column > maxColumnIndex))
     61             CRASH();
     62 
     63         m_column = column;
     64     }
     65 
     66     unsigned col() const
     67     {
     68         ASSERT(m_column != unsetColumnIndex);
     69         return m_column;
     70     }
     71 
     72     RenderTableRow* row() const { return toRenderTableRow(parent()); }
     73     RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
     74     RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
     75 
     76     unsigned rowIndex() const
     77     {
     78         // This function shouldn't be called on a detached cell.
     79         ASSERT(row());
     80         return row()->rowIndex();
     81     }
     82 
     83     Length styleOrColLogicalWidth() const
     84     {
     85         Length styleWidth = style()->logicalWidth();
     86         if (!styleWidth.isAuto())
     87             return styleWidth;
     88         if (RenderTableCol* firstColumn = table()->colElement(col()))
     89             return logicalWidthFromColumns(firstColumn, styleWidth);
     90         return styleWidth;
     91     }
     92 
     93     int logicalHeightForRowSizing() const
     94     {
     95         // FIXME: This function does too much work, and is very hot during table layout!
     96         int adjustedLogicalHeight = pixelSnappedLogicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
     97         int styleLogicalHeight = valueForLength(style()->logicalHeight(), 0, view());
     98         // In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
     99         // Call computedCSSPadding* directly to avoid including implicitPadding.
    100         if (!document()->inQuirksMode() && style()->boxSizing() != BORDER_BOX)
    101             styleLogicalHeight += (computedCSSPaddingBefore() + computedCSSPaddingAfter()).floor() + borderBefore() + borderAfter();
    102         return max(styleLogicalHeight, adjustedLogicalHeight);
    103     }
    104 
    105 
    106     void setCellLogicalWidth(int constrainedLogicalWidth);
    107 
    108     virtual int borderLeft() const;
    109     virtual int borderRight() const;
    110     virtual int borderTop() const;
    111     virtual int borderBottom() const;
    112     virtual int borderStart() const;
    113     virtual int borderEnd() const;
    114     virtual int borderBefore() const;
    115     virtual int borderAfter() const;
    116 
    117     void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
    118     static void sortBorderValues(RenderTable::CollapsedBorderValues&);
    119 
    120     virtual void layout();
    121 
    122     virtual void paint(PaintInfo&, const LayoutPoint&);
    123 
    124     void paintCollapsedBorders(PaintInfo&, const LayoutPoint&);
    125     void paintBackgroundsBehindCell(PaintInfo&, const LayoutPoint&, RenderObject* backgroundObject);
    126 
    127     LayoutUnit cellBaselinePosition() const;
    128     bool isBaselineAligned() const
    129     {
    130         EVerticalAlign va = style()->verticalAlign();
    131         return va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH;
    132     }
    133 
    134     void computeIntrinsicPadding(int rowHeight);
    135     void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); }
    136 
    137     int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
    138     int intrinsicPaddingAfter() const { return m_intrinsicPaddingAfter; }
    139 
    140     virtual LayoutUnit paddingTop() const OVERRIDE;
    141     virtual LayoutUnit paddingBottom() const OVERRIDE;
    142     virtual LayoutUnit paddingLeft() const OVERRIDE;
    143     virtual LayoutUnit paddingRight() const OVERRIDE;
    144 
    145     // FIXME: For now we just assume the cell has the same block flow direction as the table. It's likely we'll
    146     // create an extra anonymous RenderBlock to handle mixing directionality anyway, in which case we can lock
    147     // the block flow directionality of the cells to the table's directionality.
    148     virtual LayoutUnit paddingBefore() const OVERRIDE;
    149     virtual LayoutUnit paddingAfter() const OVERRIDE;
    150 
    151     void setOverrideLogicalContentHeightFromRowHeight(LayoutUnit);
    152 
    153     virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged);
    154 
    155     bool cellWidthChanged() const { return m_cellWidthChanged; }
    156     void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
    157 
    158     static RenderTableCell* createAnonymous(Document*);
    159     static RenderTableCell* createAnonymousWithParentRenderer(const RenderObject*);
    160     virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
    161     {
    162         return createAnonymousWithParentRenderer(parent);
    163     }
    164 
    165     // This function is used to unify which table part's style we use for computing direction and
    166     // writing mode. Writing modes are not allowed on row group and row but direction is.
    167     // This means we can safely use the same style in all cases to simplify our code.
    168     // FIXME: Eventually this function should replaced by style() once we support direction
    169     // on all table parts and writing-mode on cells.
    170     const RenderStyle* styleForCellFlow() const
    171     {
    172         return row()->style();
    173     }
    174 
    175     const BorderValue& borderAdjoiningTableStart() const
    176     {
    177         ASSERT(isFirstOrLastCellInRow());
    178         if (section()->hasSameDirectionAs(table()))
    179             return style()->borderStart();
    180 
    181         return style()->borderEnd();
    182     }
    183 
    184     const BorderValue& borderAdjoiningTableEnd() const
    185     {
    186         ASSERT(isFirstOrLastCellInRow());
    187         if (section()->hasSameDirectionAs(table()))
    188             return style()->borderEnd();
    189 
    190         return style()->borderStart();
    191     }
    192 
    193     const BorderValue& borderAdjoiningCellBefore(const RenderTableCell* cell)
    194     {
    195         ASSERT_UNUSED(cell, table()->cellAfter(cell) == this);
    196         // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
    197         return style()->borderStart();
    198     }
    199 
    200     const BorderValue& borderAdjoiningCellAfter(const RenderTableCell* cell)
    201     {
    202         ASSERT_UNUSED(cell, table()->cellBefore(cell) == this);
    203         // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
    204         return style()->borderEnd();
    205     }
    206 
    207 #ifndef NDEBUG
    208     bool isFirstOrLastCellInRow() const
    209     {
    210         return !table()->cellAfter(this) || !table()->cellBefore(this);
    211     }
    212 #endif
    213 protected:
    214     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
    215     virtual void computePreferredLogicalWidths();
    216 
    217 private:
    218     virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
    219 
    220     virtual bool isTableCell() const { return true; }
    221 
    222     virtual void willBeRemovedFromTree() OVERRIDE;
    223 
    224     virtual void updateLogicalWidth() OVERRIDE;
    225 
    226     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
    227     virtual void paintMask(PaintInfo&, const LayoutPoint&);
    228 
    229     virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE;
    230 
    231     virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
    232     virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
    233     virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
    234 
    235     int borderHalfLeft(bool outer) const;
    236     int borderHalfRight(bool outer) const;
    237     int borderHalfTop(bool outer) const;
    238     int borderHalfBottom(bool outer) const;
    239 
    240     int borderHalfStart(bool outer) const;
    241     int borderHalfEnd(bool outer) const;
    242     int borderHalfBefore(bool outer) const;
    243     int borderHalfAfter(bool outer) const;
    244 
    245     void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; }
    246     void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; }
    247     void setIntrinsicPadding(int before, int after) { setIntrinsicPaddingBefore(before); setIntrinsicPaddingAfter(after); }
    248 
    249     bool hasStartBorderAdjoiningTable() const;
    250     bool hasEndBorderAdjoiningTable() const;
    251 
    252     CollapsedBorderValue collapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    253     CollapsedBorderValue collapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    254     CollapsedBorderValue collapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    255     CollapsedBorderValue collapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    256 
    257     CollapsedBorderValue cachedCollapsedLeftBorder(const RenderStyle*) const;
    258     CollapsedBorderValue cachedCollapsedRightBorder(const RenderStyle*) const;
    259     CollapsedBorderValue cachedCollapsedTopBorder(const RenderStyle*) const;
    260     CollapsedBorderValue cachedCollapsedBottomBorder(const RenderStyle*) const;
    261 
    262     CollapsedBorderValue computeCollapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    263     CollapsedBorderValue computeCollapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    264     CollapsedBorderValue computeCollapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    265     CollapsedBorderValue computeCollapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    266 
    267     Length logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const;
    268 
    269     void updateColAndRowSpanFlags();
    270 
    271     unsigned parseRowSpanFromDOM() const;
    272     unsigned parseColSpanFromDOM() const;
    273 
    274     // Note MSVC will only pack members if they have identical types, hence we use unsigned instead of bool here.
    275     unsigned m_column : 29;
    276     unsigned m_cellWidthChanged : 1;
    277     unsigned m_hasColSpan: 1;
    278     unsigned m_hasRowSpan: 1;
    279     int m_intrinsicPaddingBefore;
    280     int m_intrinsicPaddingAfter;
    281 };
    282 
    283 inline RenderTableCell* toRenderTableCell(RenderObject* object)
    284 {
    285     ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableCell());
    286     return static_cast<RenderTableCell*>(object);
    287 }
    288 
    289 inline const RenderTableCell* toRenderTableCell(const RenderObject* object)
    290 {
    291     ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableCell());
    292     return static_cast<const RenderTableCell*>(object);
    293 }
    294 
    295 // This will catch anyone doing an unnecessary cast.
    296 void toRenderTableCell(const RenderTableCell*);
    297 
    298 } // namespace WebCore
    299 
    300 #endif // RenderTableCell_h
    301