|
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 /* |
|
7 * code for managing absolutely positioned children of a rendering |
|
8 * object that is a containing block for them |
|
9 */ |
|
10 |
|
11 #include "nsAbsoluteContainingBlock.h" |
|
12 |
|
13 #include "nsContainerFrame.h" |
|
14 #include "nsGkAtoms.h" |
|
15 #include "nsIPresShell.h" |
|
16 #include "nsHTMLReflowState.h" |
|
17 #include "nsPresContext.h" |
|
18 #include "nsCSSFrameConstructor.h" |
|
19 |
|
20 #ifdef DEBUG |
|
21 #include "nsBlockFrame.h" |
|
22 |
|
23 static void PrettyUC(nscoord aSize, char* aBuf) |
|
24 { |
|
25 if (NS_UNCONSTRAINEDSIZE == aSize) { |
|
26 strcpy(aBuf, "UC"); |
|
27 } else { |
|
28 if((int32_t)0xdeadbeef == aSize) { |
|
29 strcpy(aBuf, "deadbeef"); |
|
30 } else { |
|
31 sprintf(aBuf, "%d", aSize); |
|
32 } |
|
33 } |
|
34 } |
|
35 #endif |
|
36 |
|
37 nsresult |
|
38 nsAbsoluteContainingBlock::SetInitialChildList(nsIFrame* aDelegatingFrame, |
|
39 ChildListID aListID, |
|
40 nsFrameList& aChildList) |
|
41 { |
|
42 NS_PRECONDITION(mChildListID == aListID, "unexpected child list name"); |
|
43 #ifdef DEBUG |
|
44 nsFrame::VerifyDirtyBitSet(aChildList); |
|
45 #endif |
|
46 mAbsoluteFrames.SetFrames(aChildList); |
|
47 return NS_OK; |
|
48 } |
|
49 |
|
50 nsresult |
|
51 nsAbsoluteContainingBlock::AppendFrames(nsIFrame* aDelegatingFrame, |
|
52 ChildListID aListID, |
|
53 nsFrameList& aFrameList) |
|
54 { |
|
55 NS_ASSERTION(mChildListID == aListID, "unexpected child list"); |
|
56 |
|
57 // Append the frames to our list of absolutely positioned frames |
|
58 #ifdef DEBUG |
|
59 nsFrame::VerifyDirtyBitSet(aFrameList); |
|
60 #endif |
|
61 mAbsoluteFrames.AppendFrames(nullptr, aFrameList); |
|
62 |
|
63 // no damage to intrinsic widths, since absolutely positioned frames can't |
|
64 // change them |
|
65 aDelegatingFrame->PresContext()->PresShell()-> |
|
66 FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize, |
|
67 NS_FRAME_HAS_DIRTY_CHILDREN); |
|
68 |
|
69 return NS_OK; |
|
70 } |
|
71 |
|
72 nsresult |
|
73 nsAbsoluteContainingBlock::InsertFrames(nsIFrame* aDelegatingFrame, |
|
74 ChildListID aListID, |
|
75 nsIFrame* aPrevFrame, |
|
76 nsFrameList& aFrameList) |
|
77 { |
|
78 NS_ASSERTION(mChildListID == aListID, "unexpected child list"); |
|
79 NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == aDelegatingFrame, |
|
80 "inserting after sibling frame with different parent"); |
|
81 |
|
82 #ifdef DEBUG |
|
83 nsFrame::VerifyDirtyBitSet(aFrameList); |
|
84 #endif |
|
85 mAbsoluteFrames.InsertFrames(nullptr, aPrevFrame, aFrameList); |
|
86 |
|
87 // no damage to intrinsic widths, since absolutely positioned frames can't |
|
88 // change them |
|
89 aDelegatingFrame->PresContext()->PresShell()-> |
|
90 FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize, |
|
91 NS_FRAME_HAS_DIRTY_CHILDREN); |
|
92 |
|
93 return NS_OK; |
|
94 } |
|
95 |
|
96 void |
|
97 nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, |
|
98 ChildListID aListID, |
|
99 nsIFrame* aOldFrame) |
|
100 { |
|
101 NS_ASSERTION(mChildListID == aListID, "unexpected child list"); |
|
102 nsIFrame* nif = aOldFrame->GetNextInFlow(); |
|
103 if (nif) { |
|
104 static_cast<nsContainerFrame*>(nif->GetParent()) |
|
105 ->DeleteNextInFlowChild(nif, false); |
|
106 } |
|
107 |
|
108 mAbsoluteFrames.DestroyFrame(aOldFrame); |
|
109 } |
|
110 |
|
111 nsresult |
|
112 nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, |
|
113 nsPresContext* aPresContext, |
|
114 const nsHTMLReflowState& aReflowState, |
|
115 nsReflowStatus& aReflowStatus, |
|
116 const nsRect& aContainingBlock, |
|
117 bool aConstrainHeight, |
|
118 bool aCBWidthChanged, |
|
119 bool aCBHeightChanged, |
|
120 nsOverflowAreas* aOverflowAreas) |
|
121 { |
|
122 nsReflowStatus reflowStatus = NS_FRAME_COMPLETE; |
|
123 |
|
124 bool reflowAll = aReflowState.ShouldReflowAllKids(); |
|
125 |
|
126 nsIFrame* kidFrame; |
|
127 nsOverflowContinuationTracker tracker(aDelegatingFrame, true); |
|
128 for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) { |
|
129 bool kidNeedsReflow = reflowAll || NS_SUBTREE_DIRTY(kidFrame) || |
|
130 FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged); |
|
131 if (kidNeedsReflow && !aPresContext->HasPendingInterrupt()) { |
|
132 // Reflow the frame |
|
133 nsReflowStatus kidStatus = NS_FRAME_COMPLETE; |
|
134 ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, |
|
135 aContainingBlock, |
|
136 aConstrainHeight, kidFrame, kidStatus, |
|
137 aOverflowAreas); |
|
138 nsIFrame* nextFrame = kidFrame->GetNextInFlow(); |
|
139 if (!NS_FRAME_IS_FULLY_COMPLETE(kidStatus)) { |
|
140 // Need a continuation |
|
141 if (!nextFrame) { |
|
142 nextFrame = |
|
143 aPresContext->PresShell()->FrameConstructor()-> |
|
144 CreateContinuingFrame(aPresContext, kidFrame, aDelegatingFrame); |
|
145 } |
|
146 // Add it as an overflow container. |
|
147 //XXXfr This is a hack to fix some of our printing dataloss. |
|
148 // See bug 154892. Not sure how to do it "right" yet; probably want |
|
149 // to keep continuations within an nsAbsoluteContainingBlock eventually. |
|
150 tracker.Insert(nextFrame, kidStatus); |
|
151 NS_MergeReflowStatusInto(&reflowStatus, kidStatus); |
|
152 } |
|
153 else { |
|
154 // Delete any continuations |
|
155 if (nextFrame) { |
|
156 nsOverflowContinuationTracker::AutoFinish fini(&tracker, kidFrame); |
|
157 static_cast<nsContainerFrame*>(nextFrame->GetParent()) |
|
158 ->DeleteNextInFlowChild(nextFrame, true); |
|
159 } |
|
160 } |
|
161 } |
|
162 else { |
|
163 tracker.Skip(kidFrame, reflowStatus); |
|
164 if (aOverflowAreas) { |
|
165 aDelegatingFrame->ConsiderChildOverflow(*aOverflowAreas, kidFrame); |
|
166 } |
|
167 } |
|
168 |
|
169 // Make a CheckForInterrupt call, here, not just HasPendingInterrupt. That |
|
170 // will make sure that we end up reflowing aDelegatingFrame in cases when |
|
171 // one of our kids interrupted. Otherwise we'd set the dirty or |
|
172 // dirty-children bit on the kid in the condition below, and then when |
|
173 // reflow completes and we go to mark dirty bits on all ancestors of that |
|
174 // kid we'll immediately bail out, because the kid already has a dirty bit. |
|
175 // In particular, we won't set any dirty bits on aDelegatingFrame, so when |
|
176 // the following reflow happens we won't reflow the kid in question. This |
|
177 // might be slightly suboptimal in cases where |kidFrame| itself did not |
|
178 // interrupt, since we'll trigger a reflow of it too when it's not strictly |
|
179 // needed. But the logic to not do that is enough more complicated, and |
|
180 // the case enough of an edge case, that this is probably better. |
|
181 if (kidNeedsReflow && aPresContext->CheckForInterrupt(aDelegatingFrame)) { |
|
182 if (aDelegatingFrame->GetStateBits() & NS_FRAME_IS_DIRTY) { |
|
183 kidFrame->AddStateBits(NS_FRAME_IS_DIRTY); |
|
184 } else { |
|
185 kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); |
|
186 } |
|
187 } |
|
188 } |
|
189 |
|
190 // Abspos frames can't cause their parent to be incomplete, |
|
191 // only overflow incomplete. |
|
192 if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) |
|
193 NS_FRAME_SET_OVERFLOW_INCOMPLETE(reflowStatus); |
|
194 |
|
195 NS_MergeReflowStatusInto(&aReflowStatus, reflowStatus); |
|
196 return NS_OK; |
|
197 } |
|
198 |
|
199 static inline bool IsFixedPaddingSize(const nsStyleCoord& aCoord) |
|
200 { return aCoord.ConvertsToLength(); } |
|
201 static inline bool IsFixedMarginSize(const nsStyleCoord& aCoord) |
|
202 { return aCoord.ConvertsToLength(); } |
|
203 static inline bool IsFixedOffset(const nsStyleCoord& aCoord) |
|
204 { return aCoord.ConvertsToLength(); } |
|
205 |
|
206 bool |
|
207 nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f, |
|
208 bool aCBWidthChanged, |
|
209 bool aCBHeightChanged) |
|
210 { |
|
211 const nsStylePosition* pos = f->StylePosition(); |
|
212 // See if f's position might have changed because it depends on a |
|
213 // placeholder's position |
|
214 // This can happen in the following cases: |
|
215 // 1) Vertical positioning. "top" must be auto and "bottom" must be auto |
|
216 // (otherwise the vertical position is completely determined by |
|
217 // whichever of them is not auto and the height). |
|
218 // 2) Horizontal positioning. "left" must be auto and "right" must be auto |
|
219 // (otherwise the horizontal position is completely determined by |
|
220 // whichever of them is not auto and the width). |
|
221 // See nsHTMLReflowState::InitAbsoluteConstraints -- these are the |
|
222 // only cases when we call CalculateHypotheticalBox(). |
|
223 if ((pos->mOffset.GetTopUnit() == eStyleUnit_Auto && |
|
224 pos->mOffset.GetBottomUnit() == eStyleUnit_Auto) || |
|
225 (pos->mOffset.GetLeftUnit() == eStyleUnit_Auto && |
|
226 pos->mOffset.GetRightUnit() == eStyleUnit_Auto)) { |
|
227 return true; |
|
228 } |
|
229 if (!aCBWidthChanged && !aCBHeightChanged) { |
|
230 // skip getting style data |
|
231 return false; |
|
232 } |
|
233 const nsStylePadding* padding = f->StylePadding(); |
|
234 const nsStyleMargin* margin = f->StyleMargin(); |
|
235 if (aCBWidthChanged) { |
|
236 // See if f's width might have changed. |
|
237 // If border-left, border-right, padding-left, padding-right, |
|
238 // width, min-width, and max-width are all lengths, 'none', or enumerated, |
|
239 // then our frame width does not depend on the parent width. |
|
240 // Note that borders never depend on the parent width |
|
241 // XXX All of the enumerated values except -moz-available are ok too. |
|
242 if (pos->WidthDependsOnContainer() || |
|
243 pos->MinWidthDependsOnContainer() || |
|
244 pos->MaxWidthDependsOnContainer() || |
|
245 !IsFixedPaddingSize(padding->mPadding.GetLeft()) || |
|
246 !IsFixedPaddingSize(padding->mPadding.GetRight())) { |
|
247 return true; |
|
248 } |
|
249 |
|
250 // See if f's position might have changed. If we're RTL then the |
|
251 // rules are slightly different. We'll assume percentage or auto |
|
252 // margins will always induce a dependency on the size |
|
253 if (!IsFixedMarginSize(margin->mMargin.GetLeft()) || |
|
254 !IsFixedMarginSize(margin->mMargin.GetRight())) { |
|
255 return true; |
|
256 } |
|
257 if (f->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { |
|
258 // Note that even if 'left' is a length, our position can |
|
259 // still depend on the containing block width, because if |
|
260 // 'right' is also a length we will discard 'left' and be |
|
261 // positioned relative to the containing block right edge. |
|
262 // 'left' length and 'right' auto is the only combination |
|
263 // we can be sure of. |
|
264 if (!IsFixedOffset(pos->mOffset.GetLeft()) || |
|
265 pos->mOffset.GetRightUnit() != eStyleUnit_Auto) { |
|
266 return true; |
|
267 } |
|
268 } else { |
|
269 if (!IsFixedOffset(pos->mOffset.GetLeft())) { |
|
270 return true; |
|
271 } |
|
272 } |
|
273 } |
|
274 if (aCBHeightChanged) { |
|
275 // See if f's height might have changed. |
|
276 // If border-top, border-bottom, padding-top, padding-bottom, |
|
277 // min-height, and max-height are all lengths or 'none', |
|
278 // and height is a length or height and bottom are auto and top is not auto, |
|
279 // then our frame height does not depend on the parent height. |
|
280 // Note that borders never depend on the parent height |
|
281 if ((pos->HeightDependsOnContainer() && |
|
282 !(pos->mHeight.GetUnit() == eStyleUnit_Auto && |
|
283 pos->mOffset.GetBottomUnit() == eStyleUnit_Auto && |
|
284 pos->mOffset.GetTopUnit() != eStyleUnit_Auto)) || |
|
285 pos->MinHeightDependsOnContainer() || |
|
286 pos->MaxHeightDependsOnContainer() || |
|
287 !IsFixedPaddingSize(padding->mPadding.GetTop()) || |
|
288 !IsFixedPaddingSize(padding->mPadding.GetBottom())) { |
|
289 return true; |
|
290 } |
|
291 |
|
292 // See if f's position might have changed. |
|
293 if (!IsFixedMarginSize(margin->mMargin.GetTop()) || |
|
294 !IsFixedMarginSize(margin->mMargin.GetBottom())) { |
|
295 return true; |
|
296 } |
|
297 if (!IsFixedOffset(pos->mOffset.GetTop())) { |
|
298 return true; |
|
299 } |
|
300 } |
|
301 return false; |
|
302 } |
|
303 |
|
304 void |
|
305 nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame, |
|
306 nsIFrame* aDestructRoot) |
|
307 { |
|
308 mAbsoluteFrames.DestroyFramesFrom(aDestructRoot); |
|
309 } |
|
310 |
|
311 void |
|
312 nsAbsoluteContainingBlock::MarkSizeDependentFramesDirty() |
|
313 { |
|
314 DoMarkFramesDirty(false); |
|
315 } |
|
316 |
|
317 void |
|
318 nsAbsoluteContainingBlock::MarkAllFramesDirty() |
|
319 { |
|
320 DoMarkFramesDirty(true); |
|
321 } |
|
322 |
|
323 void |
|
324 nsAbsoluteContainingBlock::DoMarkFramesDirty(bool aMarkAllDirty) |
|
325 { |
|
326 for (nsIFrame* kidFrame = mAbsoluteFrames.FirstChild(); |
|
327 kidFrame; |
|
328 kidFrame = kidFrame->GetNextSibling()) { |
|
329 if (aMarkAllDirty) { |
|
330 kidFrame->AddStateBits(NS_FRAME_IS_DIRTY); |
|
331 } else if (FrameDependsOnContainer(kidFrame, true, true)) { |
|
332 // Add the weakest flags that will make sure we reflow this frame later |
|
333 kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); |
|
334 } |
|
335 } |
|
336 } |
|
337 |
|
338 // XXX Optimize the case where it's a resize reflow and the absolutely |
|
339 // positioned child has the exact same size and position and skip the |
|
340 // reflow... |
|
341 |
|
342 // When bug 154892 is checked in, make sure that when |
|
343 // mChildListID == kFixedList, the height is unconstrained. |
|
344 // since we don't allow replicated frames to split. |
|
345 |
|
346 nsresult |
|
347 nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, |
|
348 nsPresContext* aPresContext, |
|
349 const nsHTMLReflowState& aReflowState, |
|
350 const nsRect& aContainingBlock, |
|
351 bool aConstrainHeight, |
|
352 nsIFrame* aKidFrame, |
|
353 nsReflowStatus& aStatus, |
|
354 nsOverflowAreas* aOverflowAreas) |
|
355 { |
|
356 #ifdef DEBUG |
|
357 if (nsBlockFrame::gNoisyReflow) { |
|
358 nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent); |
|
359 printf("abs pos "); |
|
360 if (aKidFrame) { |
|
361 nsAutoString name; |
|
362 aKidFrame->GetFrameName(name); |
|
363 printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); |
|
364 } |
|
365 |
|
366 char width[16]; |
|
367 char height[16]; |
|
368 PrettyUC(aReflowState.AvailableWidth(), width); |
|
369 PrettyUC(aReflowState.AvailableHeight(), height); |
|
370 printf(" a=%s,%s ", width, height); |
|
371 PrettyUC(aReflowState.ComputedWidth(), width); |
|
372 PrettyUC(aReflowState.ComputedHeight(), height); |
|
373 printf("c=%s,%s \n", width, height); |
|
374 } |
|
375 AutoNoisyIndenter indent(nsBlockFrame::gNoisy); |
|
376 #endif // DEBUG |
|
377 |
|
378 nscoord availWidth = aContainingBlock.width; |
|
379 if (availWidth == -1) { |
|
380 NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE, |
|
381 "Must have a useful width _somewhere_"); |
|
382 availWidth = |
|
383 aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalPadding().LeftRight(); |
|
384 } |
|
385 |
|
386 nsHTMLReflowMetrics kidDesiredSize(aReflowState); |
|
387 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, |
|
388 nsSize(availWidth, NS_UNCONSTRAINEDSIZE), |
|
389 aContainingBlock.width, |
|
390 aContainingBlock.height); |
|
391 |
|
392 // Send the WillReflow() notification and position the frame |
|
393 aKidFrame->WillReflow(aPresContext); |
|
394 |
|
395 // Get the border values |
|
396 const nsMargin& border = aReflowState.mStyleBorder->GetComputedBorder(); |
|
397 |
|
398 bool constrainHeight = (aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) |
|
399 && aConstrainHeight |
|
400 // Don't split if told not to (e.g. for fixed frames) |
|
401 && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame) |
|
402 //XXX we don't handle splitting frames for inline absolute containing blocks yet |
|
403 && (aKidFrame->GetRect().y <= aReflowState.AvailableHeight()); |
|
404 // Don't split things below the fold. (Ideally we shouldn't *have* |
|
405 // anything totally below the fold, but we can't position frames |
|
406 // across next-in-flow breaks yet. |
|
407 if (constrainHeight) { |
|
408 kidReflowState.AvailableHeight() = aReflowState.AvailableHeight() - border.top |
|
409 - kidReflowState.ComputedPhysicalMargin().top; |
|
410 if (NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().top) |
|
411 kidReflowState.AvailableHeight() -= kidReflowState.ComputedPhysicalOffsets().top; |
|
412 } |
|
413 |
|
414 // Do the reflow |
|
415 nsresult rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); |
|
416 |
|
417 // If we're solving for 'left' or 'top', then compute it now that we know the |
|
418 // width/height |
|
419 if ((NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) || |
|
420 (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top)) { |
|
421 nscoord aContainingBlockWidth = aContainingBlock.width; |
|
422 nscoord aContainingBlockHeight = aContainingBlock.height; |
|
423 |
|
424 if (-1 == aContainingBlockWidth) { |
|
425 // Get the containing block width/height |
|
426 kidReflowState.ComputeContainingBlockRectangle(aPresContext, |
|
427 &aReflowState, |
|
428 aContainingBlockWidth, |
|
429 aContainingBlockHeight); |
|
430 } |
|
431 |
|
432 if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) { |
|
433 NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().right, |
|
434 "Can't solve for both left and right"); |
|
435 kidReflowState.ComputedPhysicalOffsets().left = aContainingBlockWidth - |
|
436 kidReflowState.ComputedPhysicalOffsets().right - |
|
437 kidReflowState.ComputedPhysicalMargin().right - |
|
438 kidDesiredSize.Width() - |
|
439 kidReflowState.ComputedPhysicalMargin().left; |
|
440 } |
|
441 if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top) { |
|
442 kidReflowState.ComputedPhysicalOffsets().top = aContainingBlockHeight - |
|
443 kidReflowState.ComputedPhysicalOffsets().bottom - |
|
444 kidReflowState.ComputedPhysicalMargin().bottom - |
|
445 kidDesiredSize.Height() - |
|
446 kidReflowState.ComputedPhysicalMargin().top; |
|
447 } |
|
448 } |
|
449 |
|
450 // Position the child relative to our padding edge |
|
451 nsRect rect(border.left + kidReflowState.ComputedPhysicalOffsets().left + kidReflowState.ComputedPhysicalMargin().left, |
|
452 border.top + kidReflowState.ComputedPhysicalOffsets().top + kidReflowState.ComputedPhysicalMargin().top, |
|
453 kidDesiredSize.Width(), kidDesiredSize.Height()); |
|
454 |
|
455 // Offset the frame rect by the given origin of the absolute containing block. |
|
456 // If the frame is auto-positioned on both sides of an axis, it will be |
|
457 // positioned based on its containing block and we don't need to offset. |
|
458 if (aContainingBlock.TopLeft() != nsPoint(0, 0)) { |
|
459 if (!(kidReflowState.mStylePosition->mOffset.GetLeftUnit() == eStyleUnit_Auto && |
|
460 kidReflowState.mStylePosition->mOffset.GetRightUnit() == eStyleUnit_Auto)) { |
|
461 rect.x += aContainingBlock.x; |
|
462 } |
|
463 if (!(kidReflowState.mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Auto && |
|
464 kidReflowState.mStylePosition->mOffset.GetBottomUnit() == eStyleUnit_Auto)) { |
|
465 rect.y += aContainingBlock.y; |
|
466 } |
|
467 } |
|
468 |
|
469 aKidFrame->SetRect(rect); |
|
470 |
|
471 nsView* view = aKidFrame->GetView(); |
|
472 if (view) { |
|
473 // Size and position the view and set its opacity, visibility, content |
|
474 // transparency, and clip |
|
475 nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, |
|
476 kidDesiredSize.VisualOverflow()); |
|
477 } else { |
|
478 nsContainerFrame::PositionChildViews(aKidFrame); |
|
479 } |
|
480 |
|
481 aKidFrame->DidReflow(aPresContext, &kidReflowState, nsDidReflowStatus::FINISHED); |
|
482 |
|
483 #ifdef DEBUG |
|
484 if (nsBlockFrame::gNoisyReflow) { |
|
485 nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1); |
|
486 printf("abs pos "); |
|
487 if (aKidFrame) { |
|
488 nsAutoString name; |
|
489 aKidFrame->GetFrameName(name); |
|
490 printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); |
|
491 } |
|
492 printf("%p rect=%d,%d,%d,%d\n", static_cast<void*>(aKidFrame), |
|
493 rect.x, rect.y, rect.width, rect.height); |
|
494 } |
|
495 #endif |
|
496 |
|
497 if (aOverflowAreas) { |
|
498 aOverflowAreas->UnionWith(kidDesiredSize.mOverflowAreas + rect.TopLeft()); |
|
499 } |
|
500 |
|
501 return rv; |
|
502 } |