nsresult nsFieldSetFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_PRECONDITION(aReflowState.ComputedWidth() != NS_INTRINSICSIZE, "Should have a precomputed width!"); // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; nsOverflowAreas ocBounds; nsReflowStatus ocStatus = NS_FRAME_COMPLETE; if (GetPrevInFlow()) { ReflowOverflowContainerChildren(aPresContext, aReflowState, ocBounds, 0, ocStatus); } //------------ Handle Incremental Reflow ----------------- bool reflowInner; bool reflowLegend; nsIFrame* legend = GetLegend(); nsIFrame* inner = GetInner(); if (aReflowState.ShouldReflowAllKids()) { reflowInner = inner != nullptr; reflowLegend = legend != nullptr; } else { reflowInner = inner && NS_SUBTREE_DIRTY(inner); reflowLegend = legend && NS_SUBTREE_DIRTY(legend); } // We don't allow fieldsets to break vertically. If we did, we'd // need logic here to push and pull overflow frames. // Since we're not applying our padding in this frame, we need to add it here // to compute the available width for our children. nsSize availSize(aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalPadding().LeftRight(), NS_UNCONSTRAINEDSIZE); NS_ASSERTION(!inner || nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, inner, nsLayoutUtils::MIN_WIDTH) <= availSize.width, "Bogus availSize.width; should be bigger"); NS_ASSERTION(!legend || nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, legend, nsLayoutUtils::MIN_WIDTH) <= availSize.width, "Bogus availSize.width; should be bigger"); // get our border and padding nsMargin border = aReflowState.ComputedPhysicalBorderPadding() - aReflowState.ComputedPhysicalPadding(); // Figure out how big the legend is if there is one. // get the legend's margin nsMargin legendMargin(0,0,0,0); // reflow the legend only if needed Maybe<nsHTMLReflowState> legendReflowState; if (legend) { legendReflowState.construct(aPresContext, aReflowState, legend, availSize); } if (reflowLegend) { nsHTMLReflowMetrics legendDesiredSize(aReflowState); ReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState.ref(), 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); #ifdef NOISY_REFLOW printf(" returned (%d, %d)\n", legendDesiredSize.Width(), legendDesiredSize.Height()); #endif // figure out the legend's rectangle legendMargin = legend->GetUsedMargin(); mLegendRect.width = legendDesiredSize.Width() + legendMargin.left + legendMargin.right; mLegendRect.height = legendDesiredSize.Height() + legendMargin.top + legendMargin.bottom; mLegendRect.x = 0; mLegendRect.y = 0; nscoord oldSpace = mLegendSpace; mLegendSpace = 0; if (mLegendRect.height > border.top) { // center the border on the legend mLegendSpace = mLegendRect.height - border.top; } else { mLegendRect.y = (border.top - mLegendRect.height)/2; } // if the legend space changes then we need to reflow the // content area as well. if (mLegendSpace != oldSpace && inner) { reflowInner = true; } FinishReflowChild(legend, aPresContext, legendDesiredSize, &legendReflowState.ref(), 0, 0, NS_FRAME_NO_MOVE_FRAME); } else if (!legend) { mLegendRect.SetEmpty(); mLegendSpace = 0; } else { // mLegendSpace and mLegendRect haven't changed, but we need // the used margin when placing the legend. legendMargin = legend->GetUsedMargin(); } // reflow the content frame only if needed if (reflowInner) { nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner, availSize, -1, -1, nsHTMLReflowState::CALLER_WILL_INIT); // Override computed padding, in case it's percentage padding kidReflowState.Init(aPresContext, -1, -1, nullptr, &aReflowState.ComputedPhysicalPadding()); // Our child is "height:100%" but we actually want its height to be reduced // by the amount of content-height the legend is eating up, unless our // height is unconstrained (in which case the child's will be too). if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) { kidReflowState.SetComputedHeight( std::max(0, aReflowState.ComputedHeight() - mLegendSpace)); } if (aReflowState.ComputedMinHeight() > 0) { kidReflowState.ComputedMinHeight() = std::max(0, aReflowState.ComputedMinHeight() - mLegendSpace); } if (aReflowState.ComputedMaxHeight() != NS_UNCONSTRAINEDSIZE) { kidReflowState.ComputedMaxHeight() = std::max(0, aReflowState.ComputedMaxHeight() - mLegendSpace); } nsHTMLReflowMetrics kidDesiredSize(kidReflowState, aDesiredSize.mFlags); // Reflow the frame NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0), "Margins on anonymous fieldset child not supported!"); nsPoint pt(border.left, border.top + mLegendSpace); ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState, pt.x, pt.y, 0, aStatus); FinishReflowChild(inner, aPresContext, kidDesiredSize, &kidReflowState, pt.x, pt.y, 0); NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); } nsRect contentRect; if (inner) { // We don't support margins on inner, so our content rect is just the // inner's border-box. contentRect = inner->GetRect(); } // Our content rect must fill up the available width if (availSize.width > contentRect.width) { contentRect.width = availSize.width; } if (legend) { // the legend is postioned horizontally within the inner's content rect // (so that padding on the fieldset affects the legend position). nsRect innerContentRect = contentRect; innerContentRect.Deflate(aReflowState.ComputedPhysicalPadding()); // if the inner content rect is larger than the legend, we can align the legend if (innerContentRect.width > mLegendRect.width) { int32_t align = static_cast<nsLegendFrame*> (legend->GetContentInsertionFrame())->GetAlign(); switch (align) { case NS_STYLE_TEXT_ALIGN_RIGHT: mLegendRect.x = innerContentRect.XMost() - mLegendRect.width; break; case NS_STYLE_TEXT_ALIGN_CENTER: // Note: rounding removed; there doesn't seem to be any need mLegendRect.x = innerContentRect.width / 2 - mLegendRect.width / 2 + innerContentRect.x; break; default: mLegendRect.x = innerContentRect.x; break; } } else { // otherwise make place for the legend mLegendRect.x = innerContentRect.x; innerContentRect.width = mLegendRect.width; contentRect.width = mLegendRect.width + aReflowState.ComputedPhysicalPadding().LeftRight(); } // place the legend nsRect actualLegendRect(mLegendRect); actualLegendRect.Deflate(legendMargin); nsPoint actualLegendPos(actualLegendRect.TopLeft()); legendReflowState.ref().ApplyRelativePositioning(&actualLegendPos); legend->SetPosition(actualLegendPos); nsContainerFrame::PositionFrameView(legend); nsContainerFrame::PositionChildViews(legend); } // Return our size and our result. aDesiredSize.Height() = mLegendSpace + border.TopBottom() + (inner ? inner->GetRect().height : 0); aDesiredSize.Width() = contentRect.width + border.LeftRight(); aDesiredSize.SetOverflowAreasToDesiredBounds(); if (legend) ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend); if (inner) ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner); // Merge overflow container bounds and status. aDesiredSize.mOverflowAreas.UnionWith(ocBounds); NS_MergeReflowStatusInto(&aStatus, ocStatus); FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); InvalidateFrame(); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
void BRFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("BRFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); WritingMode wm = aReflowState.GetWritingMode(); LogicalSize finalSize(wm); finalSize.BSize(wm) = 0; // BR frames with block size 0 are ignored in quirks // mode by nsLineLayout::VerticalAlignFrames . // However, it's not always 0. See below. finalSize.ISize(wm) = 0; aMetrics.SetBlockStartAscent(0); // Only when the BR is operating in a line-layout situation will it // behave like a BR. Additionally, we suppress breaks from BR inside // of ruby frames. To determine if we're inside ruby, we have to rely // on the *parent's* ShouldSuppressLineBreak() method, instead of our // own, because we may have custom "display" value that makes our // ShouldSuppressLineBreak() return false. nsLineLayout* ll = aReflowState.mLineLayout; if (ll && !GetParent()->StyleContext()->ShouldSuppressLineBreak()) { // Note that the compatibility mode check excludes AlmostStandards // mode, since this is the inline box model. See bug 161691. if ( ll->LineIsEmpty() || aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) { // The line is logically empty; any whitespace is trimmed away. // // If this frame is going to terminate the line we know // that nothing else will go on the line. Therefore, in this // case, we provide some height for the BR frame so that it // creates some vertical whitespace. It's necessary to use the // line-height rather than the font size because the // quirks-mode fix that doesn't apply the block's min // line-height makes this necessary to make BR cause a line // of the full line-height // We also do this in strict mode because BR should act like a // normal inline frame. That line-height is used is important // here for cases where the line-height is less than 1. nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), nsLayoutUtils::FontSizeInflationFor(this)); if (fm) { nscoord logicalHeight = aReflowState.CalcLineHeight(); finalSize.BSize(wm) = logicalHeight; aMetrics.SetBlockStartAscent(nsLayoutUtils::GetCenteredFontBaseline( fm, logicalHeight, wm.IsLineInverted())); } else { aMetrics.SetBlockStartAscent(aMetrics.BSize(wm) = 0); } // XXX temporary until I figure out a better solution; see the // code in nsLineLayout::VerticalAlignFrames that zaps minY/maxY // if the width is zero. // XXX This also fixes bug 10036! // Warning: nsTextControlFrame::CalculateSizeStandard depends on // the following line, see bug 228752. finalSize.ISize(wm) = 1; } // Return our reflow status uint32_t breakType = aReflowState.mStyleDisplay->mBreakType; if (NS_STYLE_CLEAR_NONE == breakType) { breakType = NS_STYLE_CLEAR_LINE; } aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType); ll->SetLineEndsInBR(true); } else { aStatus = NS_FRAME_COMPLETE; } aMetrics.SetSize(wm, finalSize); aMetrics.SetOverflowAreasToDesiredBounds(); mAscent = aMetrics.BlockStartAscent(); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); }
nsresult ViewportFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("ViewportFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow"); // Initialize OUT parameters aStatus = NS_FRAME_COMPLETE; // Because |Reflow| sets mComputedHeight on the child to // availableHeight. AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT); // Set our size up front, since some parts of reflow depend on it // being already set. Note that the computed height may be // unconstrained; that's ok. Consumers should watch out for that. SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); // Reflow the main content first so that the placeholders of the // fixed-position frames will be in the right places on an initial // reflow. nscoord kidHeight = 0; nsresult rv = NS_OK; if (mFrames.NotEmpty()) { // Deal with a non-incremental reflow or an incremental reflow // targeted at our one-and-only principal child frame. if (aReflowState.ShouldReflowAllKids() || aReflowState.mFlags.mVResize || NS_SUBTREE_DIRTY(mFrames.FirstChild())) { // Reflow our one-and-only principal child frame nsIFrame* kidFrame = mFrames.FirstChild(); nsHTMLReflowMetrics kidDesiredSize(aReflowState); nsSize availableSpace(aReflowState.AvailableWidth(), aReflowState.AvailableHeight()); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availableSpace); // Reflow the frame kidReflowState.SetComputedHeight(aReflowState.ComputedHeight()); rv = ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, 0, 0, 0, aStatus); kidHeight = kidDesiredSize.Height(); FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, nullptr, 0, 0, 0); } else { kidHeight = mFrames.FirstChild()->GetSize().height; } } NS_ASSERTION(aReflowState.AvailableWidth() != NS_UNCONSTRAINEDSIZE, "shouldn't happen anymore"); // Return the max size as our desired size aDesiredSize.Width() = aReflowState.AvailableWidth(); // Being flowed initially at an unconstrained height means we should // return our child's intrinsic size. aDesiredSize.Height() = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE ? aReflowState.ComputedHeight() : kidHeight; aDesiredSize.SetOverflowAreasToDesiredBounds(); if (mFrames.NotEmpty()) { ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild()); } if (IsAbsoluteContainer()) { // Make a copy of the reflow state and change the computed width and height // to reflect the available space for the fixed items nsHTMLReflowState reflowState(aReflowState); if (reflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE) { // We have an intrinsic-height document with abs-pos/fixed-pos children. // Set the available height and mComputedHeight to our chosen height. reflowState.AvailableHeight() = aDesiredSize.Height(); // Not having border/padding simplifies things NS_ASSERTION(reflowState.ComputedPhysicalBorderPadding() == nsMargin(0,0,0,0), "Viewports can't have border/padding"); reflowState.SetComputedHeight(aDesiredSize.Height()); } nsRect rect = AdjustReflowStateAsContainingBlock(&reflowState); // Just reflow all the fixed-pos frames. rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus, rect, false, true, true, // XXX could be optimized &aDesiredSize.mOverflowAreas); } // If we were dirty then do a repaint if (GetStateBits() & NS_FRAME_IS_DIRTY) { InvalidateFrame(); } // Clipping is handled by the document container (e.g., nsSubDocumentFrame), // so we don't need to change our overflow areas. bool overflowChanged = FinishAndStoreOverflow(&aDesiredSize); if (overflowChanged) { // We may need to alert our container to get it to pick up the // overflow change. nsSubDocumentFrame* container = static_cast<nsSubDocumentFrame*> (nsLayoutUtils::GetCrossDocParentFrame(this)); if (container && !container->ShouldClipSubdocument()) { container->PresContext()->PresShell()-> FrameNeedsReflow(container, nsIPresShell::eResize, NS_FRAME_IS_DIRTY); } } NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return rv; }
NS_IMETHODIMP nsSubDocumentFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); // printf("OuterFrame::Reflow %X (%d,%d) \n", this, aReflowState.availableWidth, aReflowState.availableHeight); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); aStatus = NS_FRAME_COMPLETE; NS_ASSERTION(mContent->GetPrimaryFrame() == this, "Shouldn't happen"); // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed> nsresult rv = nsLeafFrame::DoReflow(aPresContext, aDesiredSize, aReflowState, aStatus); NS_ENSURE_SUCCESS(rv, rv); // "offset" is the offset of our content area from our frame's // top-left corner. nsPoint offset = nsPoint(aReflowState.mComputedBorderPadding.left, aReflowState.mComputedBorderPadding.top); nsSize innerSize(aDesiredSize.width, aDesiredSize.height); innerSize.width -= aReflowState.mComputedBorderPadding.LeftRight(); innerSize.height -= aReflowState.mComputedBorderPadding.TopBottom(); if (mInnerView) { nsViewManager* vm = mInnerView->GetViewManager(); vm->MoveViewTo(mInnerView, offset.x, offset.y); vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), true); } aDesiredSize.SetOverflowAreasToDesiredBounds(); if (!ShouldClipSubdocument()) { nsIFrame* subdocRootFrame = GetSubdocumentRootFrame(); if (subdocRootFrame) { aDesiredSize.mOverflowAreas.UnionWith(subdocRootFrame->GetOverflowAreas() + offset); } } FinishAndStoreOverflow(&aDesiredSize); if (!aPresContext->IsPaginated() && !mPostedReflowCallback) { PresContext()->PresShell()->PostReflowCallback(this); mPostedReflowCallback = true; } // printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this, // aDesiredSize.width, aDesiredSize.height); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x", aDesiredSize.width, aDesiredSize.height, aStatus)); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
NS_IMETHODIMP nsVideoFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsVideoFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsVideoFrame::Reflow: availSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); aStatus = NS_FRAME_COMPLETE; aMetrics.width = aReflowState.ComputedWidth(); aMetrics.height = aReflowState.ComputedHeight(); // stash this away so we can compute our inner area later mBorderPadding = aReflowState.mComputedBorderPadding; aMetrics.width += mBorderPadding.left + mBorderPadding.right; aMetrics.height += mBorderPadding.top + mBorderPadding.bottom; // Reflow the child frames. We may have up to two, an image frame // which is the poster, and a box frame, which is the video controls. for (nsIFrame *child = mFrames.FirstChild(); child; child = child->GetNextSibling()) { if (child->GetType() == nsGkAtoms::imageFrame) { // Reflow the poster frame. nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child); nsHTMLReflowMetrics kidDesiredSize; nsSize availableSize = nsSize(aReflowState.availableWidth, aReflowState.availableHeight); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, imageFrame, availableSize, aMetrics.width, aMetrics.height); uint32_t posterHeight, posterWidth; nsSize scaledPosterSize(0, 0); nsSize computedArea(aReflowState.ComputedWidth(), aReflowState.ComputedHeight()); nsPoint posterTopLeft(0, 0); nsCOMPtr<nsIDOMHTMLImageElement> posterImage = do_QueryInterface(mPosterImage); NS_ENSURE_TRUE(posterImage, NS_ERROR_FAILURE); posterImage->GetNaturalHeight(&posterHeight); posterImage->GetNaturalWidth(&posterWidth); if (ShouldDisplayPoster() && posterHeight && posterWidth) { gfxFloat scale = NS_MIN(static_cast<float>(computedArea.width)/nsPresContext::CSSPixelsToAppUnits(static_cast<float>(posterWidth)), static_cast<float>(computedArea.height)/nsPresContext::CSSPixelsToAppUnits(static_cast<float>(posterHeight))); gfxSize scaledRatio = gfxSize(scale*posterWidth, scale*posterHeight); scaledPosterSize.width = nsPresContext::CSSPixelsToAppUnits(static_cast<float>(scaledRatio.width)); scaledPosterSize.height = nsPresContext::CSSPixelsToAppUnits(static_cast<int32_t>(scaledRatio.height)); } kidReflowState.SetComputedWidth(scaledPosterSize.width); kidReflowState.SetComputedHeight(scaledPosterSize.height); posterTopLeft.x = ((computedArea.width - scaledPosterSize.width) / 2) + mBorderPadding.left; posterTopLeft.y = ((computedArea.height - scaledPosterSize.height) / 2) + mBorderPadding.top; ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState, posterTopLeft.x, posterTopLeft.y, 0, aStatus); FinishReflowChild(imageFrame, aPresContext, &kidReflowState, kidDesiredSize, posterTopLeft.x, posterTopLeft.y, 0); } else if (child->GetType() == nsGkAtoms::boxFrame) { // Reflow the video controls frame. nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext); nsBoxFrame::LayoutChildAt(boxState, child, nsRect(mBorderPadding.left, mBorderPadding.top, aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); } } aMetrics.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aMetrics); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsVideoFrame::Reflow: size=%d,%d", aMetrics.width, aMetrics.height)); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); return NS_OK; }
NS_IMETHODIMP nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_PRECONDITION(aReflowState.ComputedWidth() != NS_INTRINSICSIZE, "Should have real computed width by now"); if (mState & NS_FRAME_FIRST_REFLOW) { nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), true); } // Reflow the child nsIFrame* firstKid = mFrames.FirstChild(); // XXXbz Eventually we may want to check-and-bail if // !aReflowState.ShouldReflowAllKids() && // !NS_SUBTREE_DIRTY(firstKid). // We'd need to cache our ascent for that, of course. nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding(); // Reflow the contents of the button. ReflowButtonContents(aPresContext, aDesiredSize, aReflowState, firstKid, focusPadding, aStatus); aDesiredSize.width = aReflowState.ComputedWidth(); // If computed use the computed value. if (aReflowState.ComputedHeight() != NS_INTRINSICSIZE) { aDesiredSize.height = aReflowState.ComputedHeight(); } else { aDesiredSize.height += focusPadding.TopBottom(); // Make sure we obey min/max-height in the case when we're doing intrinsic // sizing (we get it for free when we have a non-intrinsic // aReflowState.ComputedHeight()). Note that we do this before adjusting // for borderpadding, since mComputedMaxHeight and mComputedMinHeight are // content heights. aDesiredSize.height = NS_CSS_MINMAX(aDesiredSize.height, aReflowState.mComputedMinHeight, aReflowState.mComputedMaxHeight); } aDesiredSize.width += aReflowState.mComputedBorderPadding.LeftRight(); aDesiredSize.height += aReflowState.mComputedBorderPadding.TopBottom(); aDesiredSize.ascent += aReflowState.mComputedBorderPadding.top + focusPadding.top; aDesiredSize.SetOverflowAreasToDesiredBounds(); ConsiderChildOverflow(aDesiredSize.mOverflowAreas, firstKid); FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
void nsNumberControlFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsNumberControlFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_ASSERTION(mOuterWrapper, "Outer wrapper div must exist!"); NS_ASSERTION(!GetPrevContinuation() && !GetNextContinuation(), "nsNumberControlFrame should not have continuations; if it does we " "need to call RegUnregAccessKey only for the first"); NS_ASSERTION(!mFrames.FirstChild() || !mFrames.FirstChild()->GetNextSibling(), "We expect at most one direct child frame"); if (mState & NS_FRAME_FIRST_REFLOW) { nsFormControlFrame::RegUnRegAccessKey(this, true); } const WritingMode myWM = aReflowState.GetWritingMode(); // The ISize of our content box, which is the available ISize // for our anonymous content: const nscoord contentBoxISize = aReflowState.ComputedISize(); nscoord contentBoxBSize = aReflowState.ComputedBSize(); // Figure out our border-box sizes as well (by adding borderPadding to // content-box sizes): const nscoord borderBoxISize = contentBoxISize + aReflowState.ComputedLogicalBorderPadding().IStartEnd(myWM); nscoord borderBoxBSize; if (contentBoxBSize != NS_INTRINSICSIZE) { borderBoxBSize = contentBoxBSize + aReflowState.ComputedLogicalBorderPadding().BStartEnd(myWM); } // else, we'll figure out borderBoxBSize after we resolve contentBoxBSize. nsIFrame* outerWrapperFrame = mOuterWrapper->GetPrimaryFrame(); if (!outerWrapperFrame) { // display:none? if (contentBoxBSize == NS_INTRINSICSIZE) { contentBoxBSize = 0; borderBoxBSize = aReflowState.ComputedLogicalBorderPadding().BStartEnd(myWM); } } else { NS_ASSERTION(outerWrapperFrame == mFrames.FirstChild(), "huh?"); nsHTMLReflowMetrics wrappersDesiredSize(aReflowState); WritingMode wrapperWM = outerWrapperFrame->GetWritingMode(); LogicalSize availSize = aReflowState.ComputedSize(wrapperWM); availSize.BSize(wrapperWM) = NS_UNCONSTRAINEDSIZE; nsHTMLReflowState wrapperReflowState(aPresContext, aReflowState, outerWrapperFrame, availSize); // Convert wrapper margin into my own writing-mode (in case it differs): LogicalMargin wrapperMargin = wrapperReflowState.ComputedLogicalMargin().ConvertTo(myWM, wrapperWM); // offsets of wrapper frame within this frame: LogicalPoint wrapperOffset(myWM, aReflowState.ComputedLogicalBorderPadding().IStart(myWM) + wrapperMargin.IStart(myWM), aReflowState.ComputedLogicalBorderPadding().BStart(myWM) + wrapperMargin.BStart(myWM)); nsReflowStatus childStatus; // We initially reflow the child with a dummy containerSize; positioning // will be fixed later. const nsSize dummyContainerSize; ReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize, wrapperReflowState, myWM, wrapperOffset, dummyContainerSize, 0, childStatus); MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus), "We gave our child unconstrained available block-size, " "so it should be complete"); nscoord wrappersMarginBoxBSize = wrappersDesiredSize.BSize(myWM) + wrapperMargin.BStartEnd(myWM); if (contentBoxBSize == NS_INTRINSICSIZE) { // We are intrinsically sized -- we should shrinkwrap the outer wrapper's // block-size: contentBoxBSize = wrappersMarginBoxBSize; // Make sure we obey min/max-bsize in the case when we're doing intrinsic // sizing (we get it for free when we have a non-intrinsic // aReflowState.ComputedBSize()). Note that we do this before // adjusting for borderpadding, since ComputedMaxBSize and // ComputedMinBSize are content heights. contentBoxBSize = NS_CSS_MINMAX(contentBoxBSize, aReflowState.ComputedMinBSize(), aReflowState.ComputedMaxBSize()); borderBoxBSize = contentBoxBSize + aReflowState.ComputedLogicalBorderPadding().BStartEnd(myWM); } // Center child in block axis nscoord extraSpace = contentBoxBSize - wrappersMarginBoxBSize; wrapperOffset.B(myWM) += std::max(0, extraSpace / 2); // Needed in FinishReflowChild, for logical-to-physical conversion: nsSize borderBoxSize = LogicalSize(myWM, borderBoxISize, borderBoxBSize). GetPhysicalSize(myWM); // Place the child FinishReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize, &wrapperReflowState, myWM, wrapperOffset, borderBoxSize, 0); nsSize contentBoxSize = LogicalSize(myWM, contentBoxISize, contentBoxBSize). GetPhysicalSize(myWM); aDesiredSize.SetBlockStartAscent( wrappersDesiredSize.BlockStartAscent() + outerWrapperFrame->BStart(aReflowState.GetWritingMode(), contentBoxSize)); } LogicalSize logicalDesiredSize(myWM, borderBoxISize, borderBoxBSize); aDesiredSize.SetSize(myWM, logicalDesiredSize); aDesiredSize.SetOverflowAreasToDesiredBounds(); if (outerWrapperFrame) { ConsiderChildOverflow(aDesiredSize.mOverflowAreas, outerWrapperFrame); } FinishAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
void nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(), "A Page Sequence is only for real pages"); DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); aStatus = NS_FRAME_COMPLETE; // we're always complete // Don't do incremental reflow until we've taught tables how to do // it right in paginated mode. if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { // Return our desired size SetDesiredSize(aDesiredSize, aReflowState, mSize.width, mSize.height); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); return; } // See if we can get a Print Settings from the Context if (!mPageData->mPrintSettings && aPresContext->Medium() == nsGkAtoms::print) { mPageData->mPrintSettings = aPresContext->GetPrintSettings(); } // now get out margins & edges if (mPageData->mPrintSettings) { nsIntMargin unwriteableTwips; mPageData->mPrintSettings->GetUnwriteableMarginInTwips(unwriteableTwips); NS_ASSERTION(unwriteableTwips.left >= 0 && unwriteableTwips.top >= 0 && unwriteableTwips.right >= 0 && unwriteableTwips.bottom >= 0, "Unwriteable twips should be non-negative"); nsIntMargin marginTwips; mPageData->mPrintSettings->GetMarginInTwips(marginTwips); mMargin = aPresContext->CSSTwipsToAppUnits(marginTwips + unwriteableTwips); int16_t printType; mPageData->mPrintSettings->GetPrintRange(&printType); mPrintRangeType = printType; nsIntMargin edgeTwips; mPageData->mPrintSettings->GetEdgeInTwips(edgeTwips); // sanity check the values. three inches are sometimes needed int32_t inchInTwips = NS_INCHES_TO_INT_TWIPS(3.0); edgeTwips.top = clamped(edgeTwips.top, 0, inchInTwips); edgeTwips.bottom = clamped(edgeTwips.bottom, 0, inchInTwips); edgeTwips.left = clamped(edgeTwips.left, 0, inchInTwips); edgeTwips.right = clamped(edgeTwips.right, 0, inchInTwips); mPageData->mEdgePaperMargin = aPresContext->CSSTwipsToAppUnits(edgeTwips + unwriteableTwips); } // *** Special Override *** // If this is a sub-sdoc (meaning it doesn't take the whole page) // and if this Document is in the upper left hand corner // we need to suppress the top margin or it will reflow too small nsSize pageSize = aPresContext->GetPageSize(); mPageData->mReflowSize = pageSize; // If we're printing a selection, we need to reflow with // unconstrained height, to make sure we'll get to the selection // even if it's beyond the first page of content. if (nsIPrintSettings::kRangeSelection == mPrintRangeType) { mPageData->mReflowSize.height = NS_UNCONSTRAINEDSIZE; } mPageData->mReflowMargin = mMargin; // We use the CSS "margin" property on the -moz-page pseudoelement // to determine the space between each page in print preview. // Keep a running y-offset for each page. nscoord y = 0; nscoord maxXMost = 0; // Tile the pages vertically nsHTMLReflowMetrics kidSize(aReflowState); for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { nsIFrame* kidFrame = e.get(); // Set the shared data into the page frame before reflow nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame); pf->SetSharedPageData(mPageData); // Reflow the page nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, LogicalSize(kidFrame->GetWritingMode(), pageSize)); nsReflowStatus status; kidReflowState.SetComputedWidth(kidReflowState.AvailableWidth()); //kidReflowState.SetComputedHeight(kidReflowState.AvailableHeight()); PR_PL(("AV W: %d H: %d\n", kidReflowState.AvailableWidth(), kidReflowState.AvailableHeight())); nsMargin pageCSSMargin = kidReflowState.ComputedPhysicalMargin(); y += pageCSSMargin.top; const nscoord x = pageCSSMargin.left; // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, x, y, 0); y += kidSize.Height(); y += pageCSSMargin.bottom; maxXMost = std::max(maxXMost, x + kidSize.Width() + pageCSSMargin.right); // Is the page complete? nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow(); if (NS_FRAME_IS_FULLY_COMPLETE(status)) { NS_ASSERTION(!kidNextInFlow, "bad child flow list"); } else if (!kidNextInFlow) { // The page isn't complete and it doesn't have a next-in-flow, so // create a continuing page. nsIFrame* continuingPage = aPresContext->PresShell()->FrameConstructor()-> CreateContinuingFrame(aPresContext, kidFrame, this); // Add it to our child list mFrames.InsertFrame(nullptr, kidFrame, continuingPage); } } // Get Total Page Count // XXXdholbert technically we could calculate this in the loop above, // instead of needing a separate walk. int32_t pageTot = mFrames.GetLength(); // Set Page Number Info int32_t pageNum = 1; for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { MOZ_ASSERT(e.get()->GetType() == nsGkAtoms::pageFrame, "only expecting nsPageFrame children. Other children will make " "this static_cast bogus & probably violate other assumptions"); nsPageFrame* pf = static_cast<nsPageFrame*>(e.get()); pf->SetPageNumInfo(pageNum, pageTot); pageNum++; } // Create current Date/Time String if (!mDateFormatter) { mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID); } if (!mDateFormatter) { return; } nsAutoString formattedDateString; time_t ltime; time( <ime ); if (NS_SUCCEEDED(mDateFormatter->FormatTime(nullptr /* nsILocale* locale */, kDateFormatShort, kTimeFormatNoSeconds, ltime, formattedDateString))) { SetDateTimeStr(formattedDateString); } // Return our desired size // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the // correct size SetDesiredSize(aDesiredSize, aReflowState, maxXMost, y); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); // cache the size so we can set the desired size // for the other reflows that happen mSize.width = maxXMost; mSize.height = y; NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
void nsFieldSetFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_PRECONDITION(aReflowState.ComputedISize() != NS_INTRINSICSIZE, "Should have a precomputed inline-size!"); // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; nsOverflowAreas ocBounds; nsReflowStatus ocStatus = NS_FRAME_COMPLETE; if (GetPrevInFlow()) { ReflowOverflowContainerChildren(aPresContext, aReflowState, ocBounds, 0, ocStatus); } //------------ Handle Incremental Reflow ----------------- bool reflowInner; bool reflowLegend; nsIFrame* legend = GetLegend(); nsIFrame* inner = GetInner(); if (aReflowState.ShouldReflowAllKids()) { reflowInner = inner != nullptr; reflowLegend = legend != nullptr; } else { reflowInner = inner && NS_SUBTREE_DIRTY(inner); reflowLegend = legend && NS_SUBTREE_DIRTY(legend); } // We don't allow fieldsets to break vertically. If we did, we'd // need logic here to push and pull overflow frames. // Since we're not applying our padding in this frame, we need to add it here // to compute the available width for our children. WritingMode wm = GetWritingMode(); WritingMode innerWM = inner ? inner->GetWritingMode() : wm; WritingMode legendWM = legend ? legend->GetWritingMode() : wm; LogicalSize innerAvailSize = aReflowState.ComputedSizeWithPadding(innerWM); LogicalSize legendAvailSize = aReflowState.ComputedSizeWithPadding(legendWM); innerAvailSize.BSize(innerWM) = legendAvailSize.BSize(legendWM) = NS_UNCONSTRAINEDSIZE; NS_ASSERTION(!inner || nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, inner, nsLayoutUtils::MIN_ISIZE) <= innerAvailSize.ISize(innerWM), "Bogus availSize.ISize; should be bigger"); NS_ASSERTION(!legend || nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, legend, nsLayoutUtils::MIN_ISIZE) <= legendAvailSize.ISize(legendWM), "Bogus availSize.ISize; should be bigger"); // get our border and padding nsMargin border = aReflowState.ComputedPhysicalBorderPadding() - aReflowState.ComputedPhysicalPadding(); LogicalMargin logBorder(wm, border); // Figure out how big the legend is if there is one. // get the legend's margin LogicalMargin legendMargin(wm); // reflow the legend only if needed Maybe<nsHTMLReflowState> legendReflowState; if (legend) { legendReflowState.emplace(aPresContext, aReflowState, legend, legendAvailSize); } if (reflowLegend) { nsHTMLReflowMetrics legendDesiredSize(aReflowState); ReflowChild(legend, aPresContext, legendDesiredSize, *legendReflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); #ifdef NOISY_REFLOW printf(" returned (%d, %d)\n", legendDesiredSize.Width(), legendDesiredSize.Height()); #endif // figure out the legend's rectangle legendMargin = legend->GetLogicalUsedMargin(wm); mLegendRect = LogicalRect(wm, 0, 0, legendDesiredSize.ISize(wm) + legendMargin.IStartEnd(wm), legendDesiredSize.BSize(wm) + legendMargin.BStartEnd(wm)); nscoord oldSpace = mLegendSpace; mLegendSpace = 0; if (mLegendRect.BSize(wm) > logBorder.BStart(wm)) { // center the border on the legend mLegendSpace = mLegendRect.BSize(wm) - logBorder.BStart(wm); } else { mLegendRect.BStart(wm) = (logBorder.BStart(wm) - mLegendRect.BSize(wm)) / 2; } // if the legend space changes then we need to reflow the // content area as well. if (mLegendSpace != oldSpace && inner) { reflowInner = true; } // We'll move the legend to its proper place later. FinishReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState.ptr(), 0, 0, NS_FRAME_NO_MOVE_FRAME); } else if (!legend) { mLegendRect.SetEmpty(); mLegendSpace = 0; } else { // mLegendSpace and mLegendRect haven't changed, but we need // the used margin when placing the legend. legendMargin = legend->GetLogicalUsedMargin(wm); } // reflow the content frame only if needed if (reflowInner) { nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner, innerAvailSize, -1, -1, nsHTMLReflowState::CALLER_WILL_INIT); // Override computed padding, in case it's percentage padding kidReflowState.Init(aPresContext, -1, -1, nullptr, &aReflowState.ComputedPhysicalPadding()); // Our child is "height:100%" but we actually want its height to be reduced // by the amount of content-height the legend is eating up, unless our // height is unconstrained (in which case the child's will be too). if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) { kidReflowState.SetComputedHeight( std::max(0, aReflowState.ComputedHeight() - mLegendSpace)); } if (aReflowState.ComputedMinHeight() > 0) { kidReflowState.ComputedMinHeight() = std::max(0, aReflowState.ComputedMinHeight() - mLegendSpace); } if (aReflowState.ComputedMaxHeight() != NS_UNCONSTRAINEDSIZE) { kidReflowState.ComputedMaxHeight() = std::max(0, aReflowState.ComputedMaxHeight() - mLegendSpace); } nsHTMLReflowMetrics kidDesiredSize(kidReflowState, aDesiredSize.mFlags); // Reflow the frame NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0), "Margins on anonymous fieldset child not supported!"); nsPoint pt(border.left, border.top); if (wm.IsVerticalLR()) { pt.x += mLegendSpace; } else if (!wm.IsVertical()) { pt.y += mLegendSpace; } ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState, pt.x, pt.y, 0, aStatus); FinishReflowChild(inner, aPresContext, kidDesiredSize, &kidReflowState, pt.x, pt.y, 0); NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); } nscoord containerWidth = (wm.IsVertical() ? mLegendSpace : 0) + logBorder.LeftRight(wm) + (inner ? inner->GetSize().width : 0); LogicalRect contentRect(wm); if (inner) { // We don't support margins on inner, so our content rect is just the // inner's border-box. We don't care about container-width at this point, // as we'll figure out the actual positioning later. contentRect = inner->GetLogicalRect(wm, containerWidth); } // Our content rect must fill up the available width LogicalSize availSize = aReflowState.ComputedSizeWithPadding(wm); if (availSize.ISize(wm) > contentRect.ISize(wm)) { contentRect.ISize(wm) = innerAvailSize.ISize(wm); } if (legend) { // The legend is positioned inline-wards within the inner's content rect // (so that padding on the fieldset affects the legend position). LogicalRect innerContentRect = contentRect; innerContentRect.Deflate(wm, aReflowState.ComputedLogicalPadding()); // If the inner content rect is larger than the legend, we can align the // legend. if (innerContentRect.ISize(wm) > mLegendRect.ISize(wm)) { int32_t align = static_cast<nsLegendFrame*> (legend->GetContentInsertionFrame())->GetAlign(); if (!wm.IsBidiLTR()) { if (align == NS_STYLE_TEXT_ALIGN_LEFT || align == NS_STYLE_TEXT_ALIGN_MOZ_LEFT) { align = NS_STYLE_TEXT_ALIGN_END; } else if (align == NS_STYLE_TEXT_ALIGN_RIGHT || align == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT) { align = NS_STYLE_TEXT_ALIGN_DEFAULT; } } switch (align) { case NS_STYLE_TEXT_ALIGN_END: mLegendRect.IStart(wm) = innerContentRect.IEnd(wm) - mLegendRect.ISize(wm); break; case NS_STYLE_TEXT_ALIGN_CENTER: case NS_STYLE_TEXT_ALIGN_MOZ_CENTER: // Note: rounding removed; there doesn't seem to be any need mLegendRect.IStart(wm) = innerContentRect.IStart(wm) + (innerContentRect.ISize(wm) - mLegendRect.ISize(wm)) / 2; break; default: mLegendRect.IStart(wm) = innerContentRect.IStart(wm); break; } } else { // otherwise make place for the legend mLegendRect.IStart(wm) = innerContentRect.IStart(wm); innerContentRect.ISize(wm) = mLegendRect.ISize(wm); contentRect.ISize(wm) = mLegendRect.ISize(wm) + aReflowState.ComputedLogicalPadding().IStartEnd(wm); } // place the legend LogicalRect actualLegendRect = mLegendRect; actualLegendRect.Deflate(wm, legendMargin); LogicalPoint actualLegendPos(actualLegendRect.Origin(wm)); legendReflowState->ApplyRelativePositioning(&actualLegendPos, containerWidth); legend->SetPosition(wm, actualLegendPos, containerWidth); nsContainerFrame::PositionFrameView(legend); nsContainerFrame::PositionChildViews(legend); } // Return our size and our result. LogicalSize finalSize(wm, contentRect.ISize(wm) + logBorder.IStartEnd(wm), mLegendSpace + logBorder.BStartEnd(wm) + (inner ? inner->GetLogicalSize(wm).BSize(wm) : 0)); aDesiredSize.SetSize(wm, finalSize); aDesiredSize.SetOverflowAreasToDesiredBounds(); if (legend) { ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend); } if (inner) { ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner); } // Merge overflow container bounds and status. aDesiredSize.mOverflowAreas.UnionWith(ocBounds); NS_MergeReflowStatusInto(&aStatus, ocStatus); FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); InvalidateFrame(); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
void nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext, nsHTMLReflowMetrics& aButtonDesiredSize, const nsHTMLReflowState& aButtonReflowState, nsIFrame* aFirstKid) { WritingMode wm = GetWritingMode(); bool isVertical = wm.IsVertical(); LogicalSize availSize = aButtonReflowState.ComputedSize(wm); availSize.BSize(wm) = NS_INTRINSICSIZE; // Buttons have some bonus renderer-determined border/padding, // which occupies part of the button's content-box area: const LogicalMargin focusPadding = LogicalMargin(wm, mRenderer.GetAddedButtonBorderAndPadding()); // shorthand for a value we need to use in a bunch of places const LogicalMargin& clbp = aButtonReflowState.ComputedLogicalBorderPadding(); // Indent the child inside us by the focus border. We must do this separate // from the regular border. availSize.ISize(wm) -= focusPadding.IStartEnd(wm); // See whether out availSize's inline-size is big enough. If it's smaller than // our intrinsic min iSize, that means that the kid wouldn't really fit; for a // better look in such cases we adjust the available iSize and our inline-start // offset to allow the kid to spill start-wards into our padding. nscoord ioffset = focusPadding.IStart(wm) + clbp.IStart(wm); nscoord extraISize = GetMinISize(aButtonReflowState.rendContext) - aButtonReflowState.ComputedISize(); if (extraISize > 0) { nscoord extraIStart = extraISize / 2; nscoord extraIEnd = extraISize - extraIStart; NS_ASSERTION(extraIEnd >=0, "How'd that happen?"); // Do not allow the extras to be bigger than the relevant padding const LogicalMargin& padding = aButtonReflowState.ComputedLogicalPadding(); extraIStart = std::min(extraIStart, padding.IStart(wm)); extraIEnd = std::min(extraIEnd, padding.IEnd(wm)); ioffset -= extraIStart; availSize.ISize(wm) = availSize.ISize(wm) + extraIStart + extraIEnd; } availSize.ISize(wm) = std::max(availSize.ISize(wm), 0); // Give child a clone of the button's reflow state, with height/width reduced // by focusPadding, so that descendants with height:100% don't protrude. nsHTMLReflowState adjustedButtonReflowState = CloneReflowStateWithReducedContentBox(aButtonReflowState, focusPadding.GetPhysicalMargin(wm)); nsHTMLReflowState contentsReflowState(aPresContext, adjustedButtonReflowState, aFirstKid, availSize); nsReflowStatus contentsReflowStatus; nsHTMLReflowMetrics contentsDesiredSize(aButtonReflowState); nscoord boffset = focusPadding.BStart(wm) + clbp.BStart(wm); ReflowChild(aFirstKid, aPresContext, contentsDesiredSize, contentsReflowState, isVertical ? boffset : ioffset, isVertical ? ioffset : boffset, 0, contentsReflowStatus); MOZ_ASSERT(NS_FRAME_IS_COMPLETE(contentsReflowStatus), "We gave button-contents frame unconstrained available height, " "so it should be complete"); // Compute the button's content-box height: nscoord buttonContentBoxBSize = 0; if (aButtonReflowState.ComputedBSize() != NS_INTRINSICSIZE) { // Button has a fixed block-size -- that's its content-box bSize. buttonContentBoxBSize = aButtonReflowState.ComputedBSize(); } else { // Button is intrinsically sized -- it should shrinkwrap the // button-contents' bSize, plus any focus-padding space: buttonContentBoxBSize = contentsDesiredSize.BSize(wm) + focusPadding.BStartEnd(wm); // Make sure we obey min/max-bSize in the case when we're doing intrinsic // sizing (we get it for free when we have a non-intrinsic // aButtonReflowState.ComputedBSize()). Note that we do this before // adjusting for borderpadding, since mComputedMaxBSize and // mComputedMinBSize are content bSizes. buttonContentBoxBSize = NS_CSS_MINMAX(buttonContentBoxBSize, aButtonReflowState.ComputedMinBSize(), aButtonReflowState.ComputedMaxBSize()); } // Center child in the block-direction in the button // (technically, inside of the button's focus-padding area) nscoord extraSpace = buttonContentBoxBSize - focusPadding.BStartEnd(wm) - contentsDesiredSize.BSize(wm); boffset = std::max(0, extraSpace / 2); // Adjust boffset to be in terms of the button's frame-rect, instead of // its focus-padding rect: boffset += focusPadding.BStart(wm) + clbp.BStart(wm); // Place the child FinishReflowChild(aFirstKid, aPresContext, contentsDesiredSize, &contentsReflowState, isVertical ? boffset : ioffset, isVertical ? ioffset : boffset, 0); // Make sure we have a useful 'ascent' value for the child if (contentsDesiredSize.BlockStartAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) { WritingMode wm = aButtonReflowState.GetWritingMode(); contentsDesiredSize.SetBlockStartAscent(aFirstKid->GetLogicalBaseline(wm)); } // OK, we're done with the child frame. // Use what we learned to populate the button frame's reflow metrics. // * Button's height & width are content-box size + border-box contribution: aButtonDesiredSize.SetSize(wm, LogicalSize(wm, aButtonReflowState.ComputedISize() + clbp.IStartEnd(wm), buttonContentBoxBSize + clbp.BStartEnd(wm))); // * Button's ascent is its child's ascent, plus the child's block-offset // within our frame... unless it's orthogonal, in which case we'll use the // contents inline-size as an approximation for now. // XXX is there a better strategy? should we include border-padding? if (aButtonDesiredSize.GetWritingMode().IsOrthogonalTo(wm)) { aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.ISize(wm)); } else { aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.BlockStartAscent() + boffset); } aButtonDesiredSize.SetOverflowAreasToDesiredBounds(); }
void nsVideoFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsVideoFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsVideoFrame::Reflow: availSize=%d,%d", aReflowState.AvailableWidth(), aReflowState.AvailableHeight())); NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); aStatus = NS_FRAME_COMPLETE; aMetrics.Width() = aReflowState.ComputedWidth(); aMetrics.Height() = aReflowState.ComputedHeight(); // stash this away so we can compute our inner area later mBorderPadding = aReflowState.ComputedPhysicalBorderPadding(); aMetrics.Width() += mBorderPadding.left + mBorderPadding.right; aMetrics.Height() += mBorderPadding.top + mBorderPadding.bottom; // Reflow the child frames. We may have up to two, an image frame // which is the poster, and a box frame, which is the video controls. for (nsIFrame* child : mFrames) { if (child->GetContent() == mPosterImage) { // Reflow the poster frame. nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child); nsHTMLReflowMetrics kidDesiredSize(aReflowState); WritingMode wm = imageFrame->GetWritingMode(); LogicalSize availableSize = aReflowState.AvailableSize(wm); LogicalSize cbSize = aMetrics.Size(aMetrics.GetWritingMode()). ConvertTo(wm, aMetrics.GetWritingMode()); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, imageFrame, availableSize, &cbSize); nsRect posterRenderRect; if (ShouldDisplayPoster()) { posterRenderRect = nsRect(nsPoint(mBorderPadding.left, mBorderPadding.top), nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); } kidReflowState.SetComputedWidth(posterRenderRect.width); kidReflowState.SetComputedHeight(posterRenderRect.height); ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState, posterRenderRect.x, posterRenderRect.y, 0, aStatus); FinishReflowChild(imageFrame, aPresContext, kidDesiredSize, &kidReflowState, posterRenderRect.x, posterRenderRect.y, 0); } else if (child->GetContent() == mVideoControls) { // Reflow the video controls frame. nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext); nsSize size = child->GetSize(); nsBoxFrame::LayoutChildAt(boxState, child, nsRect(mBorderPadding.left, mBorderPadding.top, aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); if (child->GetSize() != size) { RefPtr<nsRunnable> event = new DispatchResizeToControls(child->GetContent()); nsContentUtils::AddScriptRunner(event); } } else if (child->GetContent() == mCaptionDiv) { // Reflow to caption div nsHTMLReflowMetrics kidDesiredSize(aReflowState); WritingMode wm = child->GetWritingMode(); LogicalSize availableSize = aReflowState.AvailableSize(wm); LogicalSize cbSize = aMetrics.Size(aMetrics.GetWritingMode()). ConvertTo(wm, aMetrics.GetWritingMode()); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, child, availableSize, &cbSize); nsSize size(aReflowState.ComputedWidth(), aReflowState.ComputedHeight()); size.width -= kidReflowState.ComputedPhysicalBorderPadding().LeftRight(); size.height -= kidReflowState.ComputedPhysicalBorderPadding().TopBottom(); kidReflowState.SetComputedWidth(std::max(size.width, 0)); kidReflowState.SetComputedHeight(std::max(size.height, 0)); ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState, mBorderPadding.left, mBorderPadding.top, 0, aStatus); FinishReflowChild(child, aPresContext, kidDesiredSize, &kidReflowState, mBorderPadding.left, mBorderPadding.top, 0); } } aMetrics.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aMetrics); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsVideoFrame::Reflow: size=%d,%d", aMetrics.Width(), aMetrics.Height())); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); }
void nsNumberControlFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsNumberControlFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_ASSERTION(mOuterWrapper, "Outer wrapper div must exist!"); NS_ASSERTION(!GetPrevContinuation() && !GetNextContinuation(), "nsNumberControlFrame should not have continuations; if it does we " "need to call RegUnregAccessKey only for the first"); NS_ASSERTION(!mFrames.FirstChild() || !mFrames.FirstChild()->GetNextSibling(), "We expect at most one direct child frame"); if (mState & NS_FRAME_FIRST_REFLOW) { nsFormControlFrame::RegUnRegAccessKey(this, true); } // The width of our content box, which is the available width // for our anonymous content: const nscoord contentBoxWidth = aReflowState.ComputedWidth(); nscoord contentBoxHeight = aReflowState.ComputedHeight(); nsIFrame* outerWrapperFrame = mOuterWrapper->GetPrimaryFrame(); if (!outerWrapperFrame) { // display:none? if (contentBoxHeight == NS_INTRINSICSIZE) { contentBoxHeight = 0; } } else { NS_ASSERTION(outerWrapperFrame == mFrames.FirstChild(), "huh?"); nsHTMLReflowMetrics wrappersDesiredSize(aReflowState); WritingMode wm = outerWrapperFrame->GetWritingMode(); LogicalSize availSize = aReflowState.ComputedSize(wm); availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE; nsHTMLReflowState wrapperReflowState(aPresContext, aReflowState, outerWrapperFrame, availSize); // offsets of wrapper frame nscoord xoffset = aReflowState.ComputedPhysicalBorderPadding().left + wrapperReflowState.ComputedPhysicalMargin().left; nscoord yoffset = aReflowState.ComputedPhysicalBorderPadding().top + wrapperReflowState.ComputedPhysicalMargin().top; nsReflowStatus childStatus; ReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize, wrapperReflowState, xoffset, yoffset, 0, childStatus); MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus), "We gave our child unconstrained height, so it should be complete"); nscoord wrappersMarginBoxHeight = wrappersDesiredSize.Height() + wrapperReflowState.ComputedPhysicalMargin().TopBottom(); if (contentBoxHeight == NS_INTRINSICSIZE) { // We are intrinsically sized -- we should shrinkwrap the outer wrapper's // height: contentBoxHeight = wrappersMarginBoxHeight; // Make sure we obey min/max-height in the case when we're doing intrinsic // sizing (we get it for free when we have a non-intrinsic // aReflowState.ComputedHeight()). Note that we do this before // adjusting for borderpadding, since mComputedMaxHeight and // mComputedMinHeight are content heights. contentBoxHeight = NS_CSS_MINMAX(contentBoxHeight, aReflowState.ComputedMinHeight(), aReflowState.ComputedMaxHeight()); } // Center child vertically nscoord extraSpace = contentBoxHeight - wrappersMarginBoxHeight; yoffset += std::max(0, extraSpace / 2); // Place the child FinishReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize, &wrapperReflowState, xoffset, yoffset, 0); aDesiredSize.SetBlockStartAscent( wrappersDesiredSize.BlockStartAscent() + outerWrapperFrame->BStart(aReflowState.GetWritingMode(), contentBoxWidth)); } aDesiredSize.Width() = contentBoxWidth + aReflowState.ComputedPhysicalBorderPadding().LeftRight(); aDesiredSize.Height() = contentBoxHeight + aReflowState.ComputedPhysicalBorderPadding().TopBottom(); aDesiredSize.SetOverflowAreasToDesiredBounds(); if (outerWrapperFrame) { ConsiderChildOverflow(aDesiredSize.mOverflowAreas, outerWrapperFrame); } FinishAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
NS_IMETHODIMP ViewportFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("ViewportFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow"); // Initialize OUT parameters aStatus = NS_FRAME_COMPLETE; // Because |Reflow| sets mComputedHeight on the child to // availableHeight. AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT); // Set our size up front, since some parts of reflow depend on it // being already set. Note that the computed height may be // unconstrained; that's ok. Consumers should watch out for that. SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); // Reflow the main content first so that the placeholders of the // fixed-position frames will be in the right places on an initial // reflow. nscoord kidHeight = 0; nsresult rv = NS_OK; if (mFrames.NotEmpty()) { // Deal with a non-incremental reflow or an incremental reflow // targeted at our one-and-only principal child frame. if (aReflowState.ShouldReflowAllKids() || aReflowState.mFlags.mVResize || NS_SUBTREE_DIRTY(mFrames.FirstChild())) { // Reflow our one-and-only principal child frame nsIFrame* kidFrame = mFrames.FirstChild(); nsHTMLReflowMetrics kidDesiredSize; nsSize availableSpace(aReflowState.availableWidth, aReflowState.availableHeight); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availableSpace); // Reflow the frame kidReflowState.SetComputedHeight(aReflowState.ComputedHeight()); rv = ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, 0, 0, 0, aStatus); kidHeight = kidDesiredSize.height; FinishReflowChild(kidFrame, aPresContext, nsnull, kidDesiredSize, 0, 0, 0); } else { kidHeight = mFrames.FirstChild()->GetSize().height; } } NS_ASSERTION(aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE, "shouldn't happen anymore"); // Return the max size as our desired size aDesiredSize.width = aReflowState.availableWidth; // Being flowed initially at an unconstrained height means we should // return our child's intrinsic size. aDesiredSize.height = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE ? aReflowState.ComputedHeight() : kidHeight; // Make a copy of the reflow state and change the computed width and height // to reflect the available space for the fixed items nsHTMLReflowState reflowState(aReflowState); nsPoint offset = AdjustReflowStateForScrollbars(&reflowState); #ifdef DEBUG NS_ASSERTION(mFixedContainer.GetChildList().IsEmpty() || (offset.x == 0 && offset.y == 0), "We don't handle correct positioning of fixed frames with " "scrollbars in odd positions"); #endif // Just reflow all the fixed-pos frames. rv = mFixedContainer.Reflow(this, aPresContext, reflowState, aStatus, reflowState.ComputedWidth(), reflowState.ComputedHeight(), PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized nsnull /* ignore overflow */); // If we were dirty then do a repaint if (GetStateBits() & NS_FRAME_IS_DIRTY) { nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height); Invalidate(damageRect); } // XXX Should we do something to clip our children to this? aDesiredSize.SetOverflowAreasToDesiredBounds(); NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return rv; }
void nsSubDocumentFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d", aReflowState.AvailableWidth(), aReflowState.AvailableHeight())); NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE, "Shouldn't have unconstrained stuff here " "thanks to the rules of reflow"); NS_ASSERTION(NS_INTRINSICSIZE != aReflowState.ComputedHeight(), "Shouldn't have unconstrained stuff here " "thanks to ComputeAutoSize"); aStatus = NS_FRAME_COMPLETE; NS_ASSERTION(mContent->GetPrimaryFrame() == this, "Shouldn't happen"); // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed> aDesiredSize.SetSize(aReflowState.GetWritingMode(), aReflowState.ComputedSizeWithBorderPadding()); // "offset" is the offset of our content area from our frame's // top-left corner. nsPoint offset = nsPoint(aReflowState.ComputedPhysicalBorderPadding().left, aReflowState.ComputedPhysicalBorderPadding().top); if (mInnerView) { const nsMargin& bp = aReflowState.ComputedPhysicalBorderPadding(); nsSize innerSize(aDesiredSize.Width() - bp.LeftRight(), aDesiredSize.Height() - bp.TopBottom()); // Size & position the view according to 'object-fit' & 'object-position'. nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame(); IntrinsicSize intrinsSize; nsSize intrinsRatio; if (subDocRoot) { intrinsSize = subDocRoot->GetIntrinsicSize(); intrinsRatio = subDocRoot->GetIntrinsicRatio(); } nsRect destRect = nsLayoutUtils::ComputeObjectDestRect(nsRect(offset, innerSize), intrinsSize, intrinsRatio, StylePosition()); nsViewManager* vm = mInnerView->GetViewManager(); vm->MoveViewTo(mInnerView, destRect.x, destRect.y); vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), destRect.Size()), true); } aDesiredSize.SetOverflowAreasToDesiredBounds(); if (!ShouldClipSubdocument()) { nsIFrame* subdocRootFrame = GetSubdocumentRootFrame(); if (subdocRootFrame) { aDesiredSize.mOverflowAreas.UnionWith(subdocRootFrame->GetOverflowAreas() + offset); } } FinishAndStoreOverflow(&aDesiredSize); if (!aPresContext->IsPaginated() && !mPostedReflowCallback) { PresContext()->PresShell()->PostReflowCallback(this); mPostedReflowCallback = true; } NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x", aDesiredSize.Width(), aDesiredSize.Height(), aStatus)); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
NS_IMETHODIMP nsVideoFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsVideoFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsVideoFrame::Reflow: availSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); aStatus = NS_FRAME_COMPLETE; aMetrics.width = aReflowState.ComputedWidth(); aMetrics.height = aReflowState.ComputedHeight(); // stash this away so we can compute our inner area later mBorderPadding = aReflowState.mComputedBorderPadding; aMetrics.width += mBorderPadding.left + mBorderPadding.right; aMetrics.height += mBorderPadding.top + mBorderPadding.bottom; // Reflow the child frames. We may have up to two, an image frame // which is the poster, and a box frame, which is the video controls. for (nsIFrame *child = mFrames.FirstChild(); child; child = child->GetNextSibling()) { if (child->GetType() == nsGkAtoms::imageFrame) { // Reflow the poster frame. nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child); nsHTMLReflowMetrics kidDesiredSize; nsSize availableSize = nsSize(aReflowState.availableWidth, aReflowState.availableHeight); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, imageFrame, availableSize, aMetrics.width, aMetrics.height); if (ShouldDisplayPoster()) { kidReflowState.SetComputedWidth(aReflowState.ComputedWidth()); kidReflowState.SetComputedHeight(aReflowState.ComputedHeight()); } else { kidReflowState.SetComputedWidth(0); kidReflowState.SetComputedHeight(0); } ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState, mBorderPadding.left, mBorderPadding.top, 0, aStatus); FinishReflowChild(imageFrame, aPresContext, &kidReflowState, kidDesiredSize, mBorderPadding.left, mBorderPadding.top, 0); } else if (child->GetType() == nsGkAtoms::boxFrame) { // Reflow the video controls frame. nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext); nsBoxFrame::LayoutChildAt(boxState, child, nsRect(mBorderPadding.left, mBorderPadding.top, aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); } } aMetrics.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aMetrics); if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) { Invalidate(nsRect(0, 0, mRect.width, mRect.height)); } NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsVideoFrame::Reflow: size=%d,%d", aMetrics.width, aMetrics.height)); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); return NS_OK; }
void nsSVGOuterSVGFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsSVGOuterSVGFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsSVGOuterSVGFrame::Reflow: availSize=%d,%d", aReflowState.AvailableWidth(), aReflowState.AvailableHeight())); NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); aStatus = NS_FRAME_COMPLETE; aDesiredSize.Width() = aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalBorderPadding().LeftRight(); aDesiredSize.Height() = aReflowState.ComputedHeight() + aReflowState.ComputedPhysicalBorderPadding().TopBottom(); NS_ASSERTION(!GetPrevInFlow(), "SVG can't currently be broken across pages."); SVGSVGElement *svgElem = static_cast<SVGSVGElement*>(mContent); nsSVGOuterSVGAnonChildFrame *anonKid = static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild()); if (mState & NS_FRAME_FIRST_REFLOW) { // Initialize svgElem->UpdateHasChildrenOnlyTransform(); } // If our SVG viewport has changed, update our content and notify. // http://www.w3.org/TR/SVG11/coords.html#ViewportSpace svgFloatSize newViewportSize( nsPresContext::AppUnitsToFloatCSSPixels(aReflowState.ComputedWidth()), nsPresContext::AppUnitsToFloatCSSPixels(aReflowState.ComputedHeight())); svgFloatSize oldViewportSize = svgElem->GetViewportSize(); uint32_t changeBits = 0; if (newViewportSize != oldViewportSize) { // When our viewport size changes, we may need to update the overflow rects // of our child frames. This is the case if: // // * We have a real/synthetic viewBox (a children-only transform), since // the viewBox transform will change as the viewport dimensions change. // // * We do not have a real/synthetic viewBox, but the last time we // reflowed (or the last time UpdateOverflow() was called) we did. // // We only handle the former case here, in which case we mark all our child // frames as dirty so that we reflow them below and update their overflow // rects. // // In the latter case, updating of overflow rects is handled for removal of // real viewBox (the viewBox attribute) in AttributeChanged. Synthetic // viewBox "removal" (e.g. a document references the same SVG via both an // <svg:image> and then as a CSS background image (a synthetic viewBox is // used when painting the former, but not when painting the latter)) is // handled in SVGSVGElement::FlushImageTransformInvalidation. // if (svgElem->HasViewBoxOrSyntheticViewBox()) { nsIFrame* anonChild = GetFirstPrincipalChild(); anonChild->AddStateBits(NS_FRAME_IS_DIRTY); for (nsIFrame* child = anonChild->GetFirstPrincipalChild(); child; child = child->GetNextSibling()) { child->AddStateBits(NS_FRAME_IS_DIRTY); } } changeBits |= COORD_CONTEXT_CHANGED; svgElem->SetViewportSize(newViewportSize); } if (mFullZoom != PresContext()->GetFullZoom()) { changeBits |= FULL_ZOOM_CHANGED; mFullZoom = PresContext()->GetFullZoom(); } if (changeBits) { NotifyViewportOrTransformChanged(changeBits); } mViewportInitialized = true; // Now that we've marked the necessary children as dirty, call // ReflowSVG() or ReflowSVGNonDisplayText() on them, depending // on whether we are non-display. mCallingReflowSVG = true; if (GetStateBits() & NS_FRAME_IS_NONDISPLAY) { ReflowSVGNonDisplayText(this); } else { // Update the mRects and visual overflow rects of all our descendants, // including our anonymous wrapper kid: anonKid->AddStateBits(mState & NS_FRAME_IS_DIRTY); anonKid->ReflowSVG(); NS_ABORT_IF_FALSE(!anonKid->GetNextSibling(), "We should have one anonymous child frame wrapping our real children"); } mCallingReflowSVG = false; // Set our anonymous kid's offset from our border box: anonKid->SetPosition(GetContentRectRelativeToSelf().TopLeft()); // Including our size in our overflow rects regardless of the value of // 'background', 'border', etc. makes sure that we usually (when we clip to // our content area) don't have to keep changing our overflow rects as our // descendants move about (see perf comment below). Including our size in our // scrollable overflow rect also makes sure that we scroll if we're too big // for our viewport. // // <svg> never allows scrolling to anything outside its mRect (only panning), // so we must always keep our scrollable overflow set to our size. // // With regards to visual overflow, we always clip root-<svg> (see our // BuildDisplayList method) regardless of the value of the 'overflow' // property since that is per-spec, even for the initial 'visible' value. For // that reason there's no point in adding descendant visual overflow to our // own when this frame is for a root-<svg>. That said, there's also a very // good performance reason for us wanting to avoid doing so. If we did, then // the frame's overflow would often change as descendants that are partially // or fully outside its rect moved (think animation on/off screen), and that // would cause us to do a full NS_FRAME_IS_DIRTY reflow and repaint of the // entire document tree each such move (see bug 875175). // // So it's only non-root outer-<svg> that has the visual overflow of its // descendants added to its own. (Note that the default user-agent style // sheet makes 'hidden' the default value for :not(root(svg)), so usually // FinishAndStoreOverflow will still clip this back to the frame's rect.) // // WARNING!! Keep UpdateBounds below in sync with whatever we do for our // overflow rects here! (Again, see bug 875175.) // aDesiredSize.SetOverflowAreasToDesiredBounds(); if (!mIsRootContent) { aDesiredSize.mOverflowAreas.VisualOverflow().UnionRect( aDesiredSize.mOverflowAreas.VisualOverflow(), anonKid->GetVisualOverflowRect() + anonKid->GetPosition()); } FinishAndStoreOverflow(&aDesiredSize); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsSVGOuterSVGFrame::Reflow: size=%d,%d", aDesiredSize.Width(), aDesiredSize.Height())); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
void nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext, nsHTMLReflowMetrics& aButtonDesiredSize, const nsHTMLReflowState& aButtonReflowState, nsIFrame* aFirstKid) { // Buttons have some bonus renderer-determined border/padding, // which occupies part of the button's content-box area: const nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding(); nsSize availSize(aButtonReflowState.ComputedWidth(), NS_INTRINSICSIZE); // Indent the child inside us by the focus border. We must do this separate // from the regular border. availSize.width -= focusPadding.LeftRight(); // See whether out availSize's width is big enough. If it's smaller than our // intrinsic min width, that means that the kid wouldn't really fit; for a // better look in such cases we adjust the available width and our left // offset to allow the kid to spill left into our padding. nscoord xoffset = focusPadding.left + aButtonReflowState.ComputedPhysicalBorderPadding().left; nscoord extrawidth = GetMinWidth(aButtonReflowState.rendContext) - aButtonReflowState.ComputedWidth(); if (extrawidth > 0) { nscoord extraleft = extrawidth / 2; nscoord extraright = extrawidth - extraleft; NS_ASSERTION(extraright >=0, "How'd that happen?"); // Do not allow the extras to be bigger than the relevant padding extraleft = std::min(extraleft, aButtonReflowState.ComputedPhysicalPadding().left); extraright = std::min(extraright, aButtonReflowState.ComputedPhysicalPadding().right); xoffset -= extraleft; availSize.width += extraleft + extraright; } availSize.width = std::max(availSize.width,0); // Give child a clone of the button's reflow state, with height/width reduced // by focusPadding, so that descendants with height:100% don't protrude. nsHTMLReflowState adjustedButtonReflowState = CloneReflowStateWithReducedContentBox(aButtonReflowState, focusPadding); nsHTMLReflowState contentsReflowState(aPresContext, adjustedButtonReflowState, aFirstKid, availSize); nsReflowStatus contentsReflowStatus; nsHTMLReflowMetrics contentsDesiredSize(aButtonReflowState.GetWritingMode()); ReflowChild(aFirstKid, aPresContext, contentsDesiredSize, contentsReflowState, xoffset, focusPadding.top + aButtonReflowState.ComputedPhysicalBorderPadding().top, 0, contentsReflowStatus); MOZ_ASSERT(NS_FRAME_IS_COMPLETE(contentsReflowStatus), "We gave button-contents frame unconstrained available height, " "so it should be complete"); // Compute the button's content-box height: nscoord buttonContentBoxHeight = 0; if (aButtonReflowState.ComputedHeight() != NS_INTRINSICSIZE) { // Button has a fixed height -- that's its content-box height. buttonContentBoxHeight = aButtonReflowState.ComputedHeight(); } else { // Button is intrinsically sized -- it should shrinkwrap the // button-contents' height, plus any focus-padding space: buttonContentBoxHeight = contentsDesiredSize.Height() + focusPadding.TopBottom(); // Make sure we obey min/max-height in the case when we're doing intrinsic // sizing (we get it for free when we have a non-intrinsic // aButtonReflowState.ComputedHeight()). Note that we do this before // adjusting for borderpadding, since mComputedMaxHeight and // mComputedMinHeight are content heights. buttonContentBoxHeight = NS_CSS_MINMAX(buttonContentBoxHeight, aButtonReflowState.ComputedMinHeight(), aButtonReflowState.ComputedMaxHeight()); } // Center child vertically in the button // (technically, inside of the button's focus-padding area) nscoord extraSpace = buttonContentBoxHeight - focusPadding.TopBottom() - contentsDesiredSize.Height(); nscoord yoffset = std::max(0, extraSpace / 2); // Adjust yoffset to be in terms of the button's frame-rect, instead of // its focus-padding rect: yoffset += focusPadding.top + aButtonReflowState.ComputedPhysicalBorderPadding().top; // Place the child FinishReflowChild(aFirstKid, aPresContext, contentsDesiredSize, &contentsReflowState, xoffset, yoffset, 0); // Make sure we have a useful 'ascent' value for the child if (contentsDesiredSize.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) { contentsDesiredSize.SetTopAscent(aFirstKid->GetBaseline()); } // OK, we're done with the child frame. // Use what we learned to populate the button frame's reflow metrics. // * Button's height & width are content-box size + border-box contribution: aButtonDesiredSize.Width() = aButtonReflowState.ComputedWidth() + aButtonReflowState.ComputedPhysicalBorderPadding().LeftRight(); aButtonDesiredSize.Height() = buttonContentBoxHeight + aButtonReflowState.ComputedPhysicalBorderPadding().TopBottom(); // * Button's ascent is its child's ascent, plus the child's y-offset // within our frame: aButtonDesiredSize.SetTopAscent(contentsDesiredSize.TopAscent() + yoffset); aButtonDesiredSize.SetOverflowAreasToDesiredBounds(); }
NS_IMETHODIMP nsCanvasFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow"); // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*> (GetPrevInFlow()); if (prevCanvasFrame) { AutoFrameListPtr overflow(aPresContext, prevCanvasFrame->StealOverflowFrames()); if (overflow) { NS_ASSERTION(overflow->OnlyChild(), "must have doc root as canvas frame's only child"); nsContainerFrame::ReparentFrameViewList(*overflow, prevCanvasFrame, this); // Prepend overflow to the our child list. There may already be // children placeholders for fixed-pos elements, which don't get // reflowed but must not be lost until the canvas frame is destroyed. mFrames.InsertFrames(this, nullptr, *overflow); } } // Set our size up front, since some parts of reflow depend on it // being already set. Note that the computed height may be // unconstrained; that's ok. Consumers should watch out for that. SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); // Reflow our one and only normal child frame. It's either the root // element's frame or a placeholder for that frame, if the root element // is abs-pos or fixed-pos. We may have additional children which // are placeholders for continuations of fixed-pos content, but those // don't need to be reflowed. The normal child is always comes before // the fixed-pos placeholders, because we insert it at the start // of the child list, above. nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode()); if (mFrames.IsEmpty()) { // We have no child frame, so return an empty size aDesiredSize.Width() = aDesiredSize.Height() = 0; } else { nsIFrame* kidFrame = mFrames.FirstChild(); bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0; nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, nsSize(aReflowState.AvailableWidth(), aReflowState.AvailableHeight())); if (aReflowState.mFlags.mVResize && (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) { // Tell our kid it's being vertically resized too. Bit of a // hack for framesets. kidReflowState.mFlags.mVResize = true; } nsPoint kidPt(kidReflowState.ComputedPhysicalMargin().left, kidReflowState.ComputedPhysicalMargin().top); kidReflowState.ApplyRelativePositioning(&kidPt); // Reflow the frame ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, kidPt.x, kidPt.y, 0, aStatus); // Complete the reflow and position and size the child frame FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowState, kidPt.x, kidPt.y, 0); if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) { nsIFrame* nextFrame = kidFrame->GetNextInFlow(); NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW, "If it's incomplete and has no nif yet, it must flag a nif reflow."); if (!nextFrame) { nextFrame = aPresContext->PresShell()->FrameConstructor()-> CreateContinuingFrame(aPresContext, kidFrame, this); SetOverflowFrames(nsFrameList(nextFrame, nextFrame)); // Root overflow containers will be normal children of // the canvas frame, but that's ok because there // aren't any other frames we need to isolate them from // during reflow. } if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) { nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER); } } // If the child frame was just inserted, then we're responsible for making sure // it repaints if (kidDirty) { // But we have a new child, which will affect our background, so // invalidate our whole rect. // Note: Even though we request to be sized to our child's size, our // scroll frame ensures that we are always the size of the viewport. // Also note: GetPosition() on a CanvasFrame is always going to return // (0, 0). We only want to invalidate GetRect() since Get*OverflowRect() // could also include overflow to our top and left (out of the viewport) // which doesn't need to be painted. nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame(); viewport->InvalidateFrame(); } // Return our desired size. Normally it's what we're told, but // sometimes we can be given an unconstrained height (when a window // is sizing-to-content), and we should compute our desired height. aDesiredSize.Width() = aReflowState.ComputedWidth(); if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) { aDesiredSize.Height() = kidFrame->GetRect().height + kidReflowState.ComputedPhysicalMargin().TopBottom(); } else { aDesiredSize.Height() = aReflowState.ComputedHeight(); } aDesiredSize.SetOverflowAreasToDesiredBounds(); aDesiredSize.mOverflowAreas.UnionWith( kidDesiredSize.mOverflowAreas + kidPt); } if (prevCanvasFrame) { ReflowOverflowContainerChildren(aPresContext, aReflowState, aDesiredSize.mOverflowAreas, 0, aStatus); } FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
NS_IMETHODIMP nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(), "A Page Sequence is only for real pages"); DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); aStatus = NS_FRAME_COMPLETE; // we're always complete // Don't do incremental reflow until we've taught tables how to do // it right in paginated mode. if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { // Return our desired size SetDesiredSize(aDesiredSize, aReflowState, mSize.width, mSize.height); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); return NS_OK; } // See if we can get a Print Settings from the Context if (!mPageData->mPrintSettings && aPresContext->Medium() == nsGkAtoms::print) { mPageData->mPrintSettings = aPresContext->GetPrintSettings(); } // now get out margins & edges if (mPageData->mPrintSettings) { nsIntMargin unwriteableTwips; mPageData->mPrintSettings->GetUnwriteableMarginInTwips(unwriteableTwips); NS_ASSERTION(unwriteableTwips.left >= 0 && unwriteableTwips.top >= 0 && unwriteableTwips.right >= 0 && unwriteableTwips.bottom >= 0, "Unwriteable twips should be non-negative"); nsIntMargin marginTwips; mPageData->mPrintSettings->GetMarginInTwips(marginTwips); mMargin = aPresContext->CSSTwipsToAppUnits(marginTwips + unwriteableTwips); int16_t printType; mPageData->mPrintSettings->GetPrintRange(&printType); mPrintRangeType = printType; nsIntMargin edgeTwips; mPageData->mPrintSettings->GetEdgeInTwips(edgeTwips); // sanity check the values. three inches are sometimes needed int32_t inchInTwips = NS_INCHES_TO_INT_TWIPS(3.0); edgeTwips.top = clamped(edgeTwips.top, 0, inchInTwips); edgeTwips.bottom = clamped(edgeTwips.bottom, 0, inchInTwips); edgeTwips.left = clamped(edgeTwips.left, 0, inchInTwips); edgeTwips.right = clamped(edgeTwips.right, 0, inchInTwips); mPageData->mEdgePaperMargin = aPresContext->CSSTwipsToAppUnits(edgeTwips + unwriteableTwips); } // *** Special Override *** // If this is a sub-sdoc (meaning it doesn't take the whole page) // and if this Document is in the upper left hand corner // we need to suppress the top margin or it will reflow too small nsSize pageSize = aPresContext->GetPageSize(); mPageData->mReflowSize = pageSize; // If we're printing a selection, we need to reflow with // unconstrained height, to make sure we'll get to the selection // even if it's beyond the first page of content. if (nsIPrintSettings::kRangeSelection == mPrintRangeType) { mPageData->mReflowSize.height = NS_UNCONSTRAINEDSIZE; } mPageData->mReflowMargin = mMargin; // Compute the size of each page and the x coordinate that each page will // be placed at nscoord extraThreshold = NS_MAX(pageSize.width, pageSize.height)/10; int32_t gapInTwips = Preferences::GetInt("print.print_extra_margin"); gapInTwips = NS_MAX(0, gapInTwips); nscoord extraGap = aPresContext->CSSTwipsToAppUnits(gapInTwips); extraGap = NS_MIN(extraGap, extraThreshold); // clamp to 1/10 of the largest dim of the page nsMargin extraMargin(0,0,0,0); if (aPresContext->IsScreen()) { extraMargin.SizeTo(extraGap, extraGap, extraGap, extraGap); } mPageData->mExtraMargin = extraMargin; // We use the CSS "margin" property on the -moz-page pseudoelement // to determine the space between each page in print preview. // Keep a running y-offset for each page. nscoord y = 0; nscoord maxXMost = 0; nsSize availSize(pageSize.width + extraMargin.LeftRight(), pageSize.height + extraMargin.TopBottom()); // Tile the pages vertically nsHTMLReflowMetrics kidSize; for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) { // Set the shared data into the page frame before reflow nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame); pf->SetSharedPageData(mPageData); // Reflow the page nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize); nsReflowStatus status; kidReflowState.SetComputedWidth(kidReflowState.availableWidth); //kidReflowState.SetComputedHeight(kidReflowState.availableHeight); PR_PL(("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight)); nsMargin pageCSSMargin = kidReflowState.mComputedMargin; y += pageCSSMargin.top; const nscoord x = pageCSSMargin.left; // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); FinishReflowChild(kidFrame, aPresContext, nullptr, kidSize, x, y, 0); y += kidSize.height; y += pageCSSMargin.bottom; maxXMost = NS_MAX(maxXMost, x + kidSize.width + pageCSSMargin.right); // Is the page complete? nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow(); if (NS_FRAME_IS_FULLY_COMPLETE(status)) { NS_ASSERTION(!kidNextInFlow, "bad child flow list"); } else if (!kidNextInFlow) { // The page isn't complete and it doesn't have a next-in-flow, so // create a continuing page. nsIFrame* continuingPage; nsresult rv = aPresContext->PresShell()->FrameConstructor()-> CreateContinuingFrame(aPresContext, kidFrame, this, &continuingPage); if (NS_FAILED(rv)) { break; } // Add it to our child list mFrames.InsertFrame(nullptr, kidFrame, continuingPage); } // Get the next page kidFrame = kidFrame->GetNextSibling(); } // Get Total Page Count nsIFrame* page; int32_t pageTot = 0; for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) { pageTot++; } // Set Page Number Info int32_t pageNum = 1; for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) { nsPageFrame * pf = static_cast<nsPageFrame*>(page); if (pf != nullptr) { pf->SetPageNumInfo(pageNum, pageTot); } pageNum++; } // Create current Date/Time String if (!mDateFormatter) mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID); NS_ENSURE_TRUE(mDateFormatter, NS_ERROR_FAILURE); nsAutoString formattedDateString; time_t ltime; time( <ime ); if (NS_SUCCEEDED(mDateFormatter->FormatTime(nullptr /* nsILocale* locale */, kDateFormatShort, kTimeFormatNoSeconds, ltime, formattedDateString))) { PRUnichar * uStr = ToNewUnicode(formattedDateString); SetDateTimeStr(uStr); // memory will be freed } // Return our desired size // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the // correct size SetDesiredSize(aDesiredSize, aReflowState, maxXMost, y); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); // cache the size so we can set the desired size // for the other reflows that happen mSize.width = maxXMost; mSize.height = y; NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsPageFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); aStatus = NS_FRAME_COMPLETE; // initialize out parameter NS_ASSERTION(mFrames.FirstChild() && nsGkAtoms::pageContentFrame == mFrames.FirstChild()->GetType(), "pageFrame must have a pageContentFrame child"); // Resize our frame allowing it only to be as big as we are // XXX Pay attention to the page's border and padding... if (mFrames.NotEmpty()) { nsIFrame* frame = mFrames.FirstChild(); // When the reflow size is NS_UNCONSTRAINEDSIZE it means we are reflowing // a single page to print selection. So this means we want to use // NS_UNCONSTRAINEDSIZE without altering it nscoord avHeight; if (mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) { avHeight = NS_UNCONSTRAINEDSIZE; } else { avHeight = mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom(); } nsSize maxSize(mPD->mReflowSize.width - mPD->mReflowMargin.LeftRight(), avHeight); float scale = aPresContext->GetPageScale(); maxSize.width = NSToCoordCeil(maxSize.width / scale); if (maxSize.height != NS_UNCONSTRAINEDSIZE) { maxSize.height = NSToCoordCeil(maxSize.height / scale); } // Get the number of Twips per pixel from the PresContext nscoord onePixelInTwips = nsPresContext::CSSPixelsToAppUnits(1); // insurance against infinite reflow, when reflowing less than a pixel // XXX Shouldn't we do something more friendly when invalid margins // are set? if (maxSize.width < onePixelInTwips || maxSize.height < onePixelInTwips) { aDesiredSize.width = 0; aDesiredSize.height = 0; NS_WARNING("Reflow aborted; no space for content"); return NS_OK; } nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize); kidReflowState.mFlags.mIsTopOfPage = true; kidReflowState.mFlags.mTableIsSplittable = true; // calc location of frame nscoord xc = mPD->mReflowMargin.left + mPD->mExtraMargin.left; nscoord yc = mPD->mReflowMargin.top + mPD->mExtraMargin.top; // Get the child's desired size ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus); // Place and size the child FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, xc, yc, 0); NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus) || !frame->GetNextInFlow(), "bad child flow list"); } PR_PL(("PageFrame::Reflow %p ", this)); PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.width, aDesiredSize.height, aReflowState.availableWidth, aReflowState.availableHeight)); // Return our desired size aDesiredSize.width = aReflowState.availableWidth; if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { aDesiredSize.height = aReflowState.availableHeight; } aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); PR_PL(("PageFrame::Reflow %p ", this)); PR_PL(("[%d,%d]\n", aReflowState.availableWidth, aReflowState.availableHeight)); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }