void nsTableWrapperFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, const ReflowInput& aOuterRI, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsTableWrapperFrame"); DISPLAY_REFLOW(aPresContext, this, aOuterRI, aDesiredSize, aStatus); // Initialize out parameters aDesiredSize.ClearSize(); aStatus = NS_FRAME_COMPLETE; if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) { // Set up our kids. They're already present, on an overflow list, // or there are none so we'll create them now MoveOverflowToChildList(); } Maybe<ReflowInput> captionRI; Maybe<ReflowInput> innerRI; nsRect origInnerRect = InnerTableFrame()->GetRect(); nsRect origInnerVisualOverflow = InnerTableFrame()->GetVisualOverflowRect(); bool innerFirstReflow = InnerTableFrame()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW); nsRect origCaptionRect; nsRect origCaptionVisualOverflow; bool captionFirstReflow = false; if (mCaptionFrames.NotEmpty()) { origCaptionRect = mCaptionFrames.FirstChild()->GetRect(); origCaptionVisualOverflow = mCaptionFrames.FirstChild()->GetVisualOverflowRect(); captionFirstReflow = mCaptionFrames.FirstChild()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW); } // ComputeAutoSize has to match this logic. WritingMode wm = aOuterRI.GetWritingMode(); uint8_t captionSide = GetCaptionSide(); WritingMode captionWM = wm; // will be changed below if necessary if (captionSide == NO_SIDE) { // We don't have a caption. OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI, innerRI, aOuterRI.ComputedSize(wm).ISize(wm)); } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT || captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) { // ComputeAutoSize takes care of making side captions small. Compute // the caption's size first, and tell the table to fit in what's left. OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRI, captionRI, aOuterRI.ComputedSize(wm).ISize(wm)); captionWM = captionRI->GetWritingMode(); nscoord innerAvailISize = aOuterRI.ComputedSize(wm).ISize(wm) - captionRI->ComputedSizeWithMarginBorderPadding(wm).ISize(wm); OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI, innerRI, innerAvailISize); } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP || captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { // Compute the table's size first, and then prevent the caption from // being larger in the inline dir unless it has to be. // // Note that CSS 2.1 (but not 2.0) says: // The width of the anonymous box is the border-edge width of the // table box inside it // We don't actually make our anonymous box that isize (if we did, // it would break 'auto' margins), but this effectively does that. OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI, innerRI, aOuterRI.ComputedSize(wm).ISize(wm)); // It's good that CSS 2.1 says not to include margins, since we // can't, since they already been converted so they exactly // fill the available isize (ignoring the margin on one side if // neither are auto). (We take advantage of that later when we call // GetCaptionOrigin, though.) nscoord innerBorderISize = innerRI->ComputedSizeWithBorderPadding(wm).ISize(wm); OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRI, captionRI, innerBorderISize); captionWM = captionRI->GetWritingMode(); } else { NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE, "unexpected caption-side"); // Size the table and the caption independently. captionWM = mCaptionFrames.FirstChild()->GetWritingMode(); OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRI, captionRI, aOuterRI.ComputedSize(captionWM).ISize(captionWM)); OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI, innerRI, aOuterRI.ComputedSize(wm).ISize(wm)); } // First reflow the caption. Maybe<ReflowOutput> captionMet; LogicalSize captionSize(wm); LogicalMargin captionMargin(wm); if (mCaptionFrames.NotEmpty()) { captionMet.emplace(wm); nsReflowStatus capStatus; // don't let the caption cause incomplete OuterDoReflowChild(aPresContext, mCaptionFrames.FirstChild(), *captionRI, *captionMet, capStatus); captionSize.ISize(wm) = captionMet->ISize(wm); captionSize.BSize(wm) = captionMet->BSize(wm); captionMargin = captionRI->ComputedLogicalMargin().ConvertTo(wm, captionWM); // Now that we know the bsize of the caption, reduce the available bsize // for the table frame if we are bsize constrained and the caption is above // or below the inner table. Also reduce the CB size that we store for // our children in case we're a grid item, by the same amount. LogicalSize* cbSize = Properties().Get(GridItemCBSizeProperty()); if (NS_UNCONSTRAINEDSIZE != aOuterRI.AvailableBSize() || cbSize) { nscoord captionBSize = 0; nscoord captionISize = 0; switch (captionSide) { case NS_STYLE_CAPTION_SIDE_TOP: case NS_STYLE_CAPTION_SIDE_BOTTOM: case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: captionBSize = captionSize.BSize(wm) + captionMargin.BStartEnd(wm); break; case NS_STYLE_CAPTION_SIDE_LEFT: case NS_STYLE_CAPTION_SIDE_RIGHT: captionISize = captionSize.ISize(wm) + captionMargin.IStartEnd(wm); break; } if (NS_UNCONSTRAINEDSIZE != aOuterRI.AvailableBSize()) { innerRI->AvailableBSize() = std::max(0, innerRI->AvailableBSize() - captionBSize); } if (cbSize) { // Shrink the CB size by the size reserved for the caption. LogicalSize oldCBSize = *cbSize; cbSize->ISize(wm) = std::max(0, cbSize->ISize(wm) - captionISize); cbSize->BSize(wm) = std::max(0, cbSize->BSize(wm) - captionBSize); if (oldCBSize != *cbSize) { // Reset the inner table's ReflowInput to stretch it to the new size. innerRI.reset(); OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRI, innerRI, aOuterRI.ComputedSize(wm).ISize(wm)); } } } } // Then, now that we know how much to reduce the isize of the inner // table to account for side captions, reflow the inner table. ReflowOutput innerMet(innerRI->GetWritingMode()); OuterDoReflowChild(aPresContext, InnerTableFrame(), *innerRI, innerMet, aStatus); LogicalSize innerSize(wm, innerMet.ISize(wm), innerMet.BSize(wm)); LogicalMargin innerMargin = innerRI->ComputedLogicalMargin(); LogicalSize containSize(wm, GetContainingBlockSize(aOuterRI)); // Now that we've reflowed both we can place them. // XXXldb Most of the input variables here are now uninitialized! // XXX Need to recompute inner table's auto margins for the case of side // captions. (Caption's are broken too, but that should be fixed earlier.) // Compute the desiredSize so that we can use it as the containerSize // for the FinishReflowChild calls below. LogicalSize desiredSize(wm); SetDesiredSize(captionSide, innerSize, captionSize, innerMargin, captionMargin, desiredSize.ISize(wm), desiredSize.BSize(wm), wm); aDesiredSize.SetSize(wm, desiredSize); nsSize containerSize = aDesiredSize.PhysicalSize(); // XXX It's possible for this to be NS_UNCONSTRAINEDSIZE, which will result // in assertions from FinishReflowChild. if (mCaptionFrames.NotEmpty()) { LogicalPoint captionOrigin(wm); GetCaptionOrigin(captionSide, containSize, innerSize, innerMargin, captionSize, captionMargin, captionOrigin, wm); FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, *captionMet, captionRI.ptr(), wm, captionOrigin, containerSize, 0); captionRI.reset(); } // XXX If the bsize is constrained then we need to check whether // everything still fits... LogicalPoint innerOrigin(wm); GetInnerOrigin(captionSide, containSize, captionSize, captionMargin, innerSize, innerMargin, innerOrigin, wm); FinishReflowChild(InnerTableFrame(), aPresContext, innerMet, innerRI.ptr(), wm, innerOrigin, containerSize, 0); innerRI.reset(); nsTableFrame::InvalidateTableFrame(InnerTableFrame(), origInnerRect, origInnerVisualOverflow, innerFirstReflow); if (mCaptionFrames.NotEmpty()) { nsTableFrame::InvalidateTableFrame(mCaptionFrames.FirstChild(), origCaptionRect, origCaptionVisualOverflow, captionFirstReflow); } UpdateOverflowAreas(aDesiredSize); if (GetPrevInFlow()) { ReflowOverflowContainerChildren(aPresContext, aOuterRI, aDesiredSize.mOverflowAreas, 0, aStatus); } FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aOuterRI, aStatus); // Return our desired rect NS_FRAME_SET_TRUNCATION(aStatus, aOuterRI, aDesiredSize); }