michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * code for managing absolutely positioned children of a rendering michael@0: * object that is a containing block for them michael@0: */ michael@0: michael@0: #include "nsAbsoluteContainingBlock.h" michael@0: michael@0: #include "nsContainerFrame.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsIPresShell.h" michael@0: #include "nsHTMLReflowState.h" michael@0: #include "nsPresContext.h" michael@0: #include "nsCSSFrameConstructor.h" michael@0: michael@0: #ifdef DEBUG michael@0: #include "nsBlockFrame.h" michael@0: michael@0: static void PrettyUC(nscoord aSize, char* aBuf) michael@0: { michael@0: if (NS_UNCONSTRAINEDSIZE == aSize) { michael@0: strcpy(aBuf, "UC"); michael@0: } else { michael@0: if((int32_t)0xdeadbeef == aSize) { michael@0: strcpy(aBuf, "deadbeef"); michael@0: } else { michael@0: sprintf(aBuf, "%d", aSize); michael@0: } michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: nsresult michael@0: nsAbsoluteContainingBlock::SetInitialChildList(nsIFrame* aDelegatingFrame, michael@0: ChildListID aListID, michael@0: nsFrameList& aChildList) michael@0: { michael@0: NS_PRECONDITION(mChildListID == aListID, "unexpected child list name"); michael@0: #ifdef DEBUG michael@0: nsFrame::VerifyDirtyBitSet(aChildList); michael@0: #endif michael@0: mAbsoluteFrames.SetFrames(aChildList); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsAbsoluteContainingBlock::AppendFrames(nsIFrame* aDelegatingFrame, michael@0: ChildListID aListID, michael@0: nsFrameList& aFrameList) michael@0: { michael@0: NS_ASSERTION(mChildListID == aListID, "unexpected child list"); michael@0: michael@0: // Append the frames to our list of absolutely positioned frames michael@0: #ifdef DEBUG michael@0: nsFrame::VerifyDirtyBitSet(aFrameList); michael@0: #endif michael@0: mAbsoluteFrames.AppendFrames(nullptr, aFrameList); michael@0: michael@0: // no damage to intrinsic widths, since absolutely positioned frames can't michael@0: // change them michael@0: aDelegatingFrame->PresContext()->PresShell()-> michael@0: FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize, michael@0: NS_FRAME_HAS_DIRTY_CHILDREN); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsAbsoluteContainingBlock::InsertFrames(nsIFrame* aDelegatingFrame, michael@0: ChildListID aListID, michael@0: nsIFrame* aPrevFrame, michael@0: nsFrameList& aFrameList) michael@0: { michael@0: NS_ASSERTION(mChildListID == aListID, "unexpected child list"); michael@0: NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == aDelegatingFrame, michael@0: "inserting after sibling frame with different parent"); michael@0: michael@0: #ifdef DEBUG michael@0: nsFrame::VerifyDirtyBitSet(aFrameList); michael@0: #endif michael@0: mAbsoluteFrames.InsertFrames(nullptr, aPrevFrame, aFrameList); michael@0: michael@0: // no damage to intrinsic widths, since absolutely positioned frames can't michael@0: // change them michael@0: aDelegatingFrame->PresContext()->PresShell()-> michael@0: FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize, michael@0: NS_FRAME_HAS_DIRTY_CHILDREN); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, michael@0: ChildListID aListID, michael@0: nsIFrame* aOldFrame) michael@0: { michael@0: NS_ASSERTION(mChildListID == aListID, "unexpected child list"); michael@0: nsIFrame* nif = aOldFrame->GetNextInFlow(); michael@0: if (nif) { michael@0: static_cast(nif->GetParent()) michael@0: ->DeleteNextInFlowChild(nif, false); michael@0: } michael@0: michael@0: mAbsoluteFrames.DestroyFrame(aOldFrame); michael@0: } michael@0: michael@0: nsresult michael@0: nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, michael@0: nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aReflowStatus, michael@0: const nsRect& aContainingBlock, michael@0: bool aConstrainHeight, michael@0: bool aCBWidthChanged, michael@0: bool aCBHeightChanged, michael@0: nsOverflowAreas* aOverflowAreas) michael@0: { michael@0: nsReflowStatus reflowStatus = NS_FRAME_COMPLETE; michael@0: michael@0: bool reflowAll = aReflowState.ShouldReflowAllKids(); michael@0: michael@0: nsIFrame* kidFrame; michael@0: nsOverflowContinuationTracker tracker(aDelegatingFrame, true); michael@0: for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) { michael@0: bool kidNeedsReflow = reflowAll || NS_SUBTREE_DIRTY(kidFrame) || michael@0: FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged); michael@0: if (kidNeedsReflow && !aPresContext->HasPendingInterrupt()) { michael@0: // Reflow the frame michael@0: nsReflowStatus kidStatus = NS_FRAME_COMPLETE; michael@0: ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, michael@0: aContainingBlock, michael@0: aConstrainHeight, kidFrame, kidStatus, michael@0: aOverflowAreas); michael@0: nsIFrame* nextFrame = kidFrame->GetNextInFlow(); michael@0: if (!NS_FRAME_IS_FULLY_COMPLETE(kidStatus)) { michael@0: // Need a continuation michael@0: if (!nextFrame) { michael@0: nextFrame = michael@0: aPresContext->PresShell()->FrameConstructor()-> michael@0: CreateContinuingFrame(aPresContext, kidFrame, aDelegatingFrame); michael@0: } michael@0: // Add it as an overflow container. michael@0: //XXXfr This is a hack to fix some of our printing dataloss. michael@0: // See bug 154892. Not sure how to do it "right" yet; probably want michael@0: // to keep continuations within an nsAbsoluteContainingBlock eventually. michael@0: tracker.Insert(nextFrame, kidStatus); michael@0: NS_MergeReflowStatusInto(&reflowStatus, kidStatus); michael@0: } michael@0: else { michael@0: // Delete any continuations michael@0: if (nextFrame) { michael@0: nsOverflowContinuationTracker::AutoFinish fini(&tracker, kidFrame); michael@0: static_cast(nextFrame->GetParent()) michael@0: ->DeleteNextInFlowChild(nextFrame, true); michael@0: } michael@0: } michael@0: } michael@0: else { michael@0: tracker.Skip(kidFrame, reflowStatus); michael@0: if (aOverflowAreas) { michael@0: aDelegatingFrame->ConsiderChildOverflow(*aOverflowAreas, kidFrame); michael@0: } michael@0: } michael@0: michael@0: // Make a CheckForInterrupt call, here, not just HasPendingInterrupt. That michael@0: // will make sure that we end up reflowing aDelegatingFrame in cases when michael@0: // one of our kids interrupted. Otherwise we'd set the dirty or michael@0: // dirty-children bit on the kid in the condition below, and then when michael@0: // reflow completes and we go to mark dirty bits on all ancestors of that michael@0: // kid we'll immediately bail out, because the kid already has a dirty bit. michael@0: // In particular, we won't set any dirty bits on aDelegatingFrame, so when michael@0: // the following reflow happens we won't reflow the kid in question. This michael@0: // might be slightly suboptimal in cases where |kidFrame| itself did not michael@0: // interrupt, since we'll trigger a reflow of it too when it's not strictly michael@0: // needed. But the logic to not do that is enough more complicated, and michael@0: // the case enough of an edge case, that this is probably better. michael@0: if (kidNeedsReflow && aPresContext->CheckForInterrupt(aDelegatingFrame)) { michael@0: if (aDelegatingFrame->GetStateBits() & NS_FRAME_IS_DIRTY) { michael@0: kidFrame->AddStateBits(NS_FRAME_IS_DIRTY); michael@0: } else { michael@0: kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // Abspos frames can't cause their parent to be incomplete, michael@0: // only overflow incomplete. michael@0: if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) michael@0: NS_FRAME_SET_OVERFLOW_INCOMPLETE(reflowStatus); michael@0: michael@0: NS_MergeReflowStatusInto(&aReflowStatus, reflowStatus); michael@0: return NS_OK; michael@0: } michael@0: michael@0: static inline bool IsFixedPaddingSize(const nsStyleCoord& aCoord) michael@0: { return aCoord.ConvertsToLength(); } michael@0: static inline bool IsFixedMarginSize(const nsStyleCoord& aCoord) michael@0: { return aCoord.ConvertsToLength(); } michael@0: static inline bool IsFixedOffset(const nsStyleCoord& aCoord) michael@0: { return aCoord.ConvertsToLength(); } michael@0: michael@0: bool michael@0: nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f, michael@0: bool aCBWidthChanged, michael@0: bool aCBHeightChanged) michael@0: { michael@0: const nsStylePosition* pos = f->StylePosition(); michael@0: // See if f's position might have changed because it depends on a michael@0: // placeholder's position michael@0: // This can happen in the following cases: michael@0: // 1) Vertical positioning. "top" must be auto and "bottom" must be auto michael@0: // (otherwise the vertical position is completely determined by michael@0: // whichever of them is not auto and the height). michael@0: // 2) Horizontal positioning. "left" must be auto and "right" must be auto michael@0: // (otherwise the horizontal position is completely determined by michael@0: // whichever of them is not auto and the width). michael@0: // See nsHTMLReflowState::InitAbsoluteConstraints -- these are the michael@0: // only cases when we call CalculateHypotheticalBox(). michael@0: if ((pos->mOffset.GetTopUnit() == eStyleUnit_Auto && michael@0: pos->mOffset.GetBottomUnit() == eStyleUnit_Auto) || michael@0: (pos->mOffset.GetLeftUnit() == eStyleUnit_Auto && michael@0: pos->mOffset.GetRightUnit() == eStyleUnit_Auto)) { michael@0: return true; michael@0: } michael@0: if (!aCBWidthChanged && !aCBHeightChanged) { michael@0: // skip getting style data michael@0: return false; michael@0: } michael@0: const nsStylePadding* padding = f->StylePadding(); michael@0: const nsStyleMargin* margin = f->StyleMargin(); michael@0: if (aCBWidthChanged) { michael@0: // See if f's width might have changed. michael@0: // If border-left, border-right, padding-left, padding-right, michael@0: // width, min-width, and max-width are all lengths, 'none', or enumerated, michael@0: // then our frame width does not depend on the parent width. michael@0: // Note that borders never depend on the parent width michael@0: // XXX All of the enumerated values except -moz-available are ok too. michael@0: if (pos->WidthDependsOnContainer() || michael@0: pos->MinWidthDependsOnContainer() || michael@0: pos->MaxWidthDependsOnContainer() || michael@0: !IsFixedPaddingSize(padding->mPadding.GetLeft()) || michael@0: !IsFixedPaddingSize(padding->mPadding.GetRight())) { michael@0: return true; michael@0: } michael@0: michael@0: // See if f's position might have changed. If we're RTL then the michael@0: // rules are slightly different. We'll assume percentage or auto michael@0: // margins will always induce a dependency on the size michael@0: if (!IsFixedMarginSize(margin->mMargin.GetLeft()) || michael@0: !IsFixedMarginSize(margin->mMargin.GetRight())) { michael@0: return true; michael@0: } michael@0: if (f->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { michael@0: // Note that even if 'left' is a length, our position can michael@0: // still depend on the containing block width, because if michael@0: // 'right' is also a length we will discard 'left' and be michael@0: // positioned relative to the containing block right edge. michael@0: // 'left' length and 'right' auto is the only combination michael@0: // we can be sure of. michael@0: if (!IsFixedOffset(pos->mOffset.GetLeft()) || michael@0: pos->mOffset.GetRightUnit() != eStyleUnit_Auto) { michael@0: return true; michael@0: } michael@0: } else { michael@0: if (!IsFixedOffset(pos->mOffset.GetLeft())) { michael@0: return true; michael@0: } michael@0: } michael@0: } michael@0: if (aCBHeightChanged) { michael@0: // See if f's height might have changed. michael@0: // If border-top, border-bottom, padding-top, padding-bottom, michael@0: // min-height, and max-height are all lengths or 'none', michael@0: // and height is a length or height and bottom are auto and top is not auto, michael@0: // then our frame height does not depend on the parent height. michael@0: // Note that borders never depend on the parent height michael@0: if ((pos->HeightDependsOnContainer() && michael@0: !(pos->mHeight.GetUnit() == eStyleUnit_Auto && michael@0: pos->mOffset.GetBottomUnit() == eStyleUnit_Auto && michael@0: pos->mOffset.GetTopUnit() != eStyleUnit_Auto)) || michael@0: pos->MinHeightDependsOnContainer() || michael@0: pos->MaxHeightDependsOnContainer() || michael@0: !IsFixedPaddingSize(padding->mPadding.GetTop()) || michael@0: !IsFixedPaddingSize(padding->mPadding.GetBottom())) { michael@0: return true; michael@0: } michael@0: michael@0: // See if f's position might have changed. michael@0: if (!IsFixedMarginSize(margin->mMargin.GetTop()) || michael@0: !IsFixedMarginSize(margin->mMargin.GetBottom())) { michael@0: return true; michael@0: } michael@0: if (!IsFixedOffset(pos->mOffset.GetTop())) { michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: void michael@0: nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame, michael@0: nsIFrame* aDestructRoot) michael@0: { michael@0: mAbsoluteFrames.DestroyFramesFrom(aDestructRoot); michael@0: } michael@0: michael@0: void michael@0: nsAbsoluteContainingBlock::MarkSizeDependentFramesDirty() michael@0: { michael@0: DoMarkFramesDirty(false); michael@0: } michael@0: michael@0: void michael@0: nsAbsoluteContainingBlock::MarkAllFramesDirty() michael@0: { michael@0: DoMarkFramesDirty(true); michael@0: } michael@0: michael@0: void michael@0: nsAbsoluteContainingBlock::DoMarkFramesDirty(bool aMarkAllDirty) michael@0: { michael@0: for (nsIFrame* kidFrame = mAbsoluteFrames.FirstChild(); michael@0: kidFrame; michael@0: kidFrame = kidFrame->GetNextSibling()) { michael@0: if (aMarkAllDirty) { michael@0: kidFrame->AddStateBits(NS_FRAME_IS_DIRTY); michael@0: } else if (FrameDependsOnContainer(kidFrame, true, true)) { michael@0: // Add the weakest flags that will make sure we reflow this frame later michael@0: kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // XXX Optimize the case where it's a resize reflow and the absolutely michael@0: // positioned child has the exact same size and position and skip the michael@0: // reflow... michael@0: michael@0: // When bug 154892 is checked in, make sure that when michael@0: // mChildListID == kFixedList, the height is unconstrained. michael@0: // since we don't allow replicated frames to split. michael@0: michael@0: nsresult michael@0: nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, michael@0: nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: const nsRect& aContainingBlock, michael@0: bool aConstrainHeight, michael@0: nsIFrame* aKidFrame, michael@0: nsReflowStatus& aStatus, michael@0: nsOverflowAreas* aOverflowAreas) michael@0: { michael@0: #ifdef DEBUG michael@0: if (nsBlockFrame::gNoisyReflow) { michael@0: nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent); michael@0: printf("abs pos "); michael@0: if (aKidFrame) { michael@0: nsAutoString name; michael@0: aKidFrame->GetFrameName(name); michael@0: printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); michael@0: } michael@0: michael@0: char width[16]; michael@0: char height[16]; michael@0: PrettyUC(aReflowState.AvailableWidth(), width); michael@0: PrettyUC(aReflowState.AvailableHeight(), height); michael@0: printf(" a=%s,%s ", width, height); michael@0: PrettyUC(aReflowState.ComputedWidth(), width); michael@0: PrettyUC(aReflowState.ComputedHeight(), height); michael@0: printf("c=%s,%s \n", width, height); michael@0: } michael@0: AutoNoisyIndenter indent(nsBlockFrame::gNoisy); michael@0: #endif // DEBUG michael@0: michael@0: nscoord availWidth = aContainingBlock.width; michael@0: if (availWidth == -1) { michael@0: NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE, michael@0: "Must have a useful width _somewhere_"); michael@0: availWidth = michael@0: aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalPadding().LeftRight(); michael@0: } michael@0: michael@0: nsHTMLReflowMetrics kidDesiredSize(aReflowState); michael@0: nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, michael@0: nsSize(availWidth, NS_UNCONSTRAINEDSIZE), michael@0: aContainingBlock.width, michael@0: aContainingBlock.height); michael@0: michael@0: // Send the WillReflow() notification and position the frame michael@0: aKidFrame->WillReflow(aPresContext); michael@0: michael@0: // Get the border values michael@0: const nsMargin& border = aReflowState.mStyleBorder->GetComputedBorder(); michael@0: michael@0: bool constrainHeight = (aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) michael@0: && aConstrainHeight michael@0: // Don't split if told not to (e.g. for fixed frames) michael@0: && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame) michael@0: //XXX we don't handle splitting frames for inline absolute containing blocks yet michael@0: && (aKidFrame->GetRect().y <= aReflowState.AvailableHeight()); michael@0: // Don't split things below the fold. (Ideally we shouldn't *have* michael@0: // anything totally below the fold, but we can't position frames michael@0: // across next-in-flow breaks yet. michael@0: if (constrainHeight) { michael@0: kidReflowState.AvailableHeight() = aReflowState.AvailableHeight() - border.top michael@0: - kidReflowState.ComputedPhysicalMargin().top; michael@0: if (NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().top) michael@0: kidReflowState.AvailableHeight() -= kidReflowState.ComputedPhysicalOffsets().top; michael@0: } michael@0: michael@0: // Do the reflow michael@0: nsresult rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); michael@0: michael@0: // If we're solving for 'left' or 'top', then compute it now that we know the michael@0: // width/height michael@0: if ((NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) || michael@0: (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top)) { michael@0: nscoord aContainingBlockWidth = aContainingBlock.width; michael@0: nscoord aContainingBlockHeight = aContainingBlock.height; michael@0: michael@0: if (-1 == aContainingBlockWidth) { michael@0: // Get the containing block width/height michael@0: kidReflowState.ComputeContainingBlockRectangle(aPresContext, michael@0: &aReflowState, michael@0: aContainingBlockWidth, michael@0: aContainingBlockHeight); michael@0: } michael@0: michael@0: if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) { michael@0: NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().right, michael@0: "Can't solve for both left and right"); michael@0: kidReflowState.ComputedPhysicalOffsets().left = aContainingBlockWidth - michael@0: kidReflowState.ComputedPhysicalOffsets().right - michael@0: kidReflowState.ComputedPhysicalMargin().right - michael@0: kidDesiredSize.Width() - michael@0: kidReflowState.ComputedPhysicalMargin().left; michael@0: } michael@0: if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top) { michael@0: kidReflowState.ComputedPhysicalOffsets().top = aContainingBlockHeight - michael@0: kidReflowState.ComputedPhysicalOffsets().bottom - michael@0: kidReflowState.ComputedPhysicalMargin().bottom - michael@0: kidDesiredSize.Height() - michael@0: kidReflowState.ComputedPhysicalMargin().top; michael@0: } michael@0: } michael@0: michael@0: // Position the child relative to our padding edge michael@0: nsRect rect(border.left + kidReflowState.ComputedPhysicalOffsets().left + kidReflowState.ComputedPhysicalMargin().left, michael@0: border.top + kidReflowState.ComputedPhysicalOffsets().top + kidReflowState.ComputedPhysicalMargin().top, michael@0: kidDesiredSize.Width(), kidDesiredSize.Height()); michael@0: michael@0: // Offset the frame rect by the given origin of the absolute containing block. michael@0: // If the frame is auto-positioned on both sides of an axis, it will be michael@0: // positioned based on its containing block and we don't need to offset. michael@0: if (aContainingBlock.TopLeft() != nsPoint(0, 0)) { michael@0: if (!(kidReflowState.mStylePosition->mOffset.GetLeftUnit() == eStyleUnit_Auto && michael@0: kidReflowState.mStylePosition->mOffset.GetRightUnit() == eStyleUnit_Auto)) { michael@0: rect.x += aContainingBlock.x; michael@0: } michael@0: if (!(kidReflowState.mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Auto && michael@0: kidReflowState.mStylePosition->mOffset.GetBottomUnit() == eStyleUnit_Auto)) { michael@0: rect.y += aContainingBlock.y; michael@0: } michael@0: } michael@0: michael@0: aKidFrame->SetRect(rect); michael@0: michael@0: nsView* view = aKidFrame->GetView(); michael@0: if (view) { michael@0: // Size and position the view and set its opacity, visibility, content michael@0: // transparency, and clip michael@0: nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, michael@0: kidDesiredSize.VisualOverflow()); michael@0: } else { michael@0: nsContainerFrame::PositionChildViews(aKidFrame); michael@0: } michael@0: michael@0: aKidFrame->DidReflow(aPresContext, &kidReflowState, nsDidReflowStatus::FINISHED); michael@0: michael@0: #ifdef DEBUG michael@0: if (nsBlockFrame::gNoisyReflow) { michael@0: nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1); michael@0: printf("abs pos "); michael@0: if (aKidFrame) { michael@0: nsAutoString name; michael@0: aKidFrame->GetFrameName(name); michael@0: printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); michael@0: } michael@0: printf("%p rect=%d,%d,%d,%d\n", static_cast(aKidFrame), michael@0: rect.x, rect.y, rect.width, rect.height); michael@0: } michael@0: #endif michael@0: michael@0: if (aOverflowAreas) { michael@0: aOverflowAreas->UnionWith(kidDesiredSize.mOverflowAreas + rect.TopLeft()); michael@0: } michael@0: michael@0: return rv; michael@0: }