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