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