void nsBox::SetBounds(nsBoxLayoutState& aState, const nsRect& aRect, bool aRemoveOverflowAreas) { NS_BOX_ASSERTION(this, aRect.width >=0 && aRect.height >= 0, "SetBounds Size < 0"); nsRect rect(mRect); uint32_t flags = 0; GetLayoutFlags(flags); uint32_t stateFlags = aState.LayoutFlags(); flags |= stateFlags; if ((flags & NS_FRAME_NO_MOVE_FRAME) == NS_FRAME_NO_MOVE_FRAME) SetSize(aRect.Size()); else SetRect(aRect); // Nuke the overflow area. The caller is responsible for restoring // it if necessary. if (aRemoveOverflowAreas) { // remove the previously stored overflow area ClearOverflowRects(); } if (!(flags & NS_FRAME_NO_MOVE_VIEW)) { nsContainerFrame::PositionFrameView(this); if ((rect.x != aRect.x) || (rect.y != aRect.y)) nsContainerFrame::PositionChildViews(this); } /* // only if the origin changed if ((rect.x != aRect.x) || (rect.y != aRect.y)) { if (frame->HasView()) { nsContainerFrame::PositionFrameView(presContext, frame, frame->GetView()); } else { nsContainerFrame::PositionChildViews(presContext, frame); } } */ }
void nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, const nsRect& aContainingBlock, AbsPosReflowFlags aFlags, nsIFrame* aKidFrame, nsReflowStatus& aStatus, nsOverflowAreas* aOverflowAreas) { #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent); printf("abs pos "); if (aKidFrame) { nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); } char width[16]; char height[16]; PrettyUC(aReflowState.AvailableWidth(), width, 16); PrettyUC(aReflowState.AvailableHeight(), height, 16); printf(" a=%s,%s ", width, height); PrettyUC(aReflowState.ComputedWidth(), width, 16); PrettyUC(aReflowState.ComputedHeight(), height, 16); printf("c=%s,%s \n", width, height); } AutoNoisyIndenter indent(nsBlockFrame::gNoisy); #endif // DEBUG WritingMode wm = aKidFrame->GetWritingMode(); LogicalSize logicalCBSize(wm, aContainingBlock.Size()); nscoord availISize = logicalCBSize.ISize(wm); if (availISize == -1) { NS_ASSERTION(aReflowState.ComputedSize(wm).ISize(wm) != NS_UNCONSTRAINEDSIZE, "Must have a useful inline-size _somewhere_"); availISize = aReflowState.ComputedSizeWithPadding(wm).ISize(wm); } uint32_t rsFlags = 0; if (aFlags & AbsPosReflowFlags::eIsGridContainerCB) { // When a grid container generates the abs.pos. CB for a *child* then // the static-position is the CB origin (i.e. of the grid area rect). // https://drafts.csswg.org/css-grid/#static-position nsIFrame* placeholder = aPresContext->PresShell()->GetPlaceholderFrameFor(aKidFrame); if (placeholder && placeholder->GetParent() == aDelegatingFrame) { rsFlags |= nsHTMLReflowState::STATIC_POS_IS_CB_ORIGIN; } } nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, LogicalSize(wm, availISize, NS_UNCONSTRAINEDSIZE), &logicalCBSize, rsFlags); // Get the border values WritingMode outerWM = aReflowState.GetWritingMode(); const LogicalMargin border(outerWM, aReflowState.mStyleBorder->GetComputedBorder()); const LogicalMargin margin = kidReflowState.ComputedLogicalMargin().ConvertTo(outerWM, wm); bool constrainBSize = (aReflowState.AvailableBSize() != NS_UNCONSTRAINEDSIZE) && (aFlags & AbsPosReflowFlags::eConstrainHeight) // Don't split if told not to (e.g. for fixed frames) && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame) //XXX we don't handle splitting frames for inline absolute containing blocks yet && (aKidFrame->GetLogicalRect(aContainingBlock.Size()).BStart(wm) <= aReflowState.AvailableBSize()); // Don't split things below the fold. (Ideally we shouldn't *have* // anything totally below the fold, but we can't position frames // across next-in-flow breaks yet. if (constrainBSize) { kidReflowState.AvailableBSize() = aReflowState.AvailableBSize() - border.ConvertTo(wm, outerWM).BStart(wm) - kidReflowState.ComputedLogicalMargin().BStart(wm); if (NS_AUTOOFFSET != kidReflowState.ComputedLogicalOffsets().BStart(wm)) { kidReflowState.AvailableBSize() -= kidReflowState.ComputedLogicalOffsets().BStart(wm); } } // Do the reflow nsHTMLReflowMetrics kidDesiredSize(kidReflowState); aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); const LogicalSize kidSize = kidDesiredSize.Size(wm).ConvertTo(outerWM, wm); LogicalMargin offsets = kidReflowState.ComputedLogicalOffsets().ConvertTo(outerWM, wm); // If we're solving for start in either inline or block direction, // then compute it now that we know the dimensions. if ((NS_AUTOOFFSET == offsets.IStart(outerWM)) || (NS_AUTOOFFSET == offsets.BStart(outerWM))) { if (-1 == logicalCBSize.ISize(wm)) { // Get the containing block width/height logicalCBSize = kidReflowState.ComputeContainingBlockRectangle(aPresContext, &aReflowState); } if (NS_AUTOOFFSET == offsets.IStart(outerWM)) { NS_ASSERTION(NS_AUTOOFFSET != offsets.IEnd(outerWM), "Can't solve for both start and end"); offsets.IStart(outerWM) = logicalCBSize.ConvertTo(outerWM, wm).ISize(outerWM) - offsets.IEnd(outerWM) - margin.IStartEnd(outerWM) - kidSize.ISize(outerWM); } if (NS_AUTOOFFSET == offsets.BStart(outerWM)) { offsets.BStart(outerWM) = logicalCBSize.ConvertTo(outerWM, wm).BSize(outerWM) - offsets.BEnd(outerWM) - margin.BStartEnd(outerWM) - kidSize.BSize(outerWM); } kidReflowState.SetComputedLogicalOffsets(offsets.ConvertTo(wm, outerWM)); } // Position the child relative to our padding edge LogicalRect rect(outerWM, border.IStart(outerWM) + offsets.IStart(outerWM) + margin.IStart(outerWM), border.BStart(outerWM) + offsets.BStart(outerWM) + margin.BStart(outerWM), kidSize.ISize(outerWM), kidSize.BSize(outerWM)); nsRect r = rect.GetPhysicalRect(outerWM, logicalCBSize.GetPhysicalSize(wm) + border.Size(outerWM).GetPhysicalSize(outerWM)); // Offset the frame rect by the given origin of the absolute containing block. // If the frame is auto-positioned on both sides of an axis, it will be // positioned based on its containing block and we don't need to offset // (unless the caller demands it (the STATIC_POS_IS_CB_ORIGIN case)). if (aContainingBlock.TopLeft() != nsPoint(0, 0)) { const nsStyleSides& offsets = kidReflowState.mStylePosition->mOffset; if (!(offsets.GetLeftUnit() == eStyleUnit_Auto && offsets.GetRightUnit() == eStyleUnit_Auto) || (rsFlags & nsHTMLReflowState::STATIC_POS_IS_CB_ORIGIN)) { r.x += aContainingBlock.x; } if (!(offsets.GetTopUnit() == eStyleUnit_Auto && offsets.GetBottomUnit() == eStyleUnit_Auto) || (rsFlags & nsHTMLReflowState::STATIC_POS_IS_CB_ORIGIN)) { r.y += aContainingBlock.y; } } aKidFrame->SetRect(r); nsView* view = aKidFrame->GetView(); if (view) { // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, kidDesiredSize.VisualOverflow()); } else { nsContainerFrame::PositionChildViews(aKidFrame); } aKidFrame->DidReflow(aPresContext, &kidReflowState, nsDidReflowStatus::FINISHED); #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1); printf("abs pos "); if (aKidFrame) { nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); } printf("%p rect=%d,%d,%d,%d\n", static_cast<void*>(aKidFrame), r.x, r.y, r.width, r.height); } #endif if (aOverflowAreas) { aOverflowAreas->UnionWith(kidDesiredSize.mOverflowAreas + r.TopLeft()); } }
void nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, const nsRect& aContainingBlock, bool aConstrainHeight, nsIFrame* aKidFrame, nsReflowStatus& aStatus, nsOverflowAreas* aOverflowAreas) { #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent); printf("abs pos "); if (aKidFrame) { nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); } char width[16]; char height[16]; PrettyUC(aReflowState.AvailableWidth(), width); PrettyUC(aReflowState.AvailableHeight(), height); printf(" a=%s,%s ", width, height); PrettyUC(aReflowState.ComputedWidth(), width); PrettyUC(aReflowState.ComputedHeight(), height); printf("c=%s,%s \n", width, height); } AutoNoisyIndenter indent(nsBlockFrame::gNoisy); #endif // DEBUG WritingMode wm = aKidFrame->GetWritingMode(); nscoord availISize = LogicalSize(wm, aContainingBlock.Size()).ISize(wm); if (availISize == -1) { NS_ASSERTION(aReflowState.ComputedSize(wm).ISize(wm) != NS_UNCONSTRAINEDSIZE, "Must have a useful inline-size _somewhere_"); availISize = aReflowState.ComputedSizeWithPadding(wm).ISize(wm); } nsHTMLReflowMetrics kidDesiredSize(aReflowState); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, LogicalSize(wm, availISize, NS_UNCONSTRAINEDSIZE), aContainingBlock.width, aContainingBlock.height); // Get the border values const nsMargin& border = aReflowState.mStyleBorder->GetComputedBorder(); bool constrainHeight = (aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) && aConstrainHeight // Don't split if told not to (e.g. for fixed frames) && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame) //XXX we don't handle splitting frames for inline absolute containing blocks yet && (aKidFrame->GetRect().y <= aReflowState.AvailableHeight()); // Don't split things below the fold. (Ideally we shouldn't *have* // anything totally below the fold, but we can't position frames // across next-in-flow breaks yet. if (constrainHeight) { kidReflowState.AvailableHeight() = aReflowState.AvailableHeight() - border.top - kidReflowState.ComputedPhysicalMargin().top; if (NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().top) kidReflowState.AvailableHeight() -= kidReflowState.ComputedPhysicalOffsets().top; } // Do the reflow aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // If we're solving for 'left' or 'top', then compute it now that we know the // width/height if ((NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) || (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top)) { nscoord aContainingBlockWidth = aContainingBlock.width; nscoord aContainingBlockHeight = aContainingBlock.height; if (-1 == aContainingBlockWidth) { // Get the containing block width/height kidReflowState.ComputeContainingBlockRectangle(aPresContext, &aReflowState, aContainingBlockWidth, aContainingBlockHeight); } if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) { NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().right, "Can't solve for both left and right"); kidReflowState.ComputedPhysicalOffsets().left = aContainingBlockWidth - kidReflowState.ComputedPhysicalOffsets().right - kidReflowState.ComputedPhysicalMargin().right - kidDesiredSize.Width() - kidReflowState.ComputedPhysicalMargin().left; } if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top) { kidReflowState.ComputedPhysicalOffsets().top = aContainingBlockHeight - kidReflowState.ComputedPhysicalOffsets().bottom - kidReflowState.ComputedPhysicalMargin().bottom - kidDesiredSize.Height() - kidReflowState.ComputedPhysicalMargin().top; } } // Position the child relative to our padding edge nsRect rect(border.left + kidReflowState.ComputedPhysicalOffsets().left + kidReflowState.ComputedPhysicalMargin().left, border.top + kidReflowState.ComputedPhysicalOffsets().top + kidReflowState.ComputedPhysicalMargin().top, kidDesiredSize.Width(), kidDesiredSize.Height()); // Offset the frame rect by the given origin of the absolute containing block. // If the frame is auto-positioned on both sides of an axis, it will be // positioned based on its containing block and we don't need to offset. if (aContainingBlock.TopLeft() != nsPoint(0, 0)) { if (!(kidReflowState.mStylePosition->mOffset.GetLeftUnit() == eStyleUnit_Auto && kidReflowState.mStylePosition->mOffset.GetRightUnit() == eStyleUnit_Auto)) { rect.x += aContainingBlock.x; } if (!(kidReflowState.mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Auto && kidReflowState.mStylePosition->mOffset.GetBottomUnit() == eStyleUnit_Auto)) { rect.y += aContainingBlock.y; } } aKidFrame->SetRect(rect); nsView* view = aKidFrame->GetView(); if (view) { // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, kidDesiredSize.VisualOverflow()); } else { nsContainerFrame::PositionChildViews(aKidFrame); } aKidFrame->DidReflow(aPresContext, &kidReflowState, nsDidReflowStatus::FINISHED); #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1); printf("abs pos "); if (aKidFrame) { nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); } printf("%p rect=%d,%d,%d,%d\n", static_cast<void*>(aKidFrame), rect.x, rect.y, rect.width, rect.height); } #endif if (aOverflowAreas) { aOverflowAreas->UnionWith(kidDesiredSize.mOverflowAreas + rect.TopLeft()); } }
void nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsPresContext* aPresContext, const ReflowInput& aReflowInput, const nsRect& aContainingBlock, AbsPosReflowFlags aFlags, nsIFrame* aKidFrame, nsReflowStatus& aStatus, nsOverflowAreas* aOverflowAreas) { #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent); printf("abs pos "); nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); char width[16]; char height[16]; PrettyUC(aReflowInput.AvailableWidth(), width, 16); PrettyUC(aReflowInput.AvailableHeight(), height, 16); printf(" a=%s,%s ", width, height); PrettyUC(aReflowInput.ComputedWidth(), width, 16); PrettyUC(aReflowInput.ComputedHeight(), height, 16); printf("c=%s,%s \n", width, height); } AutoNoisyIndenter indent(nsBlockFrame::gNoisy); #endif // DEBUG WritingMode wm = aKidFrame->GetWritingMode(); LogicalSize logicalCBSize(wm, aContainingBlock.Size()); nscoord availISize = logicalCBSize.ISize(wm); if (availISize == -1) { NS_ASSERTION(aReflowInput.ComputedSize(wm).ISize(wm) != NS_UNCONSTRAINEDSIZE, "Must have a useful inline-size _somewhere_"); availISize = aReflowInput.ComputedSizeWithPadding(wm).ISize(wm); } uint32_t rsFlags = 0; if (aFlags & AbsPosReflowFlags::eIsGridContainerCB) { // When a grid container generates the abs.pos. CB for a *child* then // the static position is determined via CSS Box Alignment within the // abs.pos. CB (a grid area, i.e. a piece of the grid). In this scenario, // due to the multiple coordinate spaces in play, we use a convenience flag // to simply have the child's ReflowInput give it a static position at its // abs.pos. CB origin, and then we'll align & offset it from there. nsIFrame* placeholder = aPresContext->PresShell()->GetPlaceholderFrameFor(aKidFrame); if (placeholder && placeholder->GetParent() == aDelegatingFrame) { rsFlags |= ReflowInput::STATIC_POS_IS_CB_ORIGIN; } } ReflowInput kidReflowInput(aPresContext, aReflowInput, aKidFrame, LogicalSize(wm, availISize, NS_UNCONSTRAINEDSIZE), &logicalCBSize, rsFlags); // Get the border values WritingMode outerWM = aReflowInput.GetWritingMode(); const LogicalMargin border(outerWM, aReflowInput.mStyleBorder->GetComputedBorder()); LogicalMargin margin = kidReflowInput.ComputedLogicalMargin().ConvertTo(outerWM, wm); // If we're doing CSS Box Alignment in either axis, that will apply the // margin for us in that axis (since the thing that's aligned is the margin // box). So, we clear out the margin here to avoid applying it twice. if (kidReflowInput.mFlags.mIOffsetsNeedCSSAlign) { margin.IStart(outerWM) = margin.IEnd(outerWM) = 0; } if (kidReflowInput.mFlags.mBOffsetsNeedCSSAlign) { margin.BStart(outerWM) = margin.BEnd(outerWM) = 0; } bool constrainBSize = (aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE) && (aFlags & AbsPosReflowFlags::eConstrainHeight) // Don't split if told not to (e.g. for fixed frames) && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame) //XXX we don't handle splitting frames for inline absolute containing blocks yet && (aKidFrame->GetLogicalRect(aContainingBlock.Size()).BStart(wm) <= aReflowInput.AvailableBSize()); // Don't split things below the fold. (Ideally we shouldn't *have* // anything totally below the fold, but we can't position frames // across next-in-flow breaks yet. if (constrainBSize) { kidReflowInput.AvailableBSize() = aReflowInput.AvailableBSize() - border.ConvertTo(wm, outerWM).BStart(wm) - kidReflowInput.ComputedLogicalMargin().BStart(wm); if (NS_AUTOOFFSET != kidReflowInput.ComputedLogicalOffsets().BStart(wm)) { kidReflowInput.AvailableBSize() -= kidReflowInput.ComputedLogicalOffsets().BStart(wm); } } // Do the reflow ReflowOutput kidDesiredSize(kidReflowInput); aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowInput, aStatus); const LogicalSize kidSize = kidDesiredSize.Size(wm).ConvertTo(outerWM, wm); LogicalMargin offsets = kidReflowInput.ComputedLogicalOffsets().ConvertTo(outerWM, wm); // If we're solving for start in either inline or block direction, // then compute it now that we know the dimensions. ResolveSizeDependentOffsets(aPresContext, kidReflowInput, kidSize, margin, &offsets, &logicalCBSize); // Position the child relative to our padding edge LogicalRect rect(outerWM, border.IStart(outerWM) + offsets.IStart(outerWM) + margin.IStart(outerWM), border.BStart(outerWM) + offsets.BStart(outerWM) + margin.BStart(outerWM), kidSize.ISize(outerWM), kidSize.BSize(outerWM)); nsRect r = rect.GetPhysicalRect(outerWM, logicalCBSize.GetPhysicalSize(wm) + border.Size(outerWM).GetPhysicalSize(outerWM)); // Offset the frame rect by the given origin of the absolute containing block. // If the frame is auto-positioned on both sides of an axis, it will be // positioned based on its containing block and we don't need to offset // (unless the caller demands it (the STATIC_POS_IS_CB_ORIGIN case)). if (aContainingBlock.TopLeft() != nsPoint(0, 0)) { const nsStyleSides& offsets = kidReflowInput.mStylePosition->mOffset; if (!(offsets.GetLeftUnit() == eStyleUnit_Auto && offsets.GetRightUnit() == eStyleUnit_Auto) || (rsFlags & ReflowInput::STATIC_POS_IS_CB_ORIGIN)) { r.x += aContainingBlock.x; } if (!(offsets.GetTopUnit() == eStyleUnit_Auto && offsets.GetBottomUnit() == eStyleUnit_Auto) || (rsFlags & ReflowInput::STATIC_POS_IS_CB_ORIGIN)) { r.y += aContainingBlock.y; } } aKidFrame->SetRect(r); nsView* view = aKidFrame->GetView(); if (view) { // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, kidDesiredSize.VisualOverflow()); } else { nsContainerFrame::PositionChildViews(aKidFrame); } aKidFrame->DidReflow(aPresContext, &kidReflowInput, nsDidReflowStatus::FINISHED); #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1); printf("abs pos "); nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); printf("%p rect=%d,%d,%d,%d\n", static_cast<void*>(aKidFrame), r.x, r.y, r.width, r.height); } #endif if (aOverflowAreas) { aOverflowAreas->UnionWith(kidDesiredSize.mOverflowAreas + r.TopLeft()); } }