blob: e6cfb7e9ce05da7a4730731604ff2b650e3b7053 [file] [log] [blame]
/*
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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.
*/
#ifndef LayoutTableRow_h
#define LayoutTableRow_h
#include "core/CoreExport.h"
#include "core/layout/LayoutTableSection.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 {
public:
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 {
DCHECK(RowIndexWasSet());
DCHECK(
!Section() ||
!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;
private:
void AddOverflowFromCell(const LayoutTableCell*);
bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectTableRow ||
LayoutTableBoxComponent::IsOfType(type);
}
void WillBeRemovedFromTree() override;
void AddChild(LayoutObject* child,
LayoutObject* before_child = nullptr) override;
void UpdateLayout() override;
PaintLayerType LayerTypeRequired() const override {
if (HasTransformRelatedProperty() || HasHiddenBackface() || HasClipPath() ||
CreatesGroup() || Style()->ShouldCompositeForCurrentAnimations() ||
IsStickyPositioned())
return kNormalPaintLayer;
if (HasOverflowClip())
return kOverflowClipPaintLayer;
return kNoPaintLayer;
}
void Paint(const PaintInfo&, const LayoutPoint&) 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;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutTableRow, IsTableRow());
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
#endif // LayoutTableRow_h