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