layout/generic/nsHTMLReflowState.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /* struct containing the input to nsIFrame::Reflow */
michael@0 7
michael@0 8 #ifndef nsHTMLReflowState_h___
michael@0 9 #define nsHTMLReflowState_h___
michael@0 10
michael@0 11 #include "nsMargin.h"
michael@0 12 #include "nsStyleCoord.h"
michael@0 13 #include "nsIFrame.h"
michael@0 14 #include "mozilla/Assertions.h"
michael@0 15 #include <algorithm>
michael@0 16
michael@0 17 class nsPresContext;
michael@0 18 class nsRenderingContext;
michael@0 19 class nsFloatManager;
michael@0 20 class nsLineLayout;
michael@0 21 class nsIPercentHeightObserver;
michael@0 22 struct nsHypotheticalBox;
michael@0 23
michael@0 24 /**
michael@0 25 * @return aValue clamped to [aMinValue, aMaxValue].
michael@0 26 *
michael@0 27 * @note This function needs to handle aMinValue > aMaxValue. In that case,
michael@0 28 * aMinValue is returned.
michael@0 29 * @see http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
michael@0 30 * @see http://www.w3.org/TR/CSS21/visudet.html#min-max-heights
michael@0 31 */
michael@0 32 template <class NumericType>
michael@0 33 NumericType
michael@0 34 NS_CSS_MINMAX(NumericType aValue, NumericType aMinValue, NumericType aMaxValue)
michael@0 35 {
michael@0 36 NumericType result = aValue;
michael@0 37 if (aMaxValue < result)
michael@0 38 result = aMaxValue;
michael@0 39 if (aMinValue > result)
michael@0 40 result = aMinValue;
michael@0 41 return result;
michael@0 42 }
michael@0 43
michael@0 44 /**
michael@0 45 * CSS Frame type. Included as part of the reflow state.
michael@0 46 */
michael@0 47 typedef uint32_t nsCSSFrameType;
michael@0 48
michael@0 49 #define NS_CSS_FRAME_TYPE_UNKNOWN 0
michael@0 50 #define NS_CSS_FRAME_TYPE_INLINE 1
michael@0 51 #define NS_CSS_FRAME_TYPE_BLOCK 2 /* block-level in normal flow */
michael@0 52 #define NS_CSS_FRAME_TYPE_FLOATING 3
michael@0 53 #define NS_CSS_FRAME_TYPE_ABSOLUTE 4
michael@0 54 #define NS_CSS_FRAME_TYPE_INTERNAL_TABLE 5 /* row group frame, row frame, cell frame, ... */
michael@0 55
michael@0 56 /**
michael@0 57 * Bit-flag that indicates whether the element is replaced. Applies to inline,
michael@0 58 * block-level, floating, and absolutely positioned elements
michael@0 59 */
michael@0 60 #define NS_CSS_FRAME_TYPE_REPLACED 0x08000
michael@0 61
michael@0 62 /**
michael@0 63 * Bit-flag that indicates that the element is replaced and contains a block
michael@0 64 * (eg some form controls). Applies to inline, block-level, floating, and
michael@0 65 * absolutely positioned elements. Mutually exclusive with
michael@0 66 * NS_CSS_FRAME_TYPE_REPLACED.
michael@0 67 */
michael@0 68 #define NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK 0x10000
michael@0 69
michael@0 70 /**
michael@0 71 * Helper macros for telling whether items are replaced
michael@0 72 */
michael@0 73 #define NS_FRAME_IS_REPLACED_NOBLOCK(_ft) \
michael@0 74 (NS_CSS_FRAME_TYPE_REPLACED == ((_ft) & NS_CSS_FRAME_TYPE_REPLACED))
michael@0 75
michael@0 76 #define NS_FRAME_IS_REPLACED(_ft) \
michael@0 77 (NS_FRAME_IS_REPLACED_NOBLOCK(_ft) || \
michael@0 78 NS_FRAME_IS_REPLACED_CONTAINS_BLOCK(_ft))
michael@0 79
michael@0 80 #define NS_FRAME_REPLACED(_ft) \
michael@0 81 (NS_CSS_FRAME_TYPE_REPLACED | (_ft))
michael@0 82
michael@0 83 #define NS_FRAME_IS_REPLACED_CONTAINS_BLOCK(_ft) \
michael@0 84 (NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK == \
michael@0 85 ((_ft) & NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK))
michael@0 86
michael@0 87 #define NS_FRAME_REPLACED_CONTAINS_BLOCK(_ft) \
michael@0 88 (NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK | (_ft))
michael@0 89
michael@0 90 /**
michael@0 91 * A macro to extract the type. Masks off the 'replaced' bit-flag
michael@0 92 */
michael@0 93 #define NS_FRAME_GET_TYPE(_ft) \
michael@0 94 ((_ft) & ~(NS_CSS_FRAME_TYPE_REPLACED | \
michael@0 95 NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK))
michael@0 96
michael@0 97 // A base class of nsHTMLReflowState that computes only the padding,
michael@0 98 // border, and margin, since those values are needed more often.
michael@0 99 struct nsCSSOffsetState {
michael@0 100 public:
michael@0 101 typedef mozilla::WritingMode WritingMode;
michael@0 102 typedef mozilla::LogicalMargin LogicalMargin;
michael@0 103
michael@0 104 // the frame being reflowed
michael@0 105 nsIFrame* frame;
michael@0 106
michael@0 107 // rendering context to use for measurement
michael@0 108 nsRenderingContext* rendContext;
michael@0 109
michael@0 110 const nsMargin& ComputedPhysicalMargin() const { return mComputedMargin; }
michael@0 111 const nsMargin& ComputedPhysicalBorderPadding() const { return mComputedBorderPadding; }
michael@0 112 const nsMargin& ComputedPhysicalPadding() const { return mComputedPadding; }
michael@0 113
michael@0 114 // We may need to eliminate the (few) users of these writable-reference accessors
michael@0 115 // as part of migrating to logical coordinates.
michael@0 116 nsMargin& ComputedPhysicalMargin() { return mComputedMargin; }
michael@0 117 nsMargin& ComputedPhysicalBorderPadding() { return mComputedBorderPadding; }
michael@0 118 nsMargin& ComputedPhysicalPadding() { return mComputedPadding; }
michael@0 119
michael@0 120 LogicalMargin ComputedLogicalMargin() const
michael@0 121 { return LogicalMargin(mWritingMode, mComputedMargin); }
michael@0 122 LogicalMargin ComputedLogicalBorderPadding() const
michael@0 123 { return LogicalMargin(mWritingMode, mComputedBorderPadding); }
michael@0 124 LogicalMargin ComputedLogicalPadding() const
michael@0 125 { return LogicalMargin(mWritingMode, mComputedPadding); }
michael@0 126
michael@0 127 WritingMode GetWritingMode() const { return mWritingMode; }
michael@0 128
michael@0 129 protected:
michael@0 130 // cached copy of the frame's writing-mode, for logical coordinates
michael@0 131 WritingMode mWritingMode;
michael@0 132
michael@0 133 // These are PHYSICAL coordinates (for now).
michael@0 134 // Will probably become logical in due course.
michael@0 135
michael@0 136 // Computed margin values
michael@0 137 nsMargin mComputedMargin;
michael@0 138
michael@0 139 // Cached copy of the border + padding values
michael@0 140 nsMargin mComputedBorderPadding;
michael@0 141
michael@0 142 // Computed padding values
michael@0 143 nsMargin mComputedPadding;
michael@0 144
michael@0 145 public:
michael@0 146 // Callers using this constructor must call InitOffsets on their own.
michael@0 147 nsCSSOffsetState(nsIFrame *aFrame, nsRenderingContext *aRenderingContext)
michael@0 148 : frame(aFrame)
michael@0 149 , rendContext(aRenderingContext)
michael@0 150 , mWritingMode(aFrame->GetWritingMode())
michael@0 151 {
michael@0 152 }
michael@0 153
michael@0 154 nsCSSOffsetState(nsIFrame *aFrame, nsRenderingContext *aRenderingContext,
michael@0 155 nscoord aContainingBlockWidth);
michael@0 156
michael@0 157 #ifdef DEBUG
michael@0 158 // Reflow trace methods. Defined in nsFrame.cpp so they have access
michael@0 159 // to the display-reflow infrastructure.
michael@0 160 static void* DisplayInitOffsetsEnter(nsIFrame* aFrame,
michael@0 161 nsCSSOffsetState* aState,
michael@0 162 nscoord aHorizontalPercentBasis,
michael@0 163 nscoord aVerticalPercentBasis,
michael@0 164 const nsMargin* aBorder,
michael@0 165 const nsMargin* aPadding);
michael@0 166 static void DisplayInitOffsetsExit(nsIFrame* aFrame,
michael@0 167 nsCSSOffsetState* aState,
michael@0 168 void* aValue);
michael@0 169 #endif
michael@0 170
michael@0 171 private:
michael@0 172 /**
michael@0 173 * Computes margin values from the specified margin style information, and
michael@0 174 * fills in the mComputedMargin member.
michael@0 175 *
michael@0 176 * @param aHorizontalPercentBasis
michael@0 177 * Length to use for resolving percentage margin values in the horizontal
michael@0 178 * axis. Usually the containing block width.
michael@0 179 * @param aVerticalPercentBasis
michael@0 180 * Length to use for resolving percentage margin values in the vertical
michael@0 181 * axis. Usually the containing block width, per CSS21 sec 8.3, but may
michael@0 182 * be the containing block *height*, e.g. in CSS3 Flexbox and Grid.
michael@0 183 * @return true if the margin is dependent on the containing block size.
michael@0 184 */
michael@0 185 bool ComputeMargin(nscoord aHorizontalPercentBasis,
michael@0 186 nscoord aVerticalPercentBasis);
michael@0 187
michael@0 188 /**
michael@0 189 * Computes padding values from the specified padding style information, and
michael@0 190 * fills in the mComputedPadding member.
michael@0 191 *
michael@0 192 * @param aHorizontalPercentBasis
michael@0 193 * Length to use for resolving percentage padding values in the horizontal
michael@0 194 * axis. Usually the containing block width.
michael@0 195 * @param aVerticalPercentBasis
michael@0 196 * Length to use for resolving percentage padding values in the vertical
michael@0 197 * axis. Usually the containing block width, per CSS21 sec 8.4, but may
michael@0 198 * be the containing block *height* in e.g. CSS3 Flexbox and Grid.
michael@0 199 * @return true if the padding is dependent on the containing block size.
michael@0 200 */
michael@0 201 bool ComputePadding(nscoord aHorizontalPercentBasis,
michael@0 202 nscoord aVerticalPercentBasis, nsIAtom* aFrameType);
michael@0 203
michael@0 204 protected:
michael@0 205
michael@0 206 void InitOffsets(nscoord aHorizontalPercentBasis,
michael@0 207 nscoord aVerticalPercentBasis,
michael@0 208 nsIAtom* aFrameType,
michael@0 209 const nsMargin *aBorder = nullptr,
michael@0 210 const nsMargin *aPadding = nullptr);
michael@0 211
michael@0 212 /*
michael@0 213 * Convert nsStyleCoord to nscoord when percentages depend on the
michael@0 214 * containing block width, and enumerated values are for width,
michael@0 215 * min-width, or max-width. Does not handle auto widths.
michael@0 216 */
michael@0 217 inline nscoord ComputeWidthValue(nscoord aContainingBlockWidth,
michael@0 218 nscoord aContentEdgeToBoxSizing,
michael@0 219 nscoord aBoxSizingToMarginEdge,
michael@0 220 const nsStyleCoord& aCoord);
michael@0 221 // same as previous, but using mComputedBorderPadding, mComputedPadding,
michael@0 222 // and mComputedMargin
michael@0 223 nscoord ComputeWidthValue(nscoord aContainingBlockWidth,
michael@0 224 uint8_t aBoxSizing,
michael@0 225 const nsStyleCoord& aCoord);
michael@0 226
michael@0 227 nscoord ComputeHeightValue(nscoord aContainingBlockHeight,
michael@0 228 uint8_t aBoxSizing,
michael@0 229 const nsStyleCoord& aCoord);
michael@0 230 };
michael@0 231
michael@0 232 /**
michael@0 233 * State passed to a frame during reflow or intrinsic size calculation.
michael@0 234 *
michael@0 235 * XXX Refactor so only a base class (nsSizingState?) is used for intrinsic
michael@0 236 * size calculation.
michael@0 237 *
michael@0 238 * @see nsIFrame#Reflow()
michael@0 239 */
michael@0 240 struct nsHTMLReflowState : public nsCSSOffsetState {
michael@0 241 // the reflow states are linked together. this is the pointer to the
michael@0 242 // parent's reflow state
michael@0 243 const nsHTMLReflowState* parentReflowState;
michael@0 244
michael@0 245 // pointer to the float manager associated with this area
michael@0 246 nsFloatManager* mFloatManager;
michael@0 247
michael@0 248 // LineLayout object (only for inline reflow; set to nullptr otherwise)
michael@0 249 nsLineLayout* mLineLayout;
michael@0 250
michael@0 251 // The appropriate reflow state for the containing block (for
michael@0 252 // percentage widths, etc.) of this reflow state's frame.
michael@0 253 const nsHTMLReflowState *mCBReflowState;
michael@0 254
michael@0 255 // The type of frame, from css's perspective. This value is
michael@0 256 // initialized by the Init method below.
michael@0 257 nsCSSFrameType mFrameType;
michael@0 258
michael@0 259 // The amount the in-flow position of the block is moving vertically relative
michael@0 260 // to its previous in-flow position (i.e. the amount the line containing the
michael@0 261 // block is moving).
michael@0 262 // This should be zero for anything which is not a block outside, and it
michael@0 263 // should be zero for anything which has a non-block parent.
michael@0 264 // The intended use of this value is to allow the accurate determination
michael@0 265 // of the potential impact of a float
michael@0 266 // This takes on an arbitrary value the first time a block is reflowed
michael@0 267 nscoord mBlockDelta;
michael@0 268
michael@0 269 // Accessors for the private fields below. Forcing all callers to use these
michael@0 270 // will allow us to introduce logical-coordinate versions and gradually
michael@0 271 // change clients from physical to logical as needed; and potentially switch
michael@0 272 // the internal fields from physical to logical coordinates in due course,
michael@0 273 // while maintaining compatibility with not-yet-updated code.
michael@0 274 nscoord AvailableWidth() const { return mAvailableWidth; }
michael@0 275 nscoord AvailableHeight() const { return mAvailableHeight; }
michael@0 276 nscoord ComputedWidth() const { return mComputedWidth; }
michael@0 277 nscoord ComputedHeight() const { return mComputedHeight; }
michael@0 278 nscoord ComputedMinWidth() const { return mComputedMinWidth; }
michael@0 279 nscoord ComputedMaxWidth() const { return mComputedMaxWidth; }
michael@0 280 nscoord ComputedMinHeight() const { return mComputedMinHeight; }
michael@0 281 nscoord ComputedMaxHeight() const { return mComputedMaxHeight; }
michael@0 282
michael@0 283 nscoord& AvailableWidth() { return mAvailableWidth; }
michael@0 284 nscoord& AvailableHeight() { return mAvailableHeight; }
michael@0 285 nscoord& ComputedWidth() { return mComputedWidth; }
michael@0 286 nscoord& ComputedHeight() { return mComputedHeight; }
michael@0 287 nscoord& ComputedMinWidth() { return mComputedMinWidth; }
michael@0 288 nscoord& ComputedMaxWidth() { return mComputedMaxWidth; }
michael@0 289 nscoord& ComputedMinHeight() { return mComputedMinHeight; }
michael@0 290 nscoord& ComputedMaxHeight() { return mComputedMaxHeight; }
michael@0 291
michael@0 292 // ISize and BSize are logical-coordinate dimensions:
michael@0 293 // ISize is the size in the writing mode's inline direction (which equates to
michael@0 294 // width in horizontal writing modes, height in vertical ones), and BSize is
michael@0 295 // the size in the block-progression direction.
michael@0 296 nscoord AvailableISize() const
michael@0 297 { return mWritingMode.IsVertical() ? mAvailableHeight : mAvailableWidth; }
michael@0 298 nscoord AvailableBSize() const
michael@0 299 { return mWritingMode.IsVertical() ? mAvailableWidth : mAvailableHeight; }
michael@0 300 nscoord ComputedISize() const
michael@0 301 { return mWritingMode.IsVertical() ? mComputedHeight : mComputedWidth; }
michael@0 302 nscoord ComputedBSize() const
michael@0 303 { return mWritingMode.IsVertical() ? mComputedWidth : mComputedHeight; }
michael@0 304 nscoord ComputedMinISize() const
michael@0 305 { return mWritingMode.IsVertical() ? mComputedMinHeight : mComputedMinWidth; }
michael@0 306 nscoord ComputedMaxISize() const
michael@0 307 { return mWritingMode.IsVertical() ? mComputedMaxHeight : mComputedMaxWidth; }
michael@0 308 nscoord ComputedMinBSize() const
michael@0 309 { return mWritingMode.IsVertical() ? mComputedMinWidth : mComputedMinHeight; }
michael@0 310 nscoord ComputedMaxBSize() const
michael@0 311 { return mWritingMode.IsVertical() ? mComputedMaxWidth : mComputedMaxHeight; }
michael@0 312
michael@0 313 nscoord& AvailableISize()
michael@0 314 { return mWritingMode.IsVertical() ? mAvailableHeight : mAvailableWidth; }
michael@0 315 nscoord& AvailableBSize()
michael@0 316 { return mWritingMode.IsVertical() ? mAvailableWidth : mAvailableHeight; }
michael@0 317 nscoord& ComputedISize()
michael@0 318 { return mWritingMode.IsVertical() ? mComputedHeight : mComputedWidth; }
michael@0 319 nscoord& ComputedBSize()
michael@0 320 { return mWritingMode.IsVertical() ? mComputedWidth : mComputedHeight; }
michael@0 321 nscoord& ComputedMinISize()
michael@0 322 { return mWritingMode.IsVertical() ? mComputedMinHeight : mComputedMinWidth; }
michael@0 323 nscoord& ComputedMaxISize()
michael@0 324 { return mWritingMode.IsVertical() ? mComputedMaxHeight : mComputedMaxWidth; }
michael@0 325 nscoord& ComputedMinBSize()
michael@0 326 { return mWritingMode.IsVertical() ? mComputedMinWidth : mComputedMinHeight; }
michael@0 327 nscoord& ComputedMaxBSize()
michael@0 328 { return mWritingMode.IsVertical() ? mComputedMaxWidth : mComputedMaxHeight; }
michael@0 329
michael@0 330 // XXX this will need to change when we make mComputedOffsets logical;
michael@0 331 // we won't be able to return a reference for the physical offsets
michael@0 332 const nsMargin& ComputedPhysicalOffsets() const { return mComputedOffsets; }
michael@0 333 nsMargin& ComputedPhysicalOffsets() { return mComputedOffsets; }
michael@0 334
michael@0 335 LogicalMargin ComputedLogicalOffsets() const
michael@0 336 { return LogicalMargin(mWritingMode, mComputedOffsets); }
michael@0 337
michael@0 338 private:
michael@0 339 // the available width in which to reflow the frame. The space
michael@0 340 // represents the amount of room for the frame's margin, border,
michael@0 341 // padding, and content area. The frame size you choose should fit
michael@0 342 // within the available width.
michael@0 343 nscoord mAvailableWidth;
michael@0 344
michael@0 345 // A value of NS_UNCONSTRAINEDSIZE for the available height means
michael@0 346 // you can choose whatever size you want. In galley mode the
michael@0 347 // available height is always NS_UNCONSTRAINEDSIZE, and only page
michael@0 348 // mode or multi-column layout involves a constrained height. The
michael@0 349 // element's the top border and padding, and content, must fit. If the
michael@0 350 // element is complete after reflow then its bottom border, padding
michael@0 351 // and margin (and similar for its complete ancestors) will need to
michael@0 352 // fit in this height.
michael@0 353 nscoord mAvailableHeight;
michael@0 354
michael@0 355 // The computed width specifies the frame's content area width, and it does
michael@0 356 // not apply to inline non-replaced elements
michael@0 357 //
michael@0 358 // For replaced inline frames, a value of NS_INTRINSICSIZE means you should
michael@0 359 // use your intrinsic width as the computed width
michael@0 360 //
michael@0 361 // For block-level frames, the computed width is based on the width of the
michael@0 362 // containing block, the margin/border/padding areas, and the min/max width.
michael@0 363 nscoord mComputedWidth;
michael@0 364
michael@0 365 // The computed height specifies the frame's content height, and it does
michael@0 366 // not apply to inline non-replaced elements
michael@0 367 //
michael@0 368 // For replaced inline frames, a value of NS_INTRINSICSIZE means you should
michael@0 369 // use your intrinsic height as the computed height
michael@0 370 //
michael@0 371 // For non-replaced block-level frames in the flow and floated, a value of
michael@0 372 // NS_AUTOHEIGHT means you choose a height to shrink wrap around the normal
michael@0 373 // flow child frames. The height must be within the limit of the min/max
michael@0 374 // height if there is such a limit
michael@0 375 //
michael@0 376 // For replaced block-level frames, a value of NS_INTRINSICSIZE
michael@0 377 // means you use your intrinsic height as the computed height
michael@0 378 nscoord mComputedHeight;
michael@0 379
michael@0 380 // Computed values for 'left/top/right/bottom' offsets. Only applies to
michael@0 381 // 'positioned' elements. These are PHYSICAL coordinates (for now).
michael@0 382 nsMargin mComputedOffsets;
michael@0 383
michael@0 384 // Computed values for 'min-width/max-width' and 'min-height/max-height'
michael@0 385 // XXXldb The width ones here should go; they should be needed only
michael@0 386 // internally.
michael@0 387 nscoord mComputedMinWidth, mComputedMaxWidth;
michael@0 388 nscoord mComputedMinHeight, mComputedMaxHeight;
michael@0 389
michael@0 390 public:
michael@0 391 // Cached pointers to the various style structs used during intialization
michael@0 392 const nsStyleDisplay* mStyleDisplay;
michael@0 393 const nsStyleVisibility* mStyleVisibility;
michael@0 394 const nsStylePosition* mStylePosition;
michael@0 395 const nsStyleBorder* mStyleBorder;
michael@0 396 const nsStyleMargin* mStyleMargin;
michael@0 397 const nsStylePadding* mStylePadding;
michael@0 398 const nsStyleText* mStyleText;
michael@0 399
michael@0 400 bool IsFloating() const;
michael@0 401
michael@0 402 uint8_t GetDisplay() const;
michael@0 403
michael@0 404 // a frame (e.g. nsTableCellFrame) which may need to generate a special
michael@0 405 // reflow for percent height calculations
michael@0 406 nsIPercentHeightObserver* mPercentHeightObserver;
michael@0 407
michael@0 408 // CSS margin collapsing sometimes requires us to reflow
michael@0 409 // optimistically assuming that margins collapse to see if clearance
michael@0 410 // is required. When we discover that clearance is required, we
michael@0 411 // store the frame in which clearance was discovered to the location
michael@0 412 // requested here.
michael@0 413 nsIFrame** mDiscoveredClearance;
michael@0 414
michael@0 415 // This value keeps track of how deeply nested a given reflow state
michael@0 416 // is from the top of the frame tree.
michael@0 417 int16_t mReflowDepth;
michael@0 418
michael@0 419 struct ReflowStateFlags {
michael@0 420 uint16_t mSpecialHeightReflow:1; // used by tables to communicate special reflow (in process) to handle
michael@0 421 // percent height frames inside cells which may not have computed heights
michael@0 422 uint16_t mNextInFlowUntouched:1; // nothing in the frame's next-in-flow (or its descendants)
michael@0 423 // is changing
michael@0 424 uint16_t mIsTopOfPage:1; // Is the current context at the top of a
michael@0 425 // page? When true, we force something
michael@0 426 // that's too tall for a page/column to
michael@0 427 // fit anyway to avoid infinite loops.
michael@0 428 uint16_t mHasClearance:1; // Block has clearance
michael@0 429 uint16_t mAssumingHScrollbar:1; // parent frame is an nsIScrollableFrame and it
michael@0 430 // is assuming a horizontal scrollbar
michael@0 431 uint16_t mAssumingVScrollbar:1; // parent frame is an nsIScrollableFrame and it
michael@0 432 // is assuming a vertical scrollbar
michael@0 433
michael@0 434 uint16_t mHResize:1; // Is frame (a) not dirty and (b) a
michael@0 435 // different width than before?
michael@0 436
michael@0 437 uint16_t mVResize:1; // Is frame (a) not dirty and (b) a
michael@0 438 // different height than before or
michael@0 439 // (potentially) in a context where
michael@0 440 // percent heights have a different
michael@0 441 // basis?
michael@0 442 uint16_t mTableIsSplittable:1; // tables are splittable, this should happen only inside a page
michael@0 443 // and never insider a column frame
michael@0 444 uint16_t mHeightDependsOnAncestorCell:1; // Does frame height depend on
michael@0 445 // an ancestor table-cell?
michael@0 446 uint16_t mIsColumnBalancing:1; // nsColumnSetFrame is balancing columns
michael@0 447 uint16_t mIsFlexContainerMeasuringHeight:1; // nsFlexContainerFrame is
michael@0 448 // reflowing this child to
michael@0 449 // measure its intrinsic height.
michael@0 450 uint16_t mDummyParentReflowState:1; // a "fake" reflow state made
michael@0 451 // in order to be the parent
michael@0 452 // of a real one
michael@0 453 uint16_t mMustReflowPlaceholders:1; // Should this frame reflow its place-
michael@0 454 // holder children? If the available
michael@0 455 // height of this frame didn't change,
michael@0 456 // but its in a paginated environment
michael@0 457 // (e.g. columns), it should always
michael@0 458 // reflow its placeholder children.
michael@0 459 } mFlags;
michael@0 460
michael@0 461 // Note: The copy constructor is written by the compiler automatically. You
michael@0 462 // can use that and then override specific values if you want, or you can
michael@0 463 // call Init as desired...
michael@0 464
michael@0 465 /**
michael@0 466 * Initialize a ROOT reflow state.
michael@0 467 *
michael@0 468 * @param aPresContext Must be equal to aFrame->PresContext().
michael@0 469 * @param aFrame The frame for whose reflow state is being constructed.
michael@0 470 * @param aRenderingContext The rendering context to be used for measurements.
michael@0 471 * @param aAvailableSpace See comments for availableHeight and availableWidth
michael@0 472 * members.
michael@0 473 * @param aFlags A set of flags used for additional boolean parameters (see
michael@0 474 * below).
michael@0 475 */
michael@0 476 nsHTMLReflowState(nsPresContext* aPresContext,
michael@0 477 nsIFrame* aFrame,
michael@0 478 nsRenderingContext* aRenderingContext,
michael@0 479 const nsSize& aAvailableSpace,
michael@0 480 uint32_t aFlags = 0);
michael@0 481
michael@0 482 /**
michael@0 483 * Initialize a reflow state for a child frame's reflow. Some parts of the
michael@0 484 * state are copied from the parent's reflow state. The remainder is computed.
michael@0 485 *
michael@0 486 * @param aPresContext Must be equal to aFrame->PresContext().
michael@0 487 * @param aParentReflowState A reference to an nsHTMLReflowState object that
michael@0 488 * is to be the parent of this object.
michael@0 489 * @param aFrame The frame for whose reflow state is being constructed.
michael@0 490 * @param aAvailableSpace See comments for availableHeight and availableWidth
michael@0 491 * members.
michael@0 492 * @param aContainingBlockWidth An optional width, in app units, that is used
michael@0 493 * by absolute positioning code to override default containing block
michael@0 494 * width.
michael@0 495 * @param aContainingBlockHeight An optional height, in app units, that is
michael@0 496 * used by absolute positioning code to override default containing
michael@0 497 * block height.
michael@0 498 * @param aFlags A set of flags used for additional boolean parameters (see
michael@0 499 * below).
michael@0 500 */
michael@0 501 nsHTMLReflowState(nsPresContext* aPresContext,
michael@0 502 const nsHTMLReflowState& aParentReflowState,
michael@0 503 nsIFrame* aFrame,
michael@0 504 const nsSize& aAvailableSpace,
michael@0 505 nscoord aContainingBlockWidth = -1,
michael@0 506 nscoord aContainingBlockHeight = -1,
michael@0 507 uint32_t aFlags = 0);
michael@0 508
michael@0 509 // Values for |aFlags| passed to constructor
michael@0 510 enum {
michael@0 511 // Indicates that the parent of this reflow state is "fake" (see
michael@0 512 // mDummyParentReflowState in mFlags).
michael@0 513 DUMMY_PARENT_REFLOW_STATE = (1<<0),
michael@0 514
michael@0 515 // Indicates that the calling function will initialize the reflow state, and
michael@0 516 // that the constructor should not call Init().
michael@0 517 CALLER_WILL_INIT = (1<<1)
michael@0 518 };
michael@0 519
michael@0 520 // This method initializes various data members. It is automatically
michael@0 521 // called by the various constructors
michael@0 522 void Init(nsPresContext* aPresContext,
michael@0 523 nscoord aContainingBlockWidth = -1,
michael@0 524 nscoord aContainingBlockHeight = -1,
michael@0 525 const nsMargin* aBorder = nullptr,
michael@0 526 const nsMargin* aPadding = nullptr);
michael@0 527 /**
michael@0 528 * Find the content width of the containing block of aReflowState
michael@0 529 */
michael@0 530 static nscoord
michael@0 531 GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
michael@0 532
michael@0 533 /**
michael@0 534 * Calculate the used line-height property. The return value will be >= 0.
michael@0 535 */
michael@0 536 nscoord CalcLineHeight() const;
michael@0 537
michael@0 538 /**
michael@0 539 * Same as CalcLineHeight() above, but doesn't need a reflow state.
michael@0 540 *
michael@0 541 * @param aBlockHeight The computed height of the content rect of the block
michael@0 542 * that the line should fill.
michael@0 543 * Only used with line-height:-moz-block-height.
michael@0 544 * NS_AUTOHEIGHT results in a normal line-height for
michael@0 545 * line-height:-moz-block-height.
michael@0 546 * @param aFontSizeInflation The result of the appropriate
michael@0 547 * nsLayoutUtils::FontSizeInflationFor call,
michael@0 548 * or 1.0 if during intrinsic size
michael@0 549 * calculation.
michael@0 550 */
michael@0 551 static nscoord CalcLineHeight(nsIContent* aContent,
michael@0 552 nsStyleContext* aStyleContext,
michael@0 553 nscoord aBlockHeight,
michael@0 554 float aFontSizeInflation);
michael@0 555
michael@0 556
michael@0 557 void ComputeContainingBlockRectangle(nsPresContext* aPresContext,
michael@0 558 const nsHTMLReflowState* aContainingBlockRS,
michael@0 559 nscoord& aContainingBlockWidth,
michael@0 560 nscoord& aContainingBlockHeight);
michael@0 561
michael@0 562 /**
michael@0 563 * Apply the mComputed(Min/Max)Width constraints to the content
michael@0 564 * size computed so far.
michael@0 565 */
michael@0 566 nscoord ApplyMinMaxWidth(nscoord aWidth) const {
michael@0 567 if (NS_UNCONSTRAINEDSIZE != ComputedMaxWidth()) {
michael@0 568 aWidth = std::min(aWidth, ComputedMaxWidth());
michael@0 569 }
michael@0 570 return std::max(aWidth, ComputedMinWidth());
michael@0 571 }
michael@0 572
michael@0 573 /**
michael@0 574 * Apply the mComputed(Min/Max)Height constraints to the content
michael@0 575 * size computed so far.
michael@0 576 *
michael@0 577 * @param aHeight The height that we've computed an to which we want to apply
michael@0 578 * min/max constraints.
michael@0 579 * @param aConsumed The amount of the computed height that was consumed by
michael@0 580 * our prev-in-flows.
michael@0 581 */
michael@0 582 nscoord ApplyMinMaxHeight(nscoord aHeight, nscoord aConsumed = 0) const {
michael@0 583 aHeight += aConsumed;
michael@0 584
michael@0 585 if (NS_UNCONSTRAINEDSIZE != ComputedMaxHeight()) {
michael@0 586 aHeight = std::min(aHeight, ComputedMaxHeight());
michael@0 587 }
michael@0 588
michael@0 589 if (NS_UNCONSTRAINEDSIZE != ComputedMinHeight()) {
michael@0 590 aHeight = std::max(aHeight, ComputedMinHeight());
michael@0 591 }
michael@0 592
michael@0 593 return aHeight - aConsumed;
michael@0 594 }
michael@0 595
michael@0 596 bool ShouldReflowAllKids() const {
michael@0 597 // Note that we could make a stronger optimization for mVResize if
michael@0 598 // we use it in a ShouldReflowChild test that replaces the current
michael@0 599 // checks of NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN, if it
michael@0 600 // were tested there along with NS_FRAME_CONTAINS_RELATIVE_HEIGHT.
michael@0 601 // This would need to be combined with a slight change in which
michael@0 602 // frames NS_FRAME_CONTAINS_RELATIVE_HEIGHT is marked on.
michael@0 603 return (frame->GetStateBits() & NS_FRAME_IS_DIRTY) ||
michael@0 604 mFlags.mHResize ||
michael@0 605 (mFlags.mVResize &&
michael@0 606 (frame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT));
michael@0 607 }
michael@0 608
michael@0 609 // This method doesn't apply min/max computed widths to the value passed in.
michael@0 610 void SetComputedWidth(nscoord aComputedWidth);
michael@0 611
michael@0 612 // This method doesn't apply min/max computed heights to the value passed in.
michael@0 613 void SetComputedHeight(nscoord aComputedHeight);
michael@0 614
michael@0 615 void SetComputedHeightWithoutResettingResizeFlags(nscoord aComputedHeight) {
michael@0 616 // Viewport frames reset the computed height on a copy of their reflow
michael@0 617 // state when reflowing fixed-pos kids. In that case we actually don't
michael@0 618 // want to mess with the resize flags, because comparing the frame's rect
michael@0 619 // to the munged computed width is pointless.
michael@0 620 ComputedHeight() = aComputedHeight;
michael@0 621 }
michael@0 622
michael@0 623 void SetTruncated(const nsHTMLReflowMetrics& aMetrics, nsReflowStatus* aStatus) const;
michael@0 624
michael@0 625 bool WillReflowAgainForClearance() const {
michael@0 626 return mDiscoveredClearance && *mDiscoveredClearance;
michael@0 627 }
michael@0 628
michael@0 629 // Compute the offsets for a relative position element
michael@0 630 static void ComputeRelativeOffsets(uint8_t aCBDirection,
michael@0 631 nsIFrame* aFrame,
michael@0 632 nscoord aContainingBlockWidth,
michael@0 633 nscoord aContainingBlockHeight,
michael@0 634 nsMargin& aComputedOffsets);
michael@0 635
michael@0 636 // If a relatively positioned element, adjust the position appropriately.
michael@0 637 static void ApplyRelativePositioning(nsIFrame* aFrame,
michael@0 638 const nsMargin& aComputedOffsets,
michael@0 639 nsPoint* aPosition);
michael@0 640
michael@0 641 void ApplyRelativePositioning(nsPoint* aPosition) const {
michael@0 642 ApplyRelativePositioning(frame, ComputedPhysicalOffsets(), aPosition);
michael@0 643 }
michael@0 644
michael@0 645 #ifdef DEBUG
michael@0 646 // Reflow trace methods. Defined in nsFrame.cpp so they have access
michael@0 647 // to the display-reflow infrastructure.
michael@0 648 static void* DisplayInitConstraintsEnter(nsIFrame* aFrame,
michael@0 649 nsHTMLReflowState* aState,
michael@0 650 nscoord aCBWidth,
michael@0 651 nscoord aCBHeight,
michael@0 652 const nsMargin* aBorder,
michael@0 653 const nsMargin* aPadding);
michael@0 654 static void DisplayInitConstraintsExit(nsIFrame* aFrame,
michael@0 655 nsHTMLReflowState* aState,
michael@0 656 void* aValue);
michael@0 657 static void* DisplayInitFrameTypeEnter(nsIFrame* aFrame,
michael@0 658 nsHTMLReflowState* aState);
michael@0 659 static void DisplayInitFrameTypeExit(nsIFrame* aFrame,
michael@0 660 nsHTMLReflowState* aState,
michael@0 661 void* aValue);
michael@0 662 #endif
michael@0 663
michael@0 664 protected:
michael@0 665 void InitFrameType(nsIAtom* aFrameType);
michael@0 666 void InitCBReflowState();
michael@0 667 void InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameType);
michael@0 668
michael@0 669 void InitConstraints(nsPresContext* aPresContext,
michael@0 670 nscoord aContainingBlockWidth,
michael@0 671 nscoord aContainingBlockHeight,
michael@0 672 const nsMargin* aBorder,
michael@0 673 const nsMargin* aPadding,
michael@0 674 nsIAtom* aFrameType);
michael@0 675
michael@0 676 // Returns the nearest containing block or block frame (whether or not
michael@0 677 // it is a containing block) for the specified frame. Also returns
michael@0 678 // the left edge and width of the containing block's content area.
michael@0 679 // These are returned in the coordinate space of the containing block.
michael@0 680 nsIFrame* GetHypotheticalBoxContainer(nsIFrame* aFrame,
michael@0 681 nscoord& aCBLeftEdge,
michael@0 682 nscoord& aCBWidth);
michael@0 683
michael@0 684 void CalculateHypotheticalBox(nsPresContext* aPresContext,
michael@0 685 nsIFrame* aPlaceholderFrame,
michael@0 686 nsIFrame* aContainingBlock,
michael@0 687 nscoord aBlockLeftContentEdge,
michael@0 688 nscoord aBlockContentWidth,
michael@0 689 const nsHTMLReflowState* cbrs,
michael@0 690 nsHypotheticalBox& aHypotheticalBox,
michael@0 691 nsIAtom* aFrameType);
michael@0 692
michael@0 693 void InitAbsoluteConstraints(nsPresContext* aPresContext,
michael@0 694 const nsHTMLReflowState* cbrs,
michael@0 695 nscoord aContainingBlockWidth,
michael@0 696 nscoord aContainingBlockHeight,
michael@0 697 nsIAtom* aFrameType);
michael@0 698
michael@0 699 // Calculates the computed values for the 'min-Width', 'max-Width',
michael@0 700 // 'min-Height', and 'max-Height' properties, and stores them in the assorted
michael@0 701 // data members
michael@0 702 void ComputeMinMaxValues(nscoord aContainingBlockWidth,
michael@0 703 nscoord aContainingBlockHeight,
michael@0 704 const nsHTMLReflowState* aContainingBlockRS);
michael@0 705
michael@0 706 void CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth,
michael@0 707 nscoord* aInsideBoxSizing,
michael@0 708 nscoord* aOutsideBoxSizing);
michael@0 709
michael@0 710 void CalculateBlockSideMargins(nscoord aAvailWidth,
michael@0 711 nscoord aComputedWidth,
michael@0 712 nsIAtom* aFrameType);
michael@0 713 };
michael@0 714
michael@0 715 #endif /* nsHTMLReflowState_h___ */
michael@0 716

mercurial