Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 |