|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 #include "nsPageContentFrame.h" |
|
6 #include "nsCSSFrameConstructor.h" |
|
7 #include "nsPresContext.h" |
|
8 #include "nsGkAtoms.h" |
|
9 #include "nsIPresShell.h" |
|
10 #include "nsSimplePageSequenceFrame.h" |
|
11 |
|
12 nsIFrame* |
|
13 NS_NewPageContentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) |
|
14 { |
|
15 return new (aPresShell) nsPageContentFrame(aContext); |
|
16 } |
|
17 |
|
18 NS_IMPL_FRAMEARENA_HELPERS(nsPageContentFrame) |
|
19 |
|
20 nsresult |
|
21 nsPageContentFrame::Reflow(nsPresContext* aPresContext, |
|
22 nsHTMLReflowMetrics& aDesiredSize, |
|
23 const nsHTMLReflowState& aReflowState, |
|
24 nsReflowStatus& aStatus) |
|
25 { |
|
26 DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame"); |
|
27 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); |
|
28 aStatus = NS_FRAME_COMPLETE; // initialize out parameter |
|
29 nsresult rv = NS_OK; |
|
30 |
|
31 if (GetPrevInFlow() && (GetStateBits() & NS_FRAME_FIRST_REFLOW)) { |
|
32 nsresult rv = aPresContext->PresShell()->FrameConstructor() |
|
33 ->ReplicateFixedFrames(this); |
|
34 NS_ENSURE_SUCCESS(rv, rv); |
|
35 } |
|
36 |
|
37 // Set our size up front, since some parts of reflow depend on it |
|
38 // being already set. Note that the computed height may be |
|
39 // unconstrained; that's ok. Consumers should watch out for that. |
|
40 nsSize maxSize(aReflowState.ComputedWidth(), |
|
41 aReflowState.ComputedHeight()); |
|
42 SetSize(maxSize); |
|
43 |
|
44 // A PageContentFrame must always have one child: the canvas frame. |
|
45 // Resize our frame allowing it only to be as big as we are |
|
46 // XXX Pay attention to the page's border and padding... |
|
47 if (mFrames.NotEmpty()) { |
|
48 nsIFrame* frame = mFrames.FirstChild(); |
|
49 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize); |
|
50 kidReflowState.SetComputedHeight(maxSize.height); |
|
51 |
|
52 // Reflow the page content area |
|
53 rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); |
|
54 NS_ENSURE_SUCCESS(rv, rv); |
|
55 |
|
56 // The document element's background should cover the entire canvas, so |
|
57 // take into account the combined area and any space taken up by |
|
58 // absolutely positioned elements |
|
59 nsMargin padding(0,0,0,0); |
|
60 |
|
61 // XXXbz this screws up percentage padding (sets padding to zero |
|
62 // in the percentage padding case) |
|
63 kidReflowState.mStylePadding->GetPadding(padding); |
|
64 |
|
65 // This is for shrink-to-fit, and therefore we want to use the |
|
66 // scrollable overflow, since the purpose of shrink to fit is to |
|
67 // make the content that ought to be reachable (represented by the |
|
68 // scrollable overflow) fit in the page. |
|
69 if (frame->HasOverflowAreas()) { |
|
70 // The background covers the content area and padding area, so check |
|
71 // for children sticking outside the child frame's padding edge |
|
72 nscoord xmost = aDesiredSize.ScrollableOverflow().XMost(); |
|
73 if (xmost > aDesiredSize.Width()) { |
|
74 nscoord widthToFit = xmost + padding.right + |
|
75 kidReflowState.mStyleBorder->GetComputedBorderWidth(NS_SIDE_RIGHT); |
|
76 float ratio = float(maxSize.width) / widthToFit; |
|
77 NS_ASSERTION(ratio >= 0.0 && ratio < 1.0, "invalid shrink-to-fit ratio"); |
|
78 mPD->mShrinkToFitRatio = std::min(mPD->mShrinkToFitRatio, ratio); |
|
79 } |
|
80 } |
|
81 |
|
82 // Place and size the child |
|
83 FinishReflowChild(frame, aPresContext, aDesiredSize, &kidReflowState, 0, 0, 0); |
|
84 |
|
85 NS_ASSERTION(aPresContext->IsDynamic() || !NS_FRAME_IS_FULLY_COMPLETE(aStatus) || |
|
86 !frame->GetNextInFlow(), "bad child flow list"); |
|
87 } |
|
88 |
|
89 // Reflow our fixed frames |
|
90 nsReflowStatus fixedStatus = NS_FRAME_COMPLETE; |
|
91 ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, fixedStatus); |
|
92 NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete"); |
|
93 |
|
94 // Return our desired size |
|
95 aDesiredSize.Width() = aReflowState.ComputedWidth(); |
|
96 if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) { |
|
97 aDesiredSize.Height() = aReflowState.ComputedHeight(); |
|
98 } |
|
99 |
|
100 FinishAndStoreOverflow(&aDesiredSize); |
|
101 |
|
102 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); |
|
103 return NS_OK; |
|
104 } |
|
105 |
|
106 nsIAtom* |
|
107 nsPageContentFrame::GetType() const |
|
108 { |
|
109 return nsGkAtoms::pageContentFrame; |
|
110 } |
|
111 |
|
112 #ifdef DEBUG_FRAME_DUMP |
|
113 nsresult |
|
114 nsPageContentFrame::GetFrameName(nsAString& aResult) const |
|
115 { |
|
116 return MakeFrameName(NS_LITERAL_STRING("PageContent"), aResult); |
|
117 } |
|
118 #endif |