1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* struct containing the input to nsIFrame::Reflow */
9 #ifndef mozilla_ReflowInput_h
10 #define mozilla_ReflowInput_h
13 #include "nsStyleConsts.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/EnumSet.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/WritingModes.h"
18 #include "LayoutConstants.h"
19 #include "ReflowOutput.h"
24 struct nsHypotheticalPosition
;
25 class nsIPercentBSizeObserver
;
27 class nsPlaceholderFrame
;
32 enum class LayoutFrameType
: uint8_t;
35 * A set of StyleSizes used as an input parameter to various functions that
36 * compute sizes like nsIFrame::ComputeSize(). If any of the member fields has a
37 * value, the function may use the value instead of retrieving it from the
40 * The logical sizes are assumed to be in the associated frame's writing-mode.
42 struct StyleSizeOverrides
{
43 Maybe
<StyleSize
> mStyleISize
;
44 Maybe
<StyleSize
> mStyleBSize
;
45 Maybe
<AspectRatio
> mAspectRatio
;
47 bool HasAnyOverrides() const { return mStyleISize
|| mStyleBSize
; }
48 bool HasAnyLengthOverrides() const {
49 return (mStyleISize
&& mStyleISize
->ConvertsToLength()) ||
50 (mStyleBSize
&& mStyleBSize
->ConvertsToLength());
53 // By default, table wrapper frame considers the size overrides applied to
54 // itself, so it creates any length size overrides for inner table frame by
55 // subtracting the area occupied by the caption and border & padding according
58 // When this flag is true, table wrapper frame is required to apply the size
59 // overrides to the inner table frame directly, without any modification,
60 // which is useful for flex container to override the inner table frame's
61 // preferred main size with 'flex-basis'.
63 // Note: if mStyleISize is a LengthPercentage, the inner table frame will
64 // comply with the inline-size override without enforcing its min-content
65 // inline-size in nsTableFrame::ComputeSize(). This is necessary so that small
66 // flex-basis values like 'flex-basis:1%' can be resolved correctly; the
67 // flexbox layout algorithm does still explicitly clamp to min-sizes *at a
68 // later step*, after the flex-basis has been resolved -- so this flag won't
69 // actually produce any user-visible tables whose final inline size is smaller
70 // than their min-content inline size.
71 bool mApplyOverridesVerbatim
= false;
73 } // namespace mozilla
76 * @return aValue clamped to [aMinValue, aMaxValue].
78 * @note This function needs to handle aMinValue > aMaxValue. In that case,
79 * aMinValue is returned.
80 * @see http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
81 * @see http://www.w3.org/TR/CSS21/visudet.html#min-max-heights
83 template <class NumericType
>
84 NumericType
NS_CSS_MINMAX(NumericType aValue
, NumericType aMinValue
,
85 NumericType aMaxValue
) {
86 NumericType result
= aValue
;
87 if (aMaxValue
< result
) result
= aMaxValue
;
88 if (aMinValue
> result
) result
= aMinValue
;
94 // A base class of ReflowInput that computes only the padding,
95 // border, and margin, since those values are needed more often.
96 struct SizeComputationInput
{
98 // The frame being reflowed.
101 // Rendering context to use for measurement.
102 gfxContext
* mRenderingContext
;
104 nsMargin
ComputedPhysicalMargin() const {
105 return mComputedMargin
.GetPhysicalMargin(mWritingMode
);
107 nsMargin
ComputedPhysicalBorderPadding() const {
108 return mComputedBorderPadding
.GetPhysicalMargin(mWritingMode
);
110 nsMargin
ComputedPhysicalPadding() const {
111 return mComputedPadding
.GetPhysicalMargin(mWritingMode
);
114 mozilla::LogicalMargin
ComputedLogicalMargin(mozilla::WritingMode aWM
) const {
115 return mComputedMargin
.ConvertTo(aWM
, mWritingMode
);
117 mozilla::LogicalMargin
ComputedLogicalBorderPadding(
118 mozilla::WritingMode aWM
) const {
119 return mComputedBorderPadding
.ConvertTo(aWM
, mWritingMode
);
121 mozilla::LogicalMargin
ComputedLogicalPadding(
122 mozilla::WritingMode aWM
) const {
123 return mComputedPadding
.ConvertTo(aWM
, mWritingMode
);
126 void SetComputedLogicalMargin(mozilla::WritingMode aWM
,
127 const mozilla::LogicalMargin
& aMargin
) {
128 mComputedMargin
= aMargin
.ConvertTo(mWritingMode
, aWM
);
130 void SetComputedLogicalBorderPadding(
131 mozilla::WritingMode aWM
, const mozilla::LogicalMargin
& aBorderPadding
) {
132 mComputedBorderPadding
= aBorderPadding
.ConvertTo(mWritingMode
, aWM
);
134 void SetComputedLogicalPadding(mozilla::WritingMode aWM
,
135 const mozilla::LogicalMargin
& aPadding
) {
136 mComputedPadding
= aPadding
.ConvertTo(mWritingMode
, aWM
);
139 mozilla::WritingMode
GetWritingMode() const { return mWritingMode
; }
142 // cached copy of the frame's writing-mode, for logical coordinates
143 mozilla::WritingMode mWritingMode
;
145 // Computed margin values
146 mozilla::LogicalMargin mComputedMargin
;
148 // Cached copy of the border + padding values
149 mozilla::LogicalMargin mComputedBorderPadding
;
151 // Computed padding values
152 mozilla::LogicalMargin mComputedPadding
;
155 // Callers using this constructor must call InitOffsets on their own.
156 SizeComputationInput(nsIFrame
* aFrame
, gfxContext
* aRenderingContext
);
158 SizeComputationInput(nsIFrame
* aFrame
, gfxContext
* aRenderingContext
,
159 mozilla::WritingMode aContainingBlockWritingMode
,
160 nscoord aContainingBlockISize
,
161 const mozilla::Maybe
<mozilla::LogicalMargin
>& aBorder
=
163 const mozilla::Maybe
<mozilla::LogicalMargin
>& aPadding
=
167 // Reflow trace methods. Defined in nsFrame.cpp so they have access
168 // to the display-reflow infrastructure.
169 static void* DisplayInitOffsetsEnter(nsIFrame
* aFrame
,
170 SizeComputationInput
* aState
,
171 nscoord aPercentBasis
,
172 mozilla::WritingMode aCBWritingMode
,
173 const nsMargin
* aBorder
,
174 const nsMargin
* aPadding
);
175 static void DisplayInitOffsetsExit(nsIFrame
* aFrame
,
176 SizeComputationInput
* aState
,
182 * Computes margin values from the specified margin style information, and
183 * fills in the mComputedMargin member.
185 * @param aCBWM Writing mode of the containing block
186 * @param aPercentBasis
187 * Inline size of the containing block (in its own writing mode), to use
188 * for resolving percentage margin values in the inline and block axes.
189 * @return true if the margin is dependent on the containing block size.
191 bool ComputeMargin(mozilla::WritingMode aCBWM
, nscoord aPercentBasis
,
192 mozilla::LayoutFrameType aFrameType
);
195 * Computes padding values from the specified padding style information, and
196 * fills in the mComputedPadding member.
198 * @param aCBWM Writing mode of the containing block
199 * @param aPercentBasis
200 * Inline size of the containing block (in its own writing mode), to use
201 * for resolving percentage padding values in the inline and block axes.
202 * @return true if the padding is dependent on the containing block size.
204 bool ComputePadding(mozilla::WritingMode aCBWM
, nscoord aPercentBasis
,
205 mozilla::LayoutFrameType aFrameType
);
208 void InitOffsets(mozilla::WritingMode aCBWM
, nscoord aPercentBasis
,
209 mozilla::LayoutFrameType aFrameType
,
210 mozilla::ComputeSizeFlags aFlags
= {},
211 const mozilla::Maybe
<mozilla::LogicalMargin
>& aBorder
=
213 const mozilla::Maybe
<mozilla::LogicalMargin
>& aPadding
=
215 const nsStyleDisplay
* aDisplay
= nullptr);
218 * Convert StyleSize or StyleMaxSize to nscoord when percentages depend on the
219 * inline size of the containing block, and enumerated values are for inline
220 * size, min-inline-size, or max-inline-size. Does not handle auto inline
223 template <typename SizeOrMaxSize
>
224 inline nscoord
ComputeISizeValue(const WritingMode aWM
,
225 const LogicalSize
& aContainingBlockSize
,
226 const LogicalSize
& aContentEdgeToBoxSizing
,
227 nscoord aBoxSizingToMarginEdge
,
228 const SizeOrMaxSize
&) const;
229 // same as previous, but using mComputedBorderPadding, mComputedPadding,
230 // and mComputedMargin
231 template <typename SizeOrMaxSize
>
232 inline nscoord
ComputeISizeValue(const LogicalSize
& aContainingBlockSize
,
233 mozilla::StyleBoxSizing aBoxSizing
,
234 const SizeOrMaxSize
&) const;
236 nscoord
ComputeBSizeValue(nscoord aContainingBlockBSize
,
237 mozilla::StyleBoxSizing aBoxSizing
,
238 const mozilla::LengthPercentage
& aCoord
) const;
242 * State passed to a frame during reflow or intrinsic size calculation.
244 * XXX Refactor so only a base class (nsSizingState?) is used for intrinsic
247 * @see nsIFrame#Reflow()
249 struct ReflowInput
: public SizeComputationInput
{
250 // the reflow inputs are linked together. this is the pointer to the
251 // parent's reflow input
252 const ReflowInput
* mParentReflowInput
= nullptr;
254 // A non-owning pointer to the float manager associated with this area,
255 // which points to the object owned by nsAutoFloatManager::mNew.
256 nsFloatManager
* mFloatManager
= nullptr;
258 // LineLayout object (only for inline reflow; set to nullptr otherwise)
259 nsLineLayout
* mLineLayout
= nullptr;
261 // The appropriate reflow input for the containing block (for
262 // percentage widths, etc.) of this reflow input's frame. It will be setup
263 // properly in InitCBReflowInput().
264 const ReflowInput
* mCBReflowInput
= nullptr;
266 // The amount the in-flow position of the block is moving vertically relative
267 // to its previous in-flow position (i.e. the amount the line containing the
269 // This should be zero for anything which is not a block outside, and it
270 // should be zero for anything which has a non-block parent.
271 // The intended use of this value is to allow the accurate determination
272 // of the potential impact of a float
273 // This takes on an arbitrary value the first time a block is reflowed
274 nscoord mBlockDelta
= 0;
276 // If a ReflowInput finds itself initialized with an unconstrained
277 // inline-size, it will look up its parentReflowInput chain for a reflow input
278 // with an orthogonal writing mode and a non-NS_UNCONSTRAINEDSIZE value for
279 // orthogonal limit; when it finds such a reflow input, it will use its
280 // orthogonal-limit value to constrain inline-size.
281 // This is initialized to NS_UNCONSTRAINEDSIZE (so it will be ignored),
282 // but reset to a suitable value for the reflow root by PresShell.
283 nscoord mOrthogonalLimit
= NS_UNCONSTRAINEDSIZE
;
285 // Physical accessors for the private fields. They are needed for
286 // compatibility with not-yet-updated code. New code should use the accessors
287 // for logical coordinates, unless the code really works on physical
289 nscoord
AvailableWidth() const { return mAvailableSize
.Width(mWritingMode
); }
290 nscoord
AvailableHeight() const {
291 return mAvailableSize
.Height(mWritingMode
);
293 nscoord
ComputedWidth() const { return mComputedSize
.Width(mWritingMode
); }
294 nscoord
ComputedHeight() const { return mComputedSize
.Height(mWritingMode
); }
295 nscoord
ComputedMinWidth() const {
296 return mComputedMinSize
.Width(mWritingMode
);
298 nscoord
ComputedMaxWidth() const {
299 return mComputedMaxSize
.Width(mWritingMode
);
301 nscoord
ComputedMinHeight() const {
302 return mComputedMinSize
.Height(mWritingMode
);
304 nscoord
ComputedMaxHeight() const {
305 return mComputedMaxSize
.Height(mWritingMode
);
308 // Logical accessors for private fields in mWritingMode.
309 nscoord
AvailableISize() const { return mAvailableSize
.ISize(mWritingMode
); }
310 nscoord
AvailableBSize() const { return mAvailableSize
.BSize(mWritingMode
); }
311 nscoord
ComputedISize() const { return mComputedSize
.ISize(mWritingMode
); }
312 nscoord
ComputedBSize() const { return mComputedSize
.BSize(mWritingMode
); }
313 nscoord
ComputedMinISize() const {
314 return mComputedMinSize
.ISize(mWritingMode
);
316 nscoord
ComputedMaxISize() const {
317 return mComputedMaxSize
.ISize(mWritingMode
);
319 nscoord
ComputedMinBSize() const {
320 return mComputedMinSize
.BSize(mWritingMode
);
322 nscoord
ComputedMaxBSize() const {
323 return mComputedMaxSize
.BSize(mWritingMode
);
326 nscoord
& AvailableISize() { return mAvailableSize
.ISize(mWritingMode
); }
327 nscoord
& AvailableBSize() { return mAvailableSize
.BSize(mWritingMode
); }
328 nscoord
& ComputedISize() { return mComputedSize
.ISize(mWritingMode
); }
329 nscoord
& ComputedBSize() { return mComputedSize
.BSize(mWritingMode
); }
330 nscoord
& ComputedMinISize() { return mComputedMinSize
.ISize(mWritingMode
); }
331 nscoord
& ComputedMaxISize() { return mComputedMaxSize
.ISize(mWritingMode
); }
332 nscoord
& ComputedMinBSize() { return mComputedMinSize
.BSize(mWritingMode
); }
333 nscoord
& ComputedMaxBSize() { return mComputedMaxSize
.BSize(mWritingMode
); }
335 mozilla::LogicalSize
AvailableSize() const { return mAvailableSize
; }
336 mozilla::LogicalSize
ComputedSize() const { return mComputedSize
; }
337 mozilla::LogicalSize
ComputedMinSize() const { return mComputedMinSize
; }
338 mozilla::LogicalSize
ComputedMaxSize() const { return mComputedMaxSize
; }
340 mozilla::LogicalSize
AvailableSize(mozilla::WritingMode aWM
) const {
341 return AvailableSize().ConvertTo(aWM
, mWritingMode
);
343 mozilla::LogicalSize
ComputedSize(mozilla::WritingMode aWM
) const {
344 return ComputedSize().ConvertTo(aWM
, mWritingMode
);
346 mozilla::LogicalSize
ComputedMinSize(mozilla::WritingMode aWM
) const {
347 return ComputedMinSize().ConvertTo(aWM
, mWritingMode
);
349 mozilla::LogicalSize
ComputedMaxSize(mozilla::WritingMode aWM
) const {
350 return ComputedMaxSize().ConvertTo(aWM
, mWritingMode
);
353 mozilla::LogicalSize
ComputedSizeWithPadding(mozilla::WritingMode aWM
) const {
354 return ComputedSize(aWM
) + ComputedLogicalPadding(aWM
).Size(aWM
);
357 mozilla::LogicalSize
ComputedSizeWithBorderPadding(
358 mozilla::WritingMode aWM
) const {
359 return ComputedSize(aWM
) + ComputedLogicalBorderPadding(aWM
).Size(aWM
);
362 mozilla::LogicalSize
ComputedSizeWithMarginBorderPadding(
363 mozilla::WritingMode aWM
) const {
364 return ComputedSizeWithBorderPadding(aWM
) +
365 ComputedLogicalMargin(aWM
).Size(aWM
);
368 nsSize
ComputedPhysicalSize() const {
369 return nsSize(ComputedWidth(), ComputedHeight());
372 nsMargin
ComputedPhysicalOffsets() const {
373 return mComputedOffsets
.GetPhysicalMargin(mWritingMode
);
376 LogicalMargin
ComputedLogicalOffsets(mozilla::WritingMode aWM
) const {
377 return mComputedOffsets
.ConvertTo(aWM
, mWritingMode
);
380 void SetComputedLogicalOffsets(mozilla::WritingMode aWM
,
381 const LogicalMargin
& aOffsets
) {
382 mComputedOffsets
= aOffsets
.ConvertTo(mWritingMode
, aWM
);
385 // Return ReflowInput's computed size including border-padding, with
386 // unconstrained dimensions replaced by zero.
387 nsSize
ComputedSizeAsContainerIfConstrained() const {
388 const nscoord wd
= ComputedWidth();
389 const nscoord ht
= ComputedHeight();
390 return nsSize(wd
== NS_UNCONSTRAINEDSIZE
392 : wd
+ ComputedPhysicalBorderPadding().LeftRight(),
393 ht
== NS_UNCONSTRAINEDSIZE
395 : ht
+ ComputedPhysicalBorderPadding().TopBottom());
398 // Our saved containing block dimensions.
399 LogicalSize mContainingBlockSize
{mWritingMode
};
401 // Cached pointers to the various style structs used during initialization.
402 const nsStyleDisplay
* mStyleDisplay
= nullptr;
403 const nsStyleVisibility
* mStyleVisibility
= nullptr;
404 const nsStylePosition
* mStylePosition
= nullptr;
405 const nsStyleBorder
* mStyleBorder
= nullptr;
406 const nsStyleMargin
* mStyleMargin
= nullptr;
407 const nsStylePadding
* mStylePadding
= nullptr;
408 const nsStyleText
* mStyleText
= nullptr;
410 // a frame (e.g. nsTableCellFrame) which may need to generate a special
411 // reflow for percent bsize calculations
412 nsIPercentBSizeObserver
* mPercentBSizeObserver
= nullptr;
414 // CSS margin collapsing sometimes requires us to reflow
415 // optimistically assuming that margins collapse to see if clearance
416 // is required. When we discover that clearance is required, we
417 // store the frame in which clearance was discovered to the location
419 nsIFrame
** mDiscoveredClearance
= nullptr;
422 Flags() { memset(this, 0, sizeof(*this)); }
424 // cached mFrame->IsFrameOfType(nsIFrame::eReplaced) ||
425 // mFrame->IsFrameOfType(nsIFrame::eReplacedContainsBlock)
426 bool mIsReplaced
: 1;
428 // used by tables to communicate special reflow (in process) to handle
429 // percent bsize frames inside cells which may not have computed bsizes
430 bool mSpecialBSizeReflow
: 1;
432 // nothing in the frame's next-in-flow (or its descendants) is changing
433 bool mNextInFlowUntouched
: 1;
435 // Is the current context at the top of a page? When true, we force
436 // something that's too tall for a page/column to fit anyway to avoid
438 bool mIsTopOfPage
: 1;
440 // parent frame is an nsIScrollableFrame and it is assuming a horizontal
442 bool mAssumingHScrollbar
: 1;
444 // parent frame is an nsIScrollableFrame and it is assuming a vertical
446 bool mAssumingVScrollbar
: 1;
448 // Is frame a different inline-size than before?
451 // Is frame (potentially) a different block-size than before?
452 // This includes cases where the block-size is 'auto' and the
453 // contents or width have changed.
456 // Has this frame changed block-size in a way that affects
457 // block-size percentages on frames for which it is the containing
458 // block? This includes a change between 'auto' and a length that
459 // doesn't actually change the frame's block-size. It does not
460 // include cases where the block-size is 'auto' and the frame's
461 // contents have changed.
463 // In the current code, this is only true when mIsBResize is also
464 // true, although it doesn't necessarily need to be that way (e.g.,
465 // in the case of a frame changing from 'auto' to a length that
466 // produces the same height).
467 bool mIsBResizeForPercentages
: 1;
469 // tables are splittable, this should happen only inside a page and never
470 // insider a column frame
471 bool mTableIsSplittable
: 1;
473 // Does frame height depend on an ancestor table-cell?
474 bool mHeightDependsOnAncestorCell
: 1;
476 // nsColumnSetFrame is balancing columns
477 bool mIsColumnBalancing
: 1;
479 // True if ColumnSetWrapperFrame has a constrained block-size, and is going
480 // to consume all of its block-size in this fragment. This bit is passed to
481 // nsColumnSetFrame to determine whether to give up balancing and create
483 bool mColumnSetWrapperHasNoBSizeLeft
: 1;
485 // If this flag is set, the BSize of this frame should be considered
486 // indefinite for the purposes of percent resolution on child frames (we
487 // should behave as if ComputedBSize() were NS_UNCONSTRAINEDSIZE when doing
488 // percent resolution against this.ComputedBSize()). For example: flex
489 // items may have their ComputedBSize() resolved ahead-of-time by their
490 // flex container, and yet their BSize might have to be considered
491 // indefinite per https://drafts.csswg.org/css-flexbox/#definite-sizes
492 bool mTreatBSizeAsIndefinite
: 1;
494 // a "fake" reflow input made in order to be the parent of a real one
495 bool mDummyParentReflowInput
: 1;
497 // Should this frame reflow its place-holder children? If the available
498 // height of this frame didn't change, but its in a paginated environment
499 // (e.g. columns), it should always reflow its placeholder children.
500 bool mMustReflowPlaceholders
: 1;
502 // the STATIC_POS_IS_CB_ORIGIN ctor flag
503 bool mStaticPosIsCBOrigin
: 1;
505 // If set, the following two flags indicate that:
506 // (1) this frame is absolutely-positioned (or fixed-positioned).
507 // (2) this frame's static position depends on the CSS Box Alignment.
508 // (3) we do need to compute the static position, because the frame's
509 // {Inline and/or Block} offsets actually depend on it.
510 // When these bits are set, the offset values (IStart/IEnd, BStart/BEnd)
511 // represent the "start" edge of the frame's CSS Box Alignment container
512 // area, in that axis -- and these offsets need to be further-resolved
513 // (with CSS Box Alignment) after we know the OOF frame's size.
514 // NOTE: The "I" and "B" (for "Inline" and "Block") refer the axes of the
515 // *containing block's writing-mode*, NOT mFrame's own writing-mode. This
516 // is purely for convenience, since that's the writing-mode we're dealing
517 // with when we set & react to these bits.
518 bool mIOffsetsNeedCSSAlign
: 1;
519 bool mBOffsetsNeedCSSAlign
: 1;
521 // Are we somewhere inside an element with -webkit-line-clamp set?
522 // This flag is inherited into descendant ReflowInputs, but we don't bother
523 // resetting it to false when crossing over into a block descendant that
524 // -webkit-line-clamp skips over (such as a BFC).
525 bool mInsideLineClamp
: 1;
527 // Is this a flex item, and should we add or remove a -webkit-line-clamp
528 // ellipsis on a descendant line? It's possible for this flag to be true
529 // when mInsideLineClamp is false if we previously had a numeric
530 // -webkit-line-clamp value, but now have 'none' and we need to find the
531 // line with the ellipsis flag and clear it.
532 // This flag is not inherited into descendant ReflowInputs.
533 bool mApplyLineClamp
: 1;
535 // Is this frame or one of its ancestors being reflowed in a different
536 // continuation than the one in which it was previously reflowed? In
537 // other words, has it moved to a different column or page than it was in
538 // the previous reflow?
540 // FIXME: For now, we only ensure that this is set correctly for blocks.
541 // This is okay because the only thing that uses it only cares about
542 // whether there's been a fragment change within the same block formatting
544 bool mMovedBlockFragments
: 1;
546 // Is the block-size computed by aspect-ratio and inline size (i.e. block
547 // axis is the ratio-dependent axis)? We set this flag so that we can check
548 // whether to apply automatic content-based minimum sizes once we know the
549 // children's block-size (after reflowing them).
550 // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
551 bool mIsBSizeSetByAspectRatio
: 1;
555 mozilla::StyleSizeOverrides mStyleSizeOverrides
;
557 mozilla::ComputeSizeFlags mComputeSizeFlags
;
559 // This value keeps track of how deeply nested a given reflow input
560 // is from the top of the frame tree.
561 int16_t mReflowDepth
= 0;
563 // Logical and physical accessors for the resize flags.
564 bool IsHResize() const {
565 return mWritingMode
.IsVertical() ? mFlags
.mIsBResize
: mFlags
.mIsIResize
;
567 bool IsVResize() const {
568 return mWritingMode
.IsVertical() ? mFlags
.mIsIResize
: mFlags
.mIsBResize
;
570 bool IsIResize() const { return mFlags
.mIsIResize
; }
571 bool IsBResize() const { return mFlags
.mIsBResize
; }
572 bool IsBResizeForWM(mozilla::WritingMode aWM
) const {
573 return aWM
.IsOrthogonalTo(mWritingMode
) ? mFlags
.mIsIResize
576 bool IsBResizeForPercentagesForWM(mozilla::WritingMode aWM
) const {
577 // This uses the relatively-accurate mIsBResizeForPercentages flag
578 // when the writing modes are parallel, and is a bit more
579 // pessimistic when orthogonal.
580 return !aWM
.IsOrthogonalTo(mWritingMode
) ? mFlags
.mIsBResizeForPercentages
583 void SetHResize(bool aValue
) {
584 if (mWritingMode
.IsVertical()) {
585 mFlags
.mIsBResize
= aValue
;
587 mFlags
.mIsIResize
= aValue
;
590 void SetVResize(bool aValue
) {
591 if (mWritingMode
.IsVertical()) {
592 mFlags
.mIsIResize
= aValue
;
594 mFlags
.mIsBResize
= aValue
;
597 void SetIResize(bool aValue
) { mFlags
.mIsIResize
= aValue
; }
598 void SetBResize(bool aValue
) { mFlags
.mIsBResize
= aValue
; }
600 // Values for |aFlags| passed to constructor
601 enum class InitFlag
: uint8_t {
602 // Indicates that the parent of this reflow input is "fake" (see
603 // mDummyParentReflowInput in mFlags).
604 DummyParentReflowInput
,
606 // Indicates that the calling function will initialize the reflow input, and
607 // that the constructor should not call Init().
610 // The caller wants the abs.pos. static-position resolved at the origin of
611 // the containing block, i.e. at LogicalPoint(0, 0). (Note that this
612 // doesn't necessarily mean that (0, 0) is the *correct* static position
613 // for the frame in question.)
614 // @note In a Grid container's masonry axis we'll always use
615 // the placeholder's position in that axis regardless of this flag.
618 using InitFlags
= mozilla::EnumSet
<InitFlag
>;
620 // Note: The copy constructor is written by the compiler automatically. You
621 // can use that and then override specific values if you want, or you can
622 // call Init as desired...
625 * Initialize a ROOT reflow input.
627 * @param aPresContext Must be equal to aFrame->PresContext().
628 * @param aFrame The frame for whose reflow input is being constructed.
629 * @param aRenderingContext The rendering context to be used for measurements.
630 * @param aAvailableSpace The available space to reflow aFrame (in aFrame's
631 * writing-mode). See comments for mAvailableSize for more information.
632 * @param aFlags A set of flags used for additional boolean parameters (see
635 ReflowInput(nsPresContext
* aPresContext
, nsIFrame
* aFrame
,
636 gfxContext
* aRenderingContext
,
637 const mozilla::LogicalSize
& aAvailableSpace
,
638 InitFlags aFlags
= {});
641 * Initialize a reflow input for a child frame's reflow. Some parts of the
642 * state are copied from the parent's reflow input. The remainder is computed.
644 * @param aPresContext Must be equal to aFrame->PresContext().
645 * @param aParentReflowInput A reference to an ReflowInput object that
646 * is to be the parent of this object.
647 * @param aFrame The frame for whose reflow input is being constructed.
648 * @param aAvailableSpace The available space to reflow aFrame (in aFrame's
649 * writing-mode). See comments for mAvailableSize for more information.
650 * @param aContainingBlockSize An optional size (in aFrame's writing mode),
651 * specifying the containing block size to use instead of the default
652 * size computed by ComputeContainingBlockRectangle(). If
653 * InitFlag::CallerWillInit is used, this is ignored. Pass it via
655 * @param aFlags A set of flags used for additional boolean parameters (see
657 * @param aStyleSizeOverrides The style data used to override mFrame's when we
658 * call nsIFrame::ComputeSize() internally.
659 * @param aComputeSizeFlags A set of flags used when we call
660 * nsIFrame::ComputeSize() internally.
662 ReflowInput(nsPresContext
* aPresContext
,
663 const ReflowInput
& aParentReflowInput
, nsIFrame
* aFrame
,
664 const mozilla::LogicalSize
& aAvailableSpace
,
665 const mozilla::Maybe
<mozilla::LogicalSize
>& aContainingBlockSize
=
667 InitFlags aFlags
= {},
668 const mozilla::StyleSizeOverrides
& aSizeOverrides
= {},
669 mozilla::ComputeSizeFlags aComputeSizeFlags
= {});
672 * This method initializes various data members. It is automatically called by
673 * the constructors if InitFlags::CallerWillInit is *not* used.
675 * @param aContainingBlockSize An optional size (in mFrame's writing mode),
676 * specifying the containing block size to use instead of the default
677 * size computed by ComputeContainingBlockRectangle().
678 * @param aBorder An optional border (in mFrame's writing mode). If given, use
679 * it instead of the border computed from mFrame's StyleBorder.
680 * @param aPadding An optional padding (in mFrame's writing mode). If given,
681 * use it instead of the padding computing from mFrame's StylePadding.
683 void Init(nsPresContext
* aPresContext
,
684 const mozilla::Maybe
<mozilla::LogicalSize
>& aContainingBlockSize
=
686 const mozilla::Maybe
<mozilla::LogicalMargin
>& aBorder
=
688 const mozilla::Maybe
<mozilla::LogicalMargin
>& aPadding
=
692 * Calculate the used line-height property. The return value will be >= 0.
694 nscoord
CalcLineHeight() const;
697 * Same as CalcLineHeight() above, but doesn't need a reflow input.
699 * @param aBlockBSize The computed block size of the content rect of the block
700 * that the line should fill.
701 * Only used with line-height:-moz-block-height.
702 * NS_UNCONSTRAINEDSIZE results in a normal line-height
703 * for line-height:-moz-block-height.
704 * @param aFontSizeInflation The result of the appropriate
705 * nsLayoutUtils::FontSizeInflationFor call,
706 * or 1.0 if during intrinsic size
709 static nscoord
CalcLineHeight(nsIContent
* aContent
,
710 ComputedStyle
* aComputedStyle
,
711 nsPresContext
* aPresContext
,
712 nscoord aBlockBSize
, float aFontSizeInflation
);
714 mozilla::LogicalSize
ComputeContainingBlockRectangle(
715 nsPresContext
* aPresContext
, const ReflowInput
* aContainingBlockRI
) const;
718 * Apply the mComputed(Min/Max)Width constraints to the content
719 * size computed so far.
721 nscoord
ApplyMinMaxWidth(nscoord aWidth
) const {
722 if (NS_UNCONSTRAINEDSIZE
!= ComputedMaxWidth()) {
723 aWidth
= std::min(aWidth
, ComputedMaxWidth());
725 return std::max(aWidth
, ComputedMinWidth());
729 * Apply the mComputed(Min/Max)ISize constraints to the content
730 * size computed so far.
732 nscoord
ApplyMinMaxISize(nscoord aISize
) const {
733 if (NS_UNCONSTRAINEDSIZE
!= ComputedMaxISize()) {
734 aISize
= std::min(aISize
, ComputedMaxISize());
736 return std::max(aISize
, ComputedMinISize());
740 * Apply the mComputed(Min/Max)Height constraints to the content
741 * size computed so far.
743 * @param aHeight The height that we've computed an to which we want to apply
744 * min/max constraints.
745 * @param aConsumed The amount of the computed height that was consumed by
748 nscoord
ApplyMinMaxHeight(nscoord aHeight
, nscoord aConsumed
= 0) const {
749 aHeight
+= aConsumed
;
751 if (NS_UNCONSTRAINEDSIZE
!= ComputedMaxHeight()) {
752 aHeight
= std::min(aHeight
, ComputedMaxHeight());
755 if (NS_UNCONSTRAINEDSIZE
!= ComputedMinHeight()) {
756 aHeight
= std::max(aHeight
, ComputedMinHeight());
759 return aHeight
- aConsumed
;
763 * Apply the mComputed(Min/Max)BSize constraints to the content
764 * size computed so far.
766 * @param aBSize The block-size that we've computed an to which we want to
767 * apply min/max constraints.
768 * @param aConsumed The amount of the computed block-size that was consumed by
771 nscoord
ApplyMinMaxBSize(nscoord aBSize
, nscoord aConsumed
= 0) const {
774 if (NS_UNCONSTRAINEDSIZE
!= ComputedMaxBSize()) {
775 aBSize
= std::min(aBSize
, ComputedMaxBSize());
778 if (NS_UNCONSTRAINEDSIZE
!= ComputedMinBSize()) {
779 aBSize
= std::max(aBSize
, ComputedMinBSize());
782 return aBSize
- aConsumed
;
785 bool ShouldReflowAllKids() const;
787 // This method doesn't apply min/max computed widths to the value passed in.
788 void SetComputedWidth(nscoord aComputedWidth
) {
789 if (mWritingMode
.IsVertical()) {
790 SetComputedBSize(aComputedWidth
);
792 SetComputedISize(aComputedWidth
);
796 // This method doesn't apply min/max computed heights to the value passed in.
797 void SetComputedHeight(nscoord aComputedHeight
) {
798 if (mWritingMode
.IsVertical()) {
799 SetComputedISize(aComputedHeight
);
801 SetComputedBSize(aComputedHeight
);
805 // This method doesn't apply min/max computed inline-sizes to the value passed
807 void SetComputedISize(nscoord aComputedISize
);
809 // These methods don't apply min/max computed block-sizes to the value passed
811 void SetComputedBSize(nscoord aComputedBSize
);
812 void SetComputedBSizeWithoutResettingResizeFlags(nscoord aComputedBSize
) {
813 // Viewport frames reset the computed block size on a copy of their reflow
814 // input when reflowing fixed-pos kids. In that case we actually don't
815 // want to mess with the resize flags, because comparing the frame's rect
816 // to the munged computed isize is pointless.
817 MOZ_ASSERT(aComputedBSize
>= 0, "Invalid computed block-size!");
818 ComputedBSize() = aComputedBSize
;
821 void SetTruncated(const ReflowOutput
& aMetrics
,
822 nsReflowStatus
* aStatus
) const;
824 bool WillReflowAgainForClearance() const {
825 return mDiscoveredClearance
&& *mDiscoveredClearance
;
828 // Compute the offsets for a relative position element
830 // @param aWM the writing mode of aCBSize and the returned offsets.
831 static mozilla::LogicalMargin
ComputeRelativeOffsets(
832 mozilla::WritingMode aWM
, nsIFrame
* aFrame
,
833 const mozilla::LogicalSize
& aCBSize
);
835 // If a relatively positioned element, adjust the position appropriately.
836 static void ApplyRelativePositioning(nsIFrame
* aFrame
,
837 const nsMargin
& aComputedOffsets
,
840 void ApplyRelativePositioning(nsPoint
* aPosition
) const {
841 ApplyRelativePositioning(mFrame
, ComputedPhysicalOffsets(), aPosition
);
844 static void ApplyRelativePositioning(
845 nsIFrame
* aFrame
, mozilla::WritingMode aWritingMode
,
846 const mozilla::LogicalMargin
& aComputedOffsets
,
847 mozilla::LogicalPoint
* aPosition
, const nsSize
& aContainerSize
);
849 void ApplyRelativePositioning(mozilla::LogicalPoint
* aPosition
,
850 const nsSize
& aContainerSize
) const {
851 ApplyRelativePositioning(mFrame
, mWritingMode
,
852 ComputedLogicalOffsets(mWritingMode
), aPosition
,
857 // Reflow trace methods. Defined in nsFrame.cpp so they have access
858 // to the display-reflow infrastructure.
859 static void* DisplayInitConstraintsEnter(nsIFrame
* aFrame
,
861 nscoord aCBISize
, nscoord aCBBSize
,
862 const nsMargin
* aBorder
,
863 const nsMargin
* aPadding
);
864 static void DisplayInitConstraintsExit(nsIFrame
* aFrame
, ReflowInput
* aState
,
866 static void* DisplayInitFrameTypeEnter(nsIFrame
* aFrame
, ReflowInput
* aState
);
867 static void DisplayInitFrameTypeExit(nsIFrame
* aFrame
, ReflowInput
* aState
,
872 void InitCBReflowInput();
873 void InitResizeFlags(nsPresContext
* aPresContext
,
874 mozilla::LayoutFrameType aFrameType
);
875 void InitDynamicReflowRoot();
877 void InitConstraints(
878 nsPresContext
* aPresContext
,
879 const mozilla::Maybe
<mozilla::LogicalSize
>& aContainingBlockSize
,
880 const mozilla::Maybe
<mozilla::LogicalMargin
>& aBorder
,
881 const mozilla::Maybe
<mozilla::LogicalMargin
>& aPadding
,
882 mozilla::LayoutFrameType aFrameType
);
884 // Returns the nearest containing block or block frame (whether or not
885 // it is a containing block) for the specified frame. Also returns
886 // the inline-start edge and logical size of the containing block's
888 // These are returned in the coordinate space of the containing block.
889 nsIFrame
* GetHypotheticalBoxContainer(nsIFrame
* aFrame
,
890 nscoord
& aCBIStartEdge
,
891 mozilla::LogicalSize
& aCBSize
) const;
893 // Calculate a "hypothetical box" position where the placeholder frame
894 // (for a position:fixed/absolute element) would have been placed if it were
895 // positioned statically. The hypothetical box position will have a writing
896 // mode with the same block direction as the absolute containing block
897 // (aCBReflowInput->frame), though it may differ in inline direction.
898 void CalculateHypotheticalPosition(nsPresContext
* aPresContext
,
899 nsPlaceholderFrame
* aPlaceholderFrame
,
900 const ReflowInput
* aCBReflowInput
,
901 nsHypotheticalPosition
& aHypotheticalPos
,
902 mozilla::LayoutFrameType aFrameType
) const;
904 // Check if we can use the resolved auto block size (by insets) to compute
905 // the inline size through aspect-ratio on absolute-positioned elements.
906 // This is only needed for non-replaced elements.
907 // https://drafts.csswg.org/css-position/#abspos-auto-size
908 bool IsInlineSizeComputableByBlockSizeAndAspectRatio(
909 nscoord aBlockSize
) const;
911 // This calculates the size by using the resolved auto block size (from
912 // non-auto block insets), according to the writing mode of current block.
913 LogicalSize
CalculateAbsoluteSizeWithResolvedAutoBlockSize(
914 nscoord aAutoBSize
, bool aNeedsComputeInlineSizeByAspectRatio
,
915 const LogicalSize
& aTentativeComputedSize
);
917 void InitAbsoluteConstraints(nsPresContext
* aPresContext
,
918 const ReflowInput
* aCBReflowInput
,
919 const mozilla::LogicalSize
& aContainingBlockSize
,
920 mozilla::LayoutFrameType aFrameType
);
922 // Calculates the computed values for the 'min-inline-size',
923 // 'max-inline-size', 'min-block-size', and 'max-block-size' properties, and
924 // stores them in the assorted data members
925 void ComputeMinMaxValues(const mozilla::LogicalSize
& aCBSize
);
927 // aInsideBoxSizing returns the part of the padding, border, and margin
928 // in the aAxis dimension that goes inside the edge given by box-sizing;
929 // aOutsideBoxSizing returns the rest.
930 void CalculateBorderPaddingMargin(mozilla::LogicalAxis aAxis
,
931 nscoord aContainingBlockSize
,
932 nscoord
* aInsideBoxSizing
,
933 nscoord
* aOutsideBoxSizing
) const;
935 void CalculateBlockSideMargins();
938 * @return true if mFrame is an internal table frame, i.e. an
939 * ns[RowGroup|ColGroup|Row|Cell]Frame. (We exclude nsTableColFrame
940 * here since we never setup a ReflowInput for those.)
942 bool IsInternalTableFrame() const;
945 // The available size in which to reflow the frame. The space represents the
946 // amount of room for the frame's margin, border, padding, and content area.
948 // The available inline-size should be constrained. The frame's inline-size
949 // you choose should fit within it.
951 // In galley mode, the available block-size is always unconstrained, and only
952 // page mode or multi-column layout involves a constrained available
955 // An unconstrained available block-size means you can choose whatever size
956 // you want. If the value is constrained, the frame's block-start border,
957 // padding, and content, must fit. If a frame is fully-complete after reflow,
958 // then its block-end border, padding, and margin (and similar for its
959 // fully-complete ancestors) will need to fit within this available
960 // block-size. However, if a frame is monolithic, it may choose a block-size
961 // larger than the available block-size.
962 mozilla::LogicalSize mAvailableSize
{mWritingMode
};
964 // The computed size specifies the frame's content area, and it does not apply
965 // to inline non-replaced elements.
967 // For block-level frames, the computed inline-size is based on the
968 // inline-size of the containing block, the margin/border/padding areas, and
969 // the min/max inline-size.
971 // For non-replaced block-level frames in the flow and floated, if the
972 // computed block-size is NS_UNCONSTRAINEDSIZE, you should choose a block-size
973 // to shrink wrap around the normal flow child frames. The block-size must be
974 // within the limit of the min/max block-size if there is such a limit.
975 mozilla::LogicalSize mComputedSize
{mWritingMode
};
977 // Computed values for 'inset' properties. Only applies to 'positioned'
979 mozilla::LogicalMargin mComputedOffsets
{mWritingMode
};
981 // Computed value for 'min-inline-size'/'min-block-size'.
982 mozilla::LogicalSize mComputedMinSize
{mWritingMode
};
984 // Computed value for 'max-inline-size'/'max-block-size'.
985 mozilla::LogicalSize mComputedMaxSize
{mWritingMode
, NS_UNCONSTRAINEDSIZE
,
986 NS_UNCONSTRAINEDSIZE
};
989 } // namespace mozilla
991 #endif // mozilla_ReflowInput_h