233 lines
12 KiB
C++
233 lines
12 KiB
C++
/*
|
|
* Copyright (C) 2011 Google Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following disclaimer
|
|
* in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Google Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "OrderIterator.h"
|
|
#include "RenderBlock.h"
|
|
|
|
namespace WebCore {
|
|
|
|
class FlexItem;
|
|
|
|
class RenderFlexibleBox : public RenderBlock {
|
|
WTF_MAKE_ISO_ALLOCATED(RenderFlexibleBox);
|
|
public:
|
|
RenderFlexibleBox(Element&, RenderStyle&&);
|
|
RenderFlexibleBox(Document&, RenderStyle&&);
|
|
virtual ~RenderFlexibleBox();
|
|
|
|
bool isFlexibleBox() const override { return true; }
|
|
|
|
const char* renderName() const override;
|
|
|
|
bool avoidsFloats() const final { return true; }
|
|
bool canDropAnonymousBlockChild() const final { return false; }
|
|
void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0_lu) final;
|
|
|
|
LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override;
|
|
std::optional<LayoutUnit> firstLineBaseline() const override;
|
|
std::optional<LayoutUnit> inlineBlockBaseline(LineDirectionMode) const override;
|
|
|
|
void styleDidChange(StyleDifference, const RenderStyle*) override;
|
|
bool hitTestChildren(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint& adjustedLocation, HitTestAction) override;
|
|
void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) override;
|
|
|
|
bool isHorizontalFlow() const;
|
|
|
|
const OrderIterator& orderIterator() const { return m_orderIterator; }
|
|
|
|
bool isTopLayoutOverflowAllowed() const override;
|
|
bool isLeftLayoutOverflowAllowed() const override;
|
|
|
|
virtual bool isFlexibleBoxImpl() const { return false; };
|
|
|
|
bool useChildOverridingLogicalHeightForPercentageResolution(const RenderBox&);
|
|
|
|
void clearCachedMainSizeForChild(const RenderBox& child);
|
|
|
|
LayoutUnit cachedChildIntrinsicContentLogicalHeight(const RenderBox& child) const;
|
|
void setCachedChildIntrinsicContentLogicalHeight(const RenderBox& child, LayoutUnit);
|
|
void clearCachedChildIntrinsicContentLogicalHeight(const RenderBox& child);
|
|
|
|
LayoutUnit staticMainAxisPositionForPositionedChild(const RenderBox&);
|
|
LayoutUnit staticCrossAxisPositionForPositionedChild(const RenderBox&);
|
|
|
|
LayoutUnit staticInlinePositionForPositionedChild(const RenderBox&);
|
|
LayoutUnit staticBlockPositionForPositionedChild(const RenderBox&);
|
|
|
|
// Returns true if the position changed. In that case, the child will have to
|
|
// be laid out again.
|
|
bool setStaticPositionForPositionedLayout(const RenderBox&);
|
|
|
|
protected:
|
|
void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
|
|
|
|
bool shouldResetChildLogicalHeightBeforeLayout(const RenderBox&) const override { return m_shouldResetChildLogicalHeightBeforeLayout; }
|
|
|
|
private:
|
|
enum FlexSign {
|
|
PositiveFlexibility,
|
|
NegativeFlexibility,
|
|
};
|
|
|
|
enum ChildLayoutType { LayoutIfNeeded, ForceLayout, NeverLayout };
|
|
|
|
enum class SizeDefiniteness { Definite, Indefinite, Unknown };
|
|
|
|
// Use an inline capacity of 8, since flexbox containers usually have less than 8 children.
|
|
typedef Vector<LayoutRect, 8> ChildFrameRects;
|
|
|
|
struct LineContext;
|
|
|
|
bool mainAxisIsChildInlineAxis(const RenderBox&) const;
|
|
bool isColumnFlow() const;
|
|
bool isLeftToRightFlow() const;
|
|
bool isMultiline() const;
|
|
Length flexBasisForChild(const RenderBox& child) const;
|
|
Length mainSizeLengthForChild(SizeType, const RenderBox&) const;
|
|
Length crossSizeLengthForChild(SizeType, const RenderBox&) const;
|
|
bool shouldApplyMinSizeAutoForChild(const RenderBox&) const;
|
|
LayoutUnit crossAxisExtentForChild(const RenderBox& child) const;
|
|
LayoutUnit crossAxisIntrinsicExtentForChild(RenderBox& child);
|
|
LayoutUnit childIntrinsicLogicalHeight(RenderBox& child) const;
|
|
LayoutUnit childIntrinsicLogicalWidth(RenderBox& child);
|
|
LayoutUnit mainAxisExtentForChild(const RenderBox& child) const;
|
|
LayoutUnit mainAxisContentExtentForChildIncludingScrollbar(const RenderBox& child) const;
|
|
LayoutUnit crossAxisExtent() const;
|
|
LayoutUnit mainAxisExtent() const;
|
|
LayoutUnit crossAxisContentExtent() const;
|
|
LayoutUnit mainAxisContentExtent(LayoutUnit contentLogicalHeight);
|
|
std::optional<LayoutUnit> computeMainAxisExtentForChild(RenderBox& child, SizeType, const Length& size);
|
|
WritingMode transformedWritingMode() const;
|
|
LayoutUnit flowAwareBorderStart() const;
|
|
LayoutUnit flowAwareBorderEnd() const;
|
|
LayoutUnit flowAwareBorderBefore() const;
|
|
LayoutUnit flowAwareBorderAfter() const;
|
|
LayoutUnit flowAwarePaddingStart() const;
|
|
LayoutUnit flowAwarePaddingEnd() const;
|
|
LayoutUnit flowAwarePaddingBefore() const;
|
|
LayoutUnit flowAwarePaddingAfter() const;
|
|
LayoutUnit flowAwareMarginStartForChild(const RenderBox& child) const;
|
|
LayoutUnit flowAwareMarginEndForChild(const RenderBox& child) const;
|
|
LayoutUnit flowAwareMarginBeforeForChild(const RenderBox& child) const;
|
|
LayoutUnit crossAxisMarginExtentForChild(const RenderBox& child) const;
|
|
LayoutUnit crossAxisScrollbarExtent() const;
|
|
LayoutUnit crossAxisScrollbarExtentForChild(const RenderBox& child) const;
|
|
LayoutPoint flowAwareLocationForChild(const RenderBox& child) const;
|
|
bool childHasComputableAspectRatio(const RenderBox&) const;
|
|
bool childHasComputableAspectRatioAndCrossSizeIsConsideredDefinite(const RenderBox&);
|
|
bool childCrossSizeShouldUseContainerCrossSize(const RenderBox& child) const;
|
|
LayoutUnit computeCrossSizeForChildUsingContainerCrossSize(const RenderBox& child) const;
|
|
void computeChildIntrinsicLogicalWidths(RenderObject&, LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
|
|
LayoutUnit computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const;
|
|
void setFlowAwareLocationForChild(RenderBox& child, const LayoutPoint&);
|
|
LayoutUnit computeInnerFlexBaseSizeForChild(RenderBox& child, LayoutUnit mainAxisBorderAndPadding);
|
|
void adjustAlignmentForChild(RenderBox& child, LayoutUnit);
|
|
ItemPosition alignmentForChild(const RenderBox& child) const;
|
|
bool canComputePercentageFlexBasis(const RenderBox& child, const Length& flexBasis, UpdatePercentageHeightDescendants);
|
|
bool childMainSizeIsDefinite(const RenderBox&, const Length& flexBasis);
|
|
bool childCrossSizeIsDefinite(const RenderBox&, const Length& flexBasis);
|
|
bool needToStretchChildLogicalHeight(const RenderBox& child) const;
|
|
bool childHasIntrinsicMainAxisSize(const RenderBox& child);
|
|
Overflow mainAxisOverflowForChild(const RenderBox& child) const;
|
|
Overflow crossAxisOverflowForChild(const RenderBox& child) const;
|
|
void cacheChildMainSize(const RenderBox& child);
|
|
bool useChildOverridingCrossSizeForPercentageResolution(const RenderBox&);
|
|
bool useChildOverridingMainSizeForPercentageResolution(const RenderBox&);
|
|
|
|
void layoutFlexItems(bool relayoutChildren);
|
|
LayoutUnit autoMarginOffsetInMainAxis(const Vector<FlexItem>&, LayoutUnit& availableFreeSpace);
|
|
void updateAutoMarginsInMainAxis(RenderBox& child, LayoutUnit autoMarginOffset);
|
|
bool hasAutoMarginsInCrossAxis(const RenderBox& child) const;
|
|
bool updateAutoMarginsInCrossAxis(RenderBox& child, LayoutUnit availableAlignmentSpace);
|
|
void repositionLogicalHeightDependentFlexItems(Vector<LineContext>&, LayoutUnit gapBetweenLines);
|
|
LayoutUnit clientLogicalBottomAfterRepositioning();
|
|
|
|
LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, const RenderBox& child);
|
|
LayoutUnit marginBoxAscentForChild(const RenderBox& child);
|
|
|
|
LayoutUnit computeChildMarginValue(Length margin);
|
|
void prepareOrderIteratorAndMargins();
|
|
std::pair<LayoutUnit, LayoutUnit> computeFlexItemMinMaxSizes(RenderBox& child);
|
|
LayoutUnit adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox& child, LayoutUnit childSize);
|
|
FlexItem constructFlexItem(RenderBox&, bool relayoutChildren);
|
|
|
|
void freezeInflexibleItems(FlexSign, Vector<FlexItem>& children, LayoutUnit& remainingFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink);
|
|
bool resolveFlexibleLengths(FlexSign, Vector<FlexItem>&, LayoutUnit initialFreeSpace, LayoutUnit& remainingFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink);
|
|
void freezeViolations(Vector<FlexItem*>&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink);
|
|
|
|
void resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox& child);
|
|
void setOverridingMainSizeForChild(RenderBox&, LayoutUnit);
|
|
void prepareChildForPositionedLayout(RenderBox& child);
|
|
void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, Vector<FlexItem>&, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>&, LayoutUnit gapBetweenItems);
|
|
void layoutColumnReverse(const Vector<FlexItem>&, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace);
|
|
void alignFlexLines(Vector<LineContext>&, LayoutUnit gapBetweenLines);
|
|
void alignChildren(const Vector<LineContext>&);
|
|
void applyStretchAlignmentToChild(RenderBox& child, LayoutUnit lineCrossAxisExtent);
|
|
void flipForRightToLeftColumn(const Vector<LineContext>& lineContexts);
|
|
void flipForWrapReverse(const Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
|
|
|
|
void appendChildFrameRects(ChildFrameRects&);
|
|
void repaintChildrenDuringLayoutIfMoved(const ChildFrameRects&);
|
|
|
|
bool childHasPercentHeightDescendants(const RenderBox&) const;
|
|
|
|
enum class GapType { BetweenLines, BetweenItems };
|
|
LayoutUnit computeGap(GapType) const;
|
|
|
|
// This is used to cache the preferred size for orthogonal flow children so we
|
|
// don't have to relayout to get it
|
|
HashMap<const RenderBox*, LayoutUnit> m_intrinsicSizeAlongMainAxis;
|
|
|
|
// This is used to cache the intrinsic size on the cross axis to avoid
|
|
// relayouts when stretching.
|
|
HashMap<const RenderBox*, LayoutUnit> m_intrinsicContentLogicalHeights;
|
|
|
|
// This set is used to keep track of which children we laid out in this
|
|
// current layout iteration. We need it because the ones in this set may
|
|
// need an additional layout pass for correct stretch alignment handling, as
|
|
// the first layout likely did not use the correct value for percentage
|
|
// sizing of children.
|
|
HashSet<const RenderBox*> m_relaidOutChildren;
|
|
|
|
mutable OrderIterator m_orderIterator { *this };
|
|
int m_numberOfInFlowChildrenOnFirstLine { -1 };
|
|
|
|
// This is SizeIsUnknown outside of layoutBlock()
|
|
SizeDefiniteness m_hasDefiniteHeight { SizeDefiniteness::Unknown };
|
|
bool m_inLayout { false };
|
|
bool m_shouldResetChildLogicalHeightBeforeLayout { false };
|
|
};
|
|
|
|
} // namespace WebCore
|
|
|
|
SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderFlexibleBox, isFlexibleBox())
|