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