blob: f70334f48de2aa8dc48e9a3713e948136217ea7e [file] [log] [blame]
* Copyright (C) 1997 Martin Jones (
* (C) 1997 Torben Weis (
* (C) 1998 Waldo Bastian (
* (C) 1999 Lars Knoll (
* (C) 1999 Antti Koivisto (
* Copyright (C) 2003, 2004, 2005, 2006, 2009, 2013 Apple Inc.
* All rights reserved.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* Library General Public License for more details.
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_table_section.h"
namespace blink {
// There is a window of opportunity to read |m_rowIndex| before it is set when
// inserting the LayoutTableRow or during LayoutTableSection::recalcCells.
// This value is used to detect that case.
static const unsigned kUnsetRowIndex = 0x7FFFFFFF;
static const unsigned kMaxRowIndex = 0x7FFFFFFE; // 2,147,483,646
// LayoutTableRow is used to represent a table row (display: table-row).
// LayoutTableRow is a simple object. The reason is that most operations
// have to be coordinated at the LayoutTableSection level and thus are
// handled in LayoutTableSection (see e.g. layoutRows).
// The table model prevents any layout overflow on rows (but allow visual
// overflow). For row height, it is defined as "the maximum of the row's
// computed 'height', the computed 'height' of each cell in the row, and
// the minimum height (MIN) required by the cells" (CSS 2.1 - section 17.5.3).
// Note that this means that rows and cells differ from other LayoutObject as
// they will ignore 'height' in some situation (when other LayoutObject just
// allow some layout overflow to occur).
// LayoutTableRow doesn't establish a containing block for the underlying
// LayoutTableCells. That's why it inherits from LayoutTableBoxComponent and not
// LayoutBlock.
// One oddity is that LayoutTableRow doesn't establish a new coordinate system
// for its children. LayoutTableCells are positioned with respect to the
// enclosing LayoutTableSection (this object's parent()). This particularity is
// why functions accumulating offset while walking the tree have to special case
// LayoutTableRow (see e.g. PaintInvalidatorContext or
// LayoutBox::PositionFromPoint()).
// LayoutTableRow is also positioned with respect to the enclosing
// LayoutTableSection. See LayoutTableSection::layoutRows() for the placement
// logic.
class CORE_EXPORT LayoutTableRow final : public LayoutTableBoxComponent {
explicit LayoutTableRow(Element*);
LayoutTableCell* FirstCell() const;
LayoutTableCell* LastCell() const;
LayoutTableRow* PreviousRow() const;
LayoutTableRow* NextRow() const;
LayoutTableSection* Section() const { return ToLayoutTableSection(Parent()); }
LayoutTable* Table() const final { return ToLayoutTable(Parent()->Parent()); }
static LayoutTableRow* CreateAnonymous(Document*);
static LayoutTableRow* CreateAnonymousWithParent(const LayoutObject*);
LayoutBox* CreateAnonymousBoxWithSameTypeAs(
const LayoutObject* parent) const override {
return CreateAnonymousWithParent(parent);
void SetRowIndex(unsigned row_index) {
CHECK_LE(row_index, kMaxRowIndex);
row_index_ = row_index;
bool RowIndexWasSet() const { return row_index_ != kUnsetRowIndex; }
unsigned RowIndex() const {
!Section() ||
->NeedsCellRecalc()); // index may be bogus if cells need recalc.
return row_index_;
bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
HitTestAction) override;
PaginationBreakability GetPaginationBreakability() const final;
void ComputeOverflow();
const char* GetName() const override { return "LayoutTableRow"; }
// Whether a row has opaque background depends on many factors, e.g. border
// spacing, border collapsing, missing cells, etc.
// For simplicity, just conservatively assume all table rows are not opaque.
bool ForegroundIsKnownToBeOpaqueInRect(const LayoutRect&,
unsigned) const override {
return false;
bool BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const override {
return false;
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override;
void AddOverflowFromCell(const LayoutTableCell*);
bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectTableRow ||
void WillBeRemovedFromTree() override;
void AddChild(LayoutObject* child,
LayoutObject* before_child = nullptr) override;
void UpdateLayout() override;
PaintLayerType LayerTypeRequired() const override {
if (HasTransformRelatedProperty() || HasHiddenBackface() ||
CreatesGroup() || StyleRef().ShouldCompositeForCurrentAnimations() ||
return kNormalPaintLayer;
if (HasOverflowClip())
return kOverflowClipPaintLayer;
return kNoPaintLayer;
void Paint(const PaintInfo&) const override;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
void NextSibling() const = delete;
void PreviousSibling() const = delete;
// This field should never be read directly. It should be read through
// rowIndex() above instead. This is to ensure that we never read this
// value before it is set.
unsigned row_index_ : 31;
inline LayoutTableRow* LayoutTableRow::PreviousRow() const {
return ToLayoutTableRow(LayoutObject::PreviousSibling());
inline LayoutTableRow* LayoutTableRow::NextRow() const {
return ToLayoutTableRow(LayoutObject::NextSibling());
inline LayoutTableRow* LayoutTableSection::FirstRow() const {
return ToLayoutTableRow(FirstChild());
inline LayoutTableRow* LayoutTableSection::LastRow() const {
return ToLayoutTableRow(LastChild());
} // namespace blink