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