blob: e7fb262fd2b22266f0f8f926fd7ce1936c9d4a2a [file]
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* Copyright (C) 2003-2025 Apple Inc. All rights reserved.
* Copyright (C) 2025 Samuel Weinig <sam@webkit.org>
*
* 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.
*
*/
#pragma once
#include <WebCore/CSSPrimitiveNumeric.h>
#include <WebCore/FontBaseline.h>
#include <WebCore/LayoutRange.h>
#include <WebCore/RenderBoxModelObject.h>
#include <WebCore/RenderOverflow.h>
#include <WebCore/ScrollSnapOffsetsInfo.h>
#include <WebCore/ScrollTypes.h>
#include <WebCore/ShapeOutsideInfo.h>
#include <WebCore/StyleUnevaluatedCalculation.h>
#include <wtf/TypeCasts.h>
namespace WebCore {
class LayoutRoundedRectRadii;
class LocalFrameView;
class RenderBlockFlow;
class RenderBoxFragmentInfo;
class RenderFragmentContainer;
class PositionedLayoutConstraints;
struct PaintInfo;
enum class AvailableLogicalHeightType : bool { ExcludeMarginBorderPadding, IncludeMarginBorderPadding };
enum class StretchingMode { Normal, Explicit };
enum class IsComputingIntrinsicSize : bool { No, Yes };
class RenderBox : public RenderBoxModelObject {
WTF_MAKE_TZONE_ALLOCATED(RenderBox);
WTF_OVERRIDE_DELETE_FOR_CHECKED_PTR(RenderBox);
public:
virtual ~RenderBox();
LayoutUnit x() const { return m_borderBoxRectInContainer.x(); }
LayoutUnit y() const { return m_borderBoxRectInContainer.y(); }
LayoutPoint location() const { return m_borderBoxRectInContainer.location(); }
LayoutSize locationOffset() const { return LayoutSize(x(), y()); }
// These represent your location relative to your container as a physical offset.
// In layout related methods you almost always want the logical location (e.g. x() and y()).
LayoutUnit top() const { return topLeftLocation().y(); }
LayoutUnit left() const { return topLeftLocation().x(); }
LayoutUnit borderBoxWidth() const { return m_borderBoxRectInContainer.width(); }
LayoutUnit borderBoxHeight() const { return m_borderBoxRectInContainer.height(); }
LayoutSize borderBoxSize() const { return m_borderBoxRectInContainer.size(); }
LayoutRect borderBoxRectInContainer() const { return m_borderBoxRectInContainer; }
template<typename T> void setX(T x) { m_borderBoxRectInContainer.setX(x); }
template<typename T> void setY(T y) { m_borderBoxRectInContainer.setY(y); }
template<typename T> void setBorderBoxWidth(T width) { m_borderBoxRectInContainer.setWidth(width); }
template<typename T> void setBorderBoxHeight(T height) { m_borderBoxRectInContainer.setHeight(height); }
void setLocation(const LayoutPoint& location) { m_borderBoxRectInContainer.setLocation(location); }
void setBorderBoxSize(const LayoutSize& size) { m_borderBoxRectInContainer.setSize(size); }
void setBorderBoxInContainer(const LayoutRect& rect) { m_borderBoxRectInContainer = rect; }
void move(LayoutUnit dx, LayoutUnit dy) { m_borderBoxRectInContainer.move(dx, dy); }
inline LayoutUnit logicalLeft() const;
inline LayoutUnit logicalRight() const;
inline LayoutUnit logicalTop() const;
inline LayoutUnit logicalBottom() const;
inline LayoutUnit logicalWidth() const;
inline LayoutUnit logicalHeight() const;
inline LayoutSize logicalSize() const;
inline void setLogicalLeft(LayoutUnit);
inline void setLogicalTop(LayoutUnit);
inline void setLogicalLocation(LayoutPoint);
inline void setLogicalWidth(LayoutUnit);
inline void setLogicalHeight(LayoutUnit);
inline void setLogicalSize(LayoutSize);
inline LayoutRect marginBoxRect() const;
LayoutRect borderBoxRect() const { return { { }, borderBoxSize() }; }
LayoutRect paddingBoxRect() const;
inline LayoutRect contentBoxRect() const;
inline LayoutRect paddingBoxRectIncludingScrollbar() const;
inline LayoutSize contentBoxSize() const;
inline LayoutUnit contentBoxWidth() const;
inline LayoutUnit contentBoxHeight() const;
inline LayoutSize contentBoxLogicalSize() const;
inline LayoutUnit contentBoxLogicalWidth() const;
inline LayoutUnit contentBoxLogicalWidth(LayoutUnit overridingBorderBoxWidth) const;
inline LayoutUnit contentBoxLogicalHeight() const;
inline LayoutUnit contentBoxLogicalHeight(LayoutUnit overridingBorderBoxHeight) const;
inline LayoutUnit paddingBoxWidth() const;
inline LayoutUnit paddingBoxHeight() const;
inline LayoutUnit paddingBoxLogicalWidth() const;
inline LayoutUnit paddingBoxLogicalHeight() const;
inline LayoutUnit paddingBoxLogicalBottom() const;
// The content area of the box (excludes padding - and intrinsic padding for table cells, etc... - and border).
LayoutPoint contentBoxLocation() const;
inline LayoutRect flippedContentBoxRect() const;
// This returns the content area of the box (excluding padding and border). The only difference with contentBoxRect is that computedCSSContentBoxRect
// does include the intrinsic padding in the content box as this is what some callers expect (like getComputedStyle).
inline LayoutRect computedCSSContentBoxRect() const;
// The content box in absolute coords. Ignores transforms.
IntRect absoluteContentBox() const;
// The content box converted to absolute coords (taking transforms into account).
WEBCORE_EXPORT FloatQuad absoluteContentQuad() const;
// https://www.w3.org/TR/css-transforms-1/#reference-box
FloatRect referenceBoxRect(CSSBoxType) const override;
LayoutRect borderBoundingBox() const final { return borderBoxRect(); }
// Don't use this; it doesn't make sense in a future world with corner-shape. Use BorderShape instead.
WEBCORE_EXPORT LayoutRoundedRectRadii borderRadii() const;
// IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
// to return the remaining width on a given line (and the height of a single line).
LayoutUnit offsetWidth() const override { return borderBoxWidth(); }
LayoutUnit offsetHeight() const override { return borderBoxHeight(); }
const LayoutBoxExtent& marginBox() const LIFETIME_BOUND { return m_marginBox; }
LayoutUnit marginTop() const override { return m_marginBox.top(); }
LayoutUnit marginBottom() const override { return m_marginBox.bottom(); }
LayoutUnit marginLeft() const override { return m_marginBox.left(); }
LayoutUnit marginRight() const override { return m_marginBox.right(); }
void setMarginTop(LayoutUnit margin) { m_marginBox.setTop(margin); }
void setMarginBottom(LayoutUnit margin) { m_marginBox.setBottom(margin); }
void setMarginLeft(LayoutUnit margin) { m_marginBox.setLeft(margin); }
void setMarginRight(LayoutUnit margin) { m_marginBox.setRight(margin); }
LayoutUnit marginLogicalLeft(const WritingMode writingMode) const { return m_marginBox.logicalLeft(writingMode); }
LayoutUnit marginLogicalRight(const WritingMode writingMode) const { return m_marginBox.logicalRight(writingMode); }
LayoutUnit marginLogicalLeft() const { return marginLogicalLeft(writingMode()); }
LayoutUnit marginLogicalRight() const { return marginLogicalRight(writingMode()); }
LayoutUnit marginBefore(const WritingMode writingMode) const override { return m_marginBox.before(writingMode); }
LayoutUnit marginAfter(const WritingMode writingMode) const override { return m_marginBox.after(writingMode); }
LayoutUnit marginStart(const WritingMode writingMode) const override { return m_marginBox.start(writingMode); }
LayoutUnit marginEnd(const WritingMode writingMode) const override { return m_marginBox.end(writingMode); }
LayoutUnit marginBefore() const { return marginBefore(writingMode()); }
LayoutUnit marginAfter() const { return marginAfter(writingMode()); }
LayoutUnit marginStart() const { return marginStart(writingMode()); }
LayoutUnit marginEnd() const { return marginEnd(writingMode()); }
inline LayoutUnit marginBoxLogicalHeight(WritingMode) const;
void setMarginBefore(LayoutUnit value, const WritingMode writingMode) { m_marginBox.setBefore(value, writingMode); }
void setMarginAfter(LayoutUnit value, const WritingMode writingMode) { m_marginBox.setAfter(value, writingMode); }
void setMarginStart(LayoutUnit value, const WritingMode writingMode) { m_marginBox.setStart(value, writingMode); }
void setMarginEnd(LayoutUnit value, const WritingMode writingMode) { m_marginBox.setEnd(value, writingMode); }
void setMarginBefore(LayoutUnit value) { setMarginBefore(value, writingMode()); }
void setMarginAfter(LayoutUnit value) { setMarginAfter(value, writingMode()); }
void setMarginStart(LayoutUnit value) { setMarginStart(value, writingMode()); }
void setMarginEnd(LayoutUnit value) { setMarginEnd(value, writingMode()); }
virtual bool isSelfCollapsingBlock() const { return false; }
virtual LayoutUnit collapsedMarginBefore() const { return marginBefore(); }
virtual LayoutUnit collapsedMarginAfter() const { return marginAfter(); }
// Resolve auto margins in the inline direction of the containing block so that objects can be pushed to the start, middle or end
// of the containing block.
void computeInlineDirectionMargins(const RenderBlock& containingBlock, LayoutUnit containerWidth, std::optional<LayoutUnit> availableSpaceAdjustedWithFloats, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const;
// Used to resolve margins in the containing block's block-flow direction.
void computeBlockDirectionMargins(const RenderBlock& containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const;
void computeAndSetBlockDirectionMargins(const RenderBlock& containingBlock);
enum class VisualEffectOverflowOption : uint8_t {
ExcludeFilterOutsets,
};
enum class ComputeOverflowOptions : uint8_t {
None,
RecomputeFloats = 1 << 0,
MarginsExtendContentAreaX = 1 << 1,
MarginsExtendContentAreaY = 1 << 2,
MarginsExtendContentArea = MarginsExtendContentAreaX | MarginsExtendContentAreaY,
MarginsExtendLayoutOverflow = 1 << 3,
};
// Overflow rects are in the coordinate space of the box. This means that they aren't purely physical directions.
// For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
// respectively are flipped when compared to their physical counterparts. For example minX is on the left in vertical-lr,
// but it is on the right in vertical-rl.
WEBCORE_EXPORT LayoutRect flippedPaddingBoxRect() const;
inline const LayoutRect scrollableContentAreaOverflowRect() const;
inline const LayoutRect scrollablePaddingAreaOverflowRect() const;
LayoutRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : flippedPaddingBoxRect(); }
bool hasLayoutOverflow() const;
inline LayoutUnit logicalLeftLayoutOverflow() const;
inline LayoutUnit logicalRightLayoutOverflow() const;
LayoutRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : borderBoxRect(); }
inline LayoutUnit logicalLeftVisualOverflow() const;
inline LayoutUnit logicalRightVisualOverflow() const;
bool hasRenderOverflow() const { return !!m_overflow; }
bool hasVisualOverflow() const { return m_overflow && !borderBoxRect().contains(m_overflow->visualOverflowRect()); }
// RenderBox's basic allowedLayoutOverflow() accounts for the writing mode (only).
virtual LayoutOptionalOutsets allowedLayoutOverflow() const;
LayoutRect clampToAllowedLayoutOverflow(const LayoutRect&, const LayoutRect& flippedPaddingBoxRect);
void addLayoutOverflow(const LayoutRect&);
void addVisualOverflow(const LayoutRect&);
void clearOverflow();
RenderOverflow& ensureOverflow();
void addVisualEffectOverflow();
LayoutRect applyVisualEffectOverflow(const LayoutRect&, EnumSet<VisualEffectOverflowOption> = { }) const;
virtual void addOverflowFromInFlowChildren(OptionSet<ComputeOverflowOptions> = { });
void addOverflowFromContainedBox(const RenderBox& child, OptionSet<ComputeOverflowOptions> = { });
void addOverflowFromFloatBox(const FloatingObject&);
LayoutRect logicalVisualOverflowRectForPropagation(const WritingMode) const;
LayoutRect visualOverflowRectForPropagation(const WritingMode) const;
LayoutRect logicalLayoutOverflowRectForPropagation(const WritingMode) const;
LayoutRect layoutOverflowRectForPropagation(const WritingMode) const;
// scrollWidth/scrollHeight will be the same as paddingBoxWidth/paddingBoxHeight unless the
// object has overflow:hidden/scroll/auto specified and also has overflow.
// scrollLeft/Top return the current scroll position. These methods are virtual so that objects like
// textareas can scroll shadow content (but pretend that they are the objects that are
// scrolling).
virtual int scrollLeft() const;
virtual int scrollTop() const;
virtual int scrollWidth() const;
virtual int scrollHeight() const;
virtual void setScrollLeft(int, const ScrollPositionChangeOptions&);
virtual void setScrollTop(int, const ScrollPositionChangeOptions&);
virtual void setScrollPosition(const ScrollPosition&, const ScrollPositionChangeOptions&);
ScrollPosition scrollPosition() const;
ScrollPosition constrainedScrollPosition() const;
LayoutSize NODELETE cachedSizeForOverflowClip() const;
WEBCORE_EXPORT virtual int verticalScrollbarWidth() const;
WEBCORE_EXPORT virtual int horizontalScrollbarHeight() const;
int intrinsicScrollbarLogicalWidthIncludingGutter() const;
inline int scrollbarLogicalWidth() const;
inline int scrollbarLogicalHeight() const;
bool includeVerticalScrollbarSize() const;
bool includeHorizontalScrollbarSize() const;
bool canUseOverlayScrollbars() const;
bool hasAutoScrollbar(ScrollbarOrientation) const;
bool hasAlwaysPresentScrollbar(ScrollbarOrientation) const;
virtual bool scroll(ScrollDirection, ScrollGranularity, unsigned stepCount = 1, Element** stopElement = nullptr, RenderBox* startBox = nullptr, const IntPoint& wheelEventAbsolutePoint = IntPoint());
virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, unsigned stepCount = 1, Element** stopElement = nullptr);
WEBCORE_EXPORT bool canBeScrolledAndHasScrollableArea() const;
virtual bool canBeProgramaticallyScrolled() const;
virtual void autoscroll(const IntPoint&);
bool canAutoscroll() const;
IntSize calculateAutoscrollDirection(const IntPoint& windowPoint) const;
static RenderBox* findAutoscrollable(RenderObject*);
virtual void stopAutoscroll() { }
virtual void panScroll(const IntPoint&);
bool usesCompositedScrolling() const;
inline bool scrollsOverflow() const;
inline bool scrollsOverflowX() const;
inline bool scrollsOverflowY() const;
inline bool hasHorizontalOverflow() const;
inline bool hasVerticalOverflow() const;
inline bool hasScrollableOverflow() const;
inline bool hasScrollableOverflowX() const;
inline bool hasScrollableOverflowY() const;
inline bool isScrollContainerX() const;
inline bool isScrollContainerY() const;
LayoutBoxExtent scrollPaddingForViewportRect(const LayoutRect& viewportRect);
enum class AllowIntrinsic : bool { No, Yes };
struct ComputedMarginValues {
LayoutUnit before;
LayoutUnit after;
LayoutUnit start;
LayoutUnit end;
};
struct LogicalExtentComputedValues {
LayoutUnit extent;
LayoutUnit position;
ComputedMarginValues margins;
};
enum class UpdatePercentageHeightDescendants : bool { No, Yes };
void layout() override;
// Called when an out-of-flow box moves but doesn't necessarily change size. A simplified layout is attempted
// that just updates the object's position. If the size does change, the object remains dirty.
inline bool tryLayoutDoingOutOfFlowMovementOnly();
virtual void updateLogicalWidth();
void updateLogicalHeight();
virtual LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const;
void computeLogicalWidth(LogicalExtentComputedValues&) const;
void overrideLogicalHeightForSizeContainment();
// This function will compute the logical border-box height, without laying
// out the box. This means that the result is only "correct" when the height
// is explicitly specified. This function exists so that intrinsic width
// calculations have a way to deal with children that have orthogonal writing modes.
// When there is no explicit height, this function assumes a content height of
// zero (and returns just border + padding).
LayoutUnit computeLogicalHeightForIntrinsicWidthContribution() const;
// Computes this box's intrinsic block-axis size (its logical height). A container
// gathering the inline-axis intrinsic contribution of an orthogonal child calls
// this because, for an orthogonal box, the block-axis size is what maps to the
// container's inline axis (CSS Writing Modes 3, orthogonal shrink-to-fit). Unlike
// computeLogicalHeightForIntrinsicWidthContribution() this lays the box out when a
// content-based height is needed, re-arming its dirty bit so the regular layout
// pass runs again afterwards. May lay out the box, hence non-const.
LayoutUnit computeIntrinsicLogicalHeight();
LayoutUnit constrainLogicalWidthByMinMax(LayoutUnit, LayoutUnit, const RenderBlock&, AllowIntrinsic = AllowIntrinsic::Yes) const;
LayoutUnit constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight, IsComputingIntrinsicSize = IsComputingIntrinsicSize::No) const;
LayoutUnit constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
virtual LayoutUnit minContentLogicalWidthContribution() const;
virtual LayoutUnit maxContentLogicalWidthContribution() const;
virtual std::pair<LayoutUnit, LayoutUnit> computeIntrinsicLogicalWidths() const = 0;
virtual LayoutSize intrinsicSize() const { return LayoutSize(); }
LayoutUnit intrinsicLogicalWidth() const;
inline LayoutUnit intrinsicLogicalHeight() const;
// Whether or not the element shrinks to its intrinsic width (rather than filling the width
// of a containing block). HTML4 buttons, <select>s, <input>s, legends, and floating/compact elements do this.
bool sizesLogicalWidthToFitContent() const;
inline bool hasStretchedLogicalHeight(StretchingMode = StretchingMode::Normal) const;
inline bool hasStretchedLogicalWidth(StretchingMode = StretchingMode::Normal) const;
bool isStretchingColumnFlexItem() const;
LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock& containingBlock, std::optional<LayoutUnit> logicalHeight = { }) const;
LayoutUnit computeLogicalWidthUsing(const Style::PreferredSize& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock& containingBlock) const;
LayoutUnit computeLogicalWidthUsing(const Style::MinimumSize& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock& containingBlock) const;
LayoutUnit computeLogicalWidthUsing(const Style::MaximumSize& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock& containingBlock) const;
LayoutUnit computeLogicalWidthUsing(const Style::FlexBasis& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock& containingBlock) const;
std::optional<LayoutUnit> computeLogicalHeightUsing(const Style::PreferredSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computeLogicalHeightUsing(const Style::MinimumSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computeLogicalHeightUsing(const Style::MaximumSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computeContentLogicalHeight(const Style::PreferredSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computeContentLogicalHeight(const Style::MinimumSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computeContentLogicalHeight(const Style::MaximumSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computeContentLogicalHeight(const Style::FlexBasis& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
std::optional<LayoutUnit> computePercentageLogicalHeight(const Style::PreferredSize& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
std::optional<LayoutUnit> computePercentageLogicalHeight(const Style::MinimumSize& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
std::optional<LayoutUnit> computePercentageLogicalHeight(const Style::MaximumSize& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
std::optional<LayoutUnit> computePercentageLogicalHeight(const Style::FlexBasis& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
std::optional<LayoutUnit> computePercentageLogicalHeight(const Style::Percentage<CSS::NonnegativeLayoutUnitClamped, float>& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
std::optional<LayoutUnit> computePercentageLogicalHeight(const Style::UnevaluatedCalculation<CSS::LengthPercentage<CSS::NonnegativeLayoutUnitClamped, float>>& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
bool hasAutoHeightOrContainingBlockWithAutoHeight(UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
virtual LayoutUnit availableLogicalHeight(AvailableLogicalHeightType) const;
LayoutUnit availableLogicalHeightUsing(const Style::PreferredSize&, AvailableLogicalHeightType) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(CSS::Keyword::Stretch, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(CSS::Keyword::MinIntrinsic, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(CSS::Keyword::MaxContent, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(CSS::Keyword::MinContent, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(CSS::Keyword::FitContent, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(const Style::PreferredSize& logicalWidth, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(const Style::MinimumSize& logicalWidth, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(const Style::MaximumSize& logicalWidth, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit computeSizingKeywordLogicalWidthUsing(const Style::FlexBasis& logicalWidth, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
LayoutUnit adjustBorderBoxLogicalWidthForBoxSizing(const Style::Length<CSS::NonnegativeLayoutUnitClamped, float>& logicalWidth) const;
LayoutUnit adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit computedLogicalWidth) const;
LayoutUnit adjustContentBoxLogicalWidthForBoxSizing(const Style::Length<CSS::NonnegativeLayoutUnitClamped, float>& logicalWidth) const;
LayoutUnit adjustContentBoxLogicalWidthForBoxSizing(LayoutUnit computedLogicalWidth) const;
// Overridden by fieldsets to subtract out the intrinsic border.
virtual LayoutUnit adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const;
virtual LayoutUnit adjustContentBoxLogicalHeightForBoxSizing(std::optional<LayoutUnit> height) const;
virtual LayoutUnit adjustIntrinsicLogicalHeightForBoxSizing(LayoutUnit height) const;
std::optional<LayoutUnit> NODELETE overridingBorderBoxLogicalWidth() const;
std::optional<LayoutUnit> NODELETE overridingBorderBoxLogicalHeight() const;
void setOverridingBorderBoxLogicalHeight(LayoutUnit);
void setOverridingBorderBoxLogicalWidth(LayoutUnit);
void clearOverridingBorderBoxLogicalHeight();
void clearOverridingBorderBoxLogicalWidth();
void clearOverridingSize();
// Grid item's containing block is not the grid container, but the grid area, for which we don't have a renderer.
using GridAreaSize = std::optional<LayoutUnit>;
std::optional<GridAreaSize> NODELETE gridAreaContentWidth(WritingMode) const;
std::optional<GridAreaSize> NODELETE gridAreaContentHeight(WritingMode) const;
std::optional<GridAreaSize> NODELETE gridAreaContentLogicalWidth() const;
std::optional<GridAreaSize> NODELETE gridAreaContentLogicalHeight() const;
void setGridAreaContentLogicalWidth(GridAreaSize);
void setGridAreaContentLogicalHeight(GridAreaSize);
void clearGridAreaContentSize();
void clearGridAreaContentLogicalHeight();
// These are currently only used by Flexbox code. In some cases we must layout flex items with a different main size
// (the size in the main direction) than the one specified by the item in order to compute the value of flex basis, i.e.,
// the initial main size of the flex item before the free space is distributed.
std::optional<Style::PreferredSize> NODELETE overridingLogicalHeightForFlexBasisComputation() const;
std::optional<Style::PreferredSize> NODELETE overridingLogicalWidthForFlexBasisComputation() const;
void setOverridingBorderBoxLogicalHeightForFlexBasisComputation(const Style::PreferredSize&);
void setOverridingBorderBoxLogicalWidthForFlexBasisComputation(const Style::PreferredSize&);
void clearOverridingLogicalHeightForFlexBasisComputation();
void clearOverridingLogicalWidthForFlexBasisComputation();
bool percentageLogicalHeightIsResolvable() const;
bool logicalHeightBehavesAsAuto() const;
bool shouldComputeLogicalHeightFromAspectRatio() const;
bool shouldComputeLogicalWidthFromAspectRatio() const;
bool hasFullyConstrainedLogicalHeight() const;
bool NODELETE shouldIgnoreLogicalMinMaxWidthSizes() const;
bool NODELETE shouldIgnoreLogicalMinMaxHeightSizes() const;
// The explicit intrinsic inner size of contain-intrinsic-size
std::optional<LayoutUnit> explicitIntrinsicInnerWidth() const;
std::optional<LayoutUnit> explicitIntrinsicInnerHeight() const;
inline std::optional<LayoutUnit> explicitIntrinsicInnerLogicalWidth() const;
inline std::optional<LayoutUnit> explicitIntrinsicInnerLogicalHeight() const;
virtual bool hasIntrinsicAspectRatio() const { return isBlockLevelReplacedOrAtomicInline() && (isImage() || isRenderVideo() || isRenderHTMLCanvas() || isRenderViewTransitionCapture()); }
virtual std::optional<double> preferredAspectRatio() const;
virtual FloatSize preferredAspectRatioAsSize() const;
inline bool stretchesToViewport() const;
virtual bool shouldInvalidateContentWidths() const;
virtual bool NODELETE hasRelativeDimensions() const;
virtual bool NODELETE hasRelativeLogicalHeight() const;
virtual bool NODELETE hasRelativeLogicalWidth() const;
virtual LayoutRect overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy = OverlayScrollbarSizeRelevancy::IgnoreOverlayScrollbarSize, PaintPhase = PaintPhase::BlockBackground) const;
virtual LayoutRect overflowClipRectForChildLayers(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy) const { return overflowClipRect(location, relevancy); }
LayoutRect clipRect(const LayoutPoint& location) const;
virtual bool hasControlClip() const { return false; }
virtual LayoutRect controlClipRect(const LayoutPoint&) const { return LayoutRect(); }
bool pushContentsClip(PaintInfo&, const LayoutPoint& accumulatedOffset);
void popContentsClip(PaintInfo&, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset);
LayoutRect maskClipRect(const LayoutPoint& paintOffset);
ControlPart* ensureControlPart();
ControlPart* ensureControlPartForRenderer();
ControlPart* ensureControlPartForBorderOnly();
ControlPart* ensureControlPartForDecorations();
virtual void paintObject(PaintInfo&, const LayoutPoint&) { ASSERT_NOT_REACHED(); }
virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
virtual void paintMask(PaintInfo&, const LayoutPoint&);
virtual void paintClippingMask(PaintInfo&, const LayoutPoint&);
void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
virtual void adjustBorderBoxRectForPainting(LayoutRect&) { };
// Returns true if the background is painted opaque in the given rect.
// The query rect is given in local coordinate system.
virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const;
inline bool backgroundIsKnownToBeObscured(const LayoutPoint& paintOffset);
void NODELETE invalidateAncestorBackgroundObscurationStatus();
bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint& accumulatedOffset, HitTestAction) override;
bool hitTestVisualOverflow(const HitTestLocation&, const LayoutPoint& accumulatedOffset) const;
bool hitTestClipPath(const HitTestLocation&, const LayoutPoint& accumulatedOffset) const;
bool hitTestBorderRadius(const HitTestLocation&, const LayoutPoint& accumulatedOffset) const;
PositionWithAffinity positionForPoint(const LayoutPoint&, HitTestSource, const RenderFragmentContainer*) override;
void boundingRects(Vector<LayoutRect>&, const LayoutPoint& accumulatedOffset) const override;
void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
LayoutSize offsetFromContainer(const RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const override;
LayoutUnit offsetLeft() const override;
LayoutUnit offsetTop() const override;
LayoutPoint NODELETE flipForWritingModeForChild(const RenderBox& child, const LayoutPoint&) const;
LayoutUnit NODELETE flipForWritingMode(LayoutUnit position) const; // The offset is in the block direction (y for horizontal writing modes, x for vertical writing modes).
LayoutPoint NODELETE flipForWritingMode(const LayoutPoint&) const;
LayoutSize NODELETE flipForWritingMode(const LayoutSize&) const;
FloatPoint flipForWritingMode(const FloatPoint&) const;
void flipForWritingMode(LayoutRect&) const;
void flipForWritingMode(FloatRect&) const;
void flipForWritingMode(RepaintRects&) const;
// These represent your location relative to your container as a physical offset.
// In layout related methods you almost always want the logical location (e.g. x() and y()).
LayoutPoint topLeftLocation() const; // Defined in RenderBoxInlines.h
LayoutSize topLeftLocationOffset() const; // Defined in RenderBoxInlines.h
LayoutRect applyPaintGeometryTransformToRect(LayoutRect) const;
LayoutRect NODELETE convertRectToParentWritingMode(LayoutRect, const WritingMode parentWritingMode) const;
// Bounds of the outline box in absolute coords. Respects transforms
LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap* = nullptr) const final;
FloatRect repaintRectInLocalCoordinates(RepaintRectCalculation = RepaintRectCalculation::Fast) const override { return borderBoxRect(); }
FloatRect objectBoundingBox() const override { return borderBoxRect(); }
RepaintRects localRectsForRepaint(RepaintOutlineBounds) const override;
std::optional<RepaintRects> computeVisibleRectsInContainer(const RepaintRects&, const RenderLayerModelObject* container, const VisibleRectContext&, VisibleRectState) const override;
void repaintDuringLayoutIfMoved(const LayoutRect&);
virtual void repaintOverhangingFloats(bool paintAllDescendants);
// Returns false if the rect has no intersection with the applied clip rect. When the context specifies edge-inclusive
// intersection, this return value allows distinguishing between no intersection and zero-area intersection.
bool applyCachedClipAndScrollPosition(RepaintRects&, const RenderLayerModelObject* container, const VisibleRectContext&) const final;
enum class RenderBoxFragmentInfoFlags : bool { CacheRenderBoxFragmentInfo, DoNotCacheRenderBoxFragmentInfo };
LayoutUnit containingBlockLogicalWidthForContent() const override;
LayoutUnit containingBlockLogicalHeightForContent(AvailableLogicalHeightType) const;
LayoutRange containingBlockRangeForPositioned(const RenderBoxModelObject& containingBlock, BoxAxis physicalAxis) const;
LayoutUnit containingBlockAvailableLineWidth() const;
LayoutUnit perpendicularContainingBlockLogicalHeight() const;
RenderFragmentContainer* clampToStartAndEndFragments(RenderFragmentContainer*) const;
bool hasFragmentRangeInFragmentedFlow() const;
virtual LayoutUnit offsetFromLogicalTopOfFirstPage() const;
RenderBoxFragmentInfo* NODELETE renderBoxFragmentInfo(RenderFragmentContainer*, RenderBoxFragmentInfoFlags = RenderBoxFragmentInfoFlags::CacheRenderBoxFragmentInfo) const;
// True if this box can have a range in an outside fragmentation context.
bool canHaveOutsideFragmentRange() const { return !isRenderFragmentedFlow(); }
virtual bool needsLayoutAfterFragmentRangeChange() const { return false; }
bool hasUnsplittableScrollingOverflow() const;
bool isUnsplittableForPagination() const;
virtual void markForPaginationRelayoutIfNeeded() { }
// Note these functions are not equivalent of childrenOfType<RenderBox>
RenderBox* parentBox() const;
RenderBox* firstChildBox() const;
RenderBox* firstInFlowChildBox() const;
RenderBox* lastChildBox() const;
RenderBox* lastInFlowChildBox() const;
RenderBox* previousSiblingBox() const;
RenderBox* previousInFlowSiblingBox() const;
RenderBox* nextSiblingBox() const;
RenderBox* nextInFlowSiblingBox() const;
int reflectionOffset() const;
// Given a rect in the object's coordinate space, returns the corresponding rect in the reflection.
LayoutRect reflectedRect(const LayoutRect&) const;
void removeFloatingAndInvalidateForLayout();
void removeFloatingOrOutOfFlowChildFromBlockLists();
virtual std::optional<LayoutUnit> firstLineBaseline() const { return { }; }
virtual std::optional<LayoutUnit> lastLineBaseline() const { return { }; }
bool shrinkToAvoidFloats() const;
bool avoidsFloats() const;
LayoutUnit lineHeight() const;
inline void markShapeOutsideDependentsForLayout();
bool isGridItem() const { return parent() && parent()->isRenderGrid() && !isExcludedFromNormalLayout(); }
bool isFlexItem() const { return parent() && parent()->isRenderFlexibleBox() && !isExcludedFromNormalLayout(); }
inline bool isColumnSpanner() const;
void applyTransform(TransformationMatrix&, const Style::ComputedStyle&, const FloatRect& boundingBox, OptionSet<Style::TransformResolverOption>) const override;
bool NODELETE computeHasTransformRelatedProperty(const Style::ComputedStyle&) const;
void updateFloatPainterAfterSelfPaintingLayerChange();
ShapeOutsideInfo* shapeOutsideInfo() const LIFETIME_BOUND;
bool requiresLayer() const override;
bool NODELETE requiresLayerWithScrollableArea() const;
protected:
RenderBox(Type, Element&, Style::ComputedStyle&&, OptionSet<TypeFlag> = { }, TypeSpecificFlags = { });
RenderBox(Type, Document&, Style::ComputedStyle&&, OptionSet<TypeFlag> = { }, TypeSpecificFlags = { });
void styleWillChange(Style::Difference, const Style::ComputedStyle& newStyle) override;
void styleDidChange(Style::Difference, const Style::ComputedStyle* oldStyle) override;
void updateFromStyle() override;
void willBeDestroyed() override;
virtual bool NODELETE shouldResetLogicalHeightBeforeLayout() const;
void NODELETE resetLogicalHeightBeforeLayoutIfNeeded();
// Returns false if it could not cheaply compute the extent (e.g. fixed background), in which case the returned rect may be incorrect.
bool getBackgroundPaintedExtent(const LayoutPoint& paintOffset, LayoutRect&) const;
virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const;
virtual bool computeBackgroundIsKnownToBeObscured(const LayoutPoint& paintOffset);
void paintMaskImages(const PaintInfo&, const LayoutRect&);
void clipToPaddingBoxShape(GraphicsContext&, const LayoutPoint&, float deviceScaleFactor) const;
void clipToContentBoxShape(GraphicsContext&, const LayoutPoint&, float deviceScaleFactor) const;
BleedAvoidance determineBleedAvoidance(GraphicsContext&) const;
bool backgroundHasOpaqueTopLayer() const;
void computeOutOfFlowPositionedLogicalWidth(LogicalExtentComputedValues&) const;
std::optional<LayoutUnit> computeSizingKeywordLogicalContentHeightUsing(const Style::PreferredSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const;
std::optional<LayoutUnit> computeSizingKeywordLogicalContentHeightUsing(const Style::MinimumSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const;
std::optional<LayoutUnit> computeSizingKeywordLogicalContentHeightUsing(const Style::MaximumSize& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const;
std::optional<LayoutUnit> computeSizingKeywordLogicalContentHeightUsing(const Style::FlexBasis& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const;
LayoutRect localOutlineBoundsRepaintRect() const;
void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const override;
const RenderElement* pushMappingToContainer(const RenderLayerModelObject*, RenderGeometryMap&) const override;
void mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode>, TransformState&) const override;
bool skipContainingBlockForPercentHeightCalculation(const RenderBox& containingBlock, bool isPerpendicularWritingMode) const;
void incrementVisuallyNonEmptyPixelCountIfNeeded(const IntSize&);
bool NODELETE shouldIgnoreAspectRatio() const;
// -webkit-fill-available always resolves through the containing-block chain (walking up to the
// viewport if needed), so it is considered resolvable regardless of whether the immediate CB has
// a definite block size. Only the spec stretch keyword is gated on `isBlockSizeResolvableForStretch`.
bool isResolveableStretchSize(const auto& size) const { return size.isStretch() && (size.isFillAvailable() || isBlockSizeResolvableForStretch()); }
bool isUnresolveableStretchSize(const auto& size) const { return size.isStretch() && !size.isFillAvailable() && !isBlockSizeResolvableForStretch(); }
LayoutUnit computeLogicalWidthFromAspectRatio() const;
void applyAutomaticContentBasedMinimumSize(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
void applyTransferredMinMaxSizesFromAspectRatio(LayoutUnit& minContentLogicalWidth, LayoutUnit& maxContentLogicalWidth) const;
std::pair<LayoutUnit, LayoutUnit> computeMinMaxLogicalWidthFromAspectRatio() const;
std::pair<LayoutUnit, LayoutUnit> computeMinMaxLogicalHeightFromAspectRatio() const;
enum class ConstrainDimension { Width, Height };
enum class MinimumSizeIsAutomaticContentBased : bool { No, Yes };
void constrainLogicalMinMaxSizesByAspectRatio(LayoutUnit& minSize, LayoutUnit& maxSize, LayoutUnit computedSize, MinimumSizeIsAutomaticContentBased, ConstrainDimension) const;
static LayoutUnit blockSizeFromAspectRatio(LayoutUnit borderPaddingInlineSum, LayoutUnit borderPaddingBlockSum, double aspectRatioValue, BoxSizing, LayoutUnit inlineSize, const Style::AspectRatio&, bool isRenderReplaced);
void constrainIntrinsicLogicalWidthsByMinMax(LayoutUnit& minIntrinsicLogicalWidth, LayoutUnit& maxIntrinsicLogicalWidth) const;
bool isAspectRatioDegenerate(double aspectRatio) const { return !aspectRatio || isnan(aspectRatio); }
LayoutUnit fillAvailableMeasure(LayoutUnit availableLogicalWidth) const;
LayoutUnit fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const;
bool overflowChangesMayAffectLayout() const final;
virtual std::pair<LayoutUnit, LayoutUnit> computeIntrinsicKeywordLogicalWidths() const { return computeIntrinsicLogicalWidths(); }
private:
bool isBlockSizeResolvableForStretch() const;
void addOverflowWithRendererOffset(const RenderBox&, LayoutSize, OptionSet<ComputeOverflowOptions> = { });
void addMarginBoxOverflow(const RenderBox&, LayoutSize offsetFromThis, OptionSet<ComputeOverflowOptions>);
void updateShapeOutsideInfoAfterStyleChange(const Style::ComputedStyle&, const Style::ComputedStyle* oldStyle, Style::Difference);
void updateGridPositionAfterStyleChange(const Style::ComputedStyle&, const Style::ComputedStyle* oldStyle);
bool scrollLayer(ScrollDirection, ScrollGranularity, unsigned stepCount, Element** stopElement);
bool fixedElementLaysOutRelativeToFrame(const LocalFrameView&) const;
bool isScrollableOrRubberbandableBox() const override;
// Returns true if we did a full repaint.
template<typename Layers> bool repaintLayerRectsForImage(WrappedImagePtr, const Layers&, Style::ZoomFactor, bool drawingBackground);
void computeOutOfFlowPositionedLogicalHeight(LogicalExtentComputedValues&) const;
template<typename SizeType> LayoutUnit computeOutOfFlowPositionedLogicalWidthUsing(const SizeType&, const PositionedLayoutConstraints&) const;
LayoutUnit computeOutOfFlowPositionedLogicalHeightUsing(const Style::PreferredSize& logicalHeight, LayoutUnit computedHeight, const PositionedLayoutConstraints& blockConstraints) const;
LayoutUnit computeOutOfFlowPositionedLogicalHeightUsing(const Style::MinimumSize& logicalHeight, LayoutUnit computedHeight, const PositionedLayoutConstraints& blockConstraints) const;
LayoutUnit computeOutOfFlowPositionedLogicalHeightUsing(const Style::MaximumSize& logicalHeight, LayoutUnit computedHeight, const PositionedLayoutConstraints& blockConstraints) const;
template<typename Keyword> std::pair<LayoutUnit, LayoutUnit> computeIntrinsicKeywordLogicalWidths(Keyword, LayoutUnit borderAndPadding) const;
template<typename SizeType> LayoutUnit computeLogicalWidthUsingGeneric(const SizeType& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock& containingBlock) const;
template<typename SizeType> LayoutUnit computeSizingKeywordLogicalWidthUsingGeneric(const SizeType& logicalWidth, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
template<typename SizeType> std::optional<LayoutUnit> computeLogicalHeightUsingGeneric(const SizeType& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
template<typename SizeType> std::optional<LayoutUnit> computeSizingKeywordLogicalContentHeightUsingGeneric(const SizeType& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const;
template<typename SizeType> std::optional<LayoutUnit> computePercentageLogicalHeightGeneric(const SizeType& logicalHeight, UpdatePercentageHeightDescendants = UpdatePercentageHeightDescendants::Yes) const;
template<typename SizeType> std::optional<LayoutUnit> computeContentLogicalHeightGeneric(const SizeType& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
template<typename SizeType> std::optional<LayoutUnit> computeContentAndScrollbarLogicalHeightUsing(const SizeType& logicalHeight, std::optional<LayoutUnit> intrinsicContentHeight) const;
LayoutUnit blockAxisMarginForStretch() const;
// This function calculates the minimum and maximum preferred widths for an object.
// These values are used in shrink-to-fit layout systems.
// These include tables, positioned objects, floats and flexible boxes.
virtual void computeIntrinsicLogicalWidthContributions();
LayoutRect frameRectForStickyPositioning() const override { return borderBoxRectInContainer(); }
RepaintRects computeVisibleRectsUsingPaintOffset(const RepaintRects&) const;
LayoutPoint topLeftLocationWithFlipping() const;
ShapeOutsideInfo& ensureShapeOutsideInfo();
void removeShapeOutsideInfo();
private:
// Relative to our container.
LayoutRect m_borderBoxRectInContainer;
protected:
LayoutBoxExtent m_marginBox;
// The min-content contribution: the box's min-content size after its CSS width and min/max-width have been applied.
LayoutUnit m_minContentLogicalWidthContribution;
// The max-content contribution: the box's max-content size after its CSS width and min/max-width have been applied.
LayoutUnit m_maxContentLogicalWidthContribution;
// Our overflow information.
std::unique_ptr<RenderOverflow> m_overflow;
private:
// Used to store state between styleWillChange and styleDidChange
static bool s_hadNonVisibleOverflow;
};
inline bool isSkippedContentRoot(const RenderBox&);
inline RenderBox* RenderBox::parentBox() const
{
if (auto* box = dynamicDowncast<RenderBox>(parent()))
return box;
ASSERT(!parent());
return nullptr;
}
inline RenderBox* RenderBox::firstChildBox() const
{
if (CheckedPtr box = dynamicDowncast<RenderBox>(firstChild()))
return box.unsafeGet();
ASSERT(!firstChild());
return nullptr;
}
inline RenderBox* RenderBox::firstInFlowChildBox() const
{
return dynamicDowncast<RenderBox>(firstInFlowChild());
}
inline RenderBox* RenderBox::lastChildBox() const
{
if (CheckedPtr box = dynamicDowncast<RenderBox>(lastChild()))
return box.unsafeGet();
ASSERT(!lastChild());
return nullptr;
}
inline RenderBox* RenderBox::lastInFlowChildBox() const
{
return dynamicDowncast<RenderBox>(lastInFlowChild());
}
inline RenderBox* RenderBox::previousSiblingBox() const
{
if (CheckedPtr box = dynamicDowncast<RenderBox>(previousSibling()))
return box.unsafeGet();
ASSERT(!previousSibling());
return nullptr;
}
inline RenderBox* RenderBox::previousInFlowSiblingBox() const
{
for (CheckedPtr curr = previousSiblingBox(); curr; curr = curr->previousSiblingBox()) {
if (!curr->isFloatingOrOutOfFlowPositioned())
return curr.unsafeGet();
}
return nullptr;
}
inline RenderBox* RenderBox::nextSiblingBox() const
{
if (CheckedPtr box = dynamicDowncast<RenderBox>(nextSibling()))
return box.unsafeGet();
ASSERT(!nextSibling());
return nullptr;
}
inline RenderBox* RenderBox::nextInFlowSiblingBox() const
{
for (CheckedPtr curr = nextSiblingBox(); curr; curr = curr->nextSiblingBox()) {
if (!curr->isFloatingOrOutOfFlowPositioned())
return curr.unsafeGet();
}
return nullptr;
}
} // namespace WebCore
SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderBox, isRenderBox())