#include "config.h"
#include "LayoutBox.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "RenderStyle.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
namespace Layout {
WTF_MAKE_ISO_ALLOCATED_IMPL(Box);
Box::Box(std::optional<ElementAttributes> attributes, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
: m_style(WTFMove(style))
, m_elementAttributes(attributes)
, m_baseTypeFlags(baseTypeFlags)
{
}
Box::~Box()
{
}
bool Box::establishesFormattingContext() const
{
return establishesBlockFormattingContext() || establishesInlineFormattingContext();
}
bool Box::establishesBlockFormattingContext() const
{
if (!parent())
return true;
if (isFloatingPositioned() || isAbsolutelyPositioned())
return true;
if (isBlockContainerBox() && !isBlockLevelBox())
return true;
if (isBlockLevelBox() && !isOverflowVisible())
return true;
return false;
}
bool Box::isRelativelyPositioned() const
{
return m_style.position() == PositionType::Relative;
}
bool Box::isStickyPositioned() const
{
return m_style.position() == PositionType::Sticky;
}
bool Box::isAbsolutelyPositioned() const
{
return m_style.position() == PositionType::Absolute || isFixedPositioned();
}
bool Box::isFixedPositioned() const
{
return m_style.position() == PositionType::Fixed;
}
bool Box::isFloatingPositioned() const
{
return m_style.floating() != Float::No;
}
const Container* Box::containingBlock() const
{
if (!parent())
return nullptr;
if (!isPositioned() || isInFlowPositioned()) {
auto* nearestBlockContainer = parent();
for (; nearestBlockContainer->parent() && !nearestBlockContainer->isBlockContainerBox(); nearestBlockContainer = nearestBlockContainer->parent()) { }
return nearestBlockContainer;
}
if (isFixedPositioned()) {
auto* initialContainingBlock = parent();
for (; initialContainingBlock->parent(); initialContainingBlock = initialContainingBlock->parent()) { }
return initialContainingBlock;
}
if (isOutOfFlowPositioned()) {
auto* positionedAncestor = parent();
for (; positionedAncestor->parent() && !positionedAncestor->isPositioned(); positionedAncestor = positionedAncestor->parent()) { }
return positionedAncestor;
}
ASSERT_NOT_REACHED();
return nullptr;
}
const Container& Box::formattingContextRoot() const
{
for (auto* ancestor = containingBlock(); ancestor; ancestor = ancestor->containingBlock()) {
if (ancestor->establishesFormattingContext())
return *ancestor;
}
if (isInitialContainingBlock())
return downcast<Container>(*this);
RELEASE_ASSERT_NOT_REACHED();
}
bool Box::isDescendantOf(Container& container) const
{
for (auto* ancestor = containingBlock(); ancestor; ancestor = ancestor->containingBlock()) {
if (ancestor == &container)
return true;
}
return false;
}
bool Box::isInlineBlockBox() const
{
return m_style.display() == DisplayType::InlineBlock;
}
bool Box::isBlockLevelBox() const
{
auto display = m_style.display();
return display == DisplayType::Block || display == DisplayType::ListItem || display == DisplayType::Table;
}
bool Box::isInlineLevelBox() const
{
auto display = m_style.display();
return display == DisplayType::Inline || display == DisplayType::InlineBlock || display == DisplayType::InlineTable;
}
bool Box::isBlockContainerBox() const
{
auto display = m_style.display();
return display == DisplayType::Block || display == DisplayType::ListItem || display == DisplayType::InlineBlock || display == DisplayType::TableCell || display == DisplayType::TableCaption; }
bool Box::isInitialContainingBlock() const
{
return !parent();
}
const Box* Box::nextInFlowSibling() const
{
if (auto* nextSibling = this->nextSibling()) {
if (nextSibling->isInFlow())
return nextSibling;
return nextSibling->nextInFlowSibling();
}
return nullptr;
}
const Box* Box::nextInFlowOrFloatingSibling() const
{
if (auto* nextSibling = this->nextSibling()) {
if (nextSibling->isInFlow() || nextSibling->isFloatingPositioned())
return nextSibling;
return nextSibling->nextInFlowSibling();
}
return nullptr;
}
const Box* Box::previousInFlowSibling() const
{
if (auto* previousSibling = this->previousSibling()) {
if (previousSibling->isInFlow())
return previousSibling;
return previousSibling->previousInFlowSibling();
}
return nullptr;
}
const Box* Box::previousInFlowOrFloatingSibling() const
{
if (auto* previousSibling = this->previousSibling()) {
if (previousSibling->isInFlow() || previousSibling->isFloatingPositioned())
return previousSibling;
return previousSibling->previousInFlowOrFloatingSibling();
}
return nullptr;
}
bool Box::isOverflowVisible() const
{
return m_style.overflowX() == Overflow::Visible || m_style.overflowY() == Overflow::Visible;
}
bool Box::isPaddingApplicable() const
{
if (isAnonymous())
return false;
auto elementType = m_elementAttributes.value().elementType;
return elementType != ElementType::TableRowGroup
&& elementType != ElementType::TableHeaderGroup
&& elementType != ElementType::TableFooterGroup
&& elementType != ElementType::TableRow
&& elementType != ElementType::TableColumnGroup
&& elementType != ElementType::TableColumn;
}
}
}
#endif