Line data Source code
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 :
6 : #ifndef nsColumnSetFrame_h___
7 : #define nsColumnSetFrame_h___
8 :
9 : /* rendering object for css3 multi-column layout */
10 :
11 : #include "mozilla/Attributes.h"
12 : #include "nsContainerFrame.h"
13 : #include "nsIFrameInlines.h" // for methods used by IS_TRUE_OVERFLOW_CONTAINER
14 :
15 : /**
16 : * nsColumnSetFrame implements CSS multi-column layout.
17 : * @note nsColumnSetFrame keeps true overflow containers in the normal flow
18 : * child lists (i.e. the principal and overflow lists).
19 : */
20 0 : class nsColumnSetFrame final : public nsContainerFrame
21 : {
22 : public:
23 0 : NS_DECL_FRAMEARENA_HELPERS(nsColumnSetFrame)
24 :
25 : explicit nsColumnSetFrame(nsStyleContext* aContext);
26 :
27 : virtual void Reflow(nsPresContext* aPresContext,
28 : ReflowOutput& aDesiredSize,
29 : const ReflowInput& aReflowInput,
30 : nsReflowStatus& aStatus) override;
31 :
32 : #ifdef DEBUG
33 : virtual void SetInitialChildList(ChildListID aListID,
34 : nsFrameList& aChildList) override;
35 : virtual void AppendFrames(ChildListID aListID,
36 : nsFrameList& aFrameList) override;
37 : virtual void InsertFrames(ChildListID aListID,
38 : nsIFrame* aPrevFrame,
39 : nsFrameList& aFrameList) override;
40 : virtual void RemoveFrame(ChildListID aListID,
41 : nsIFrame* aOldFrame) override;
42 : #endif
43 :
44 : virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
45 : virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
46 :
47 : /**
48 : * Retrieve the available height for content of this frame. The available content
49 : * height is the available height for the frame, minus borders and padding.
50 : */
51 : virtual nscoord GetAvailableContentBSize(const ReflowInput& aReflowInput);
52 :
53 0 : virtual nsContainerFrame* GetContentInsertionFrame() override {
54 0 : nsIFrame* frame = PrincipalChildList().FirstChild();
55 :
56 : // if no children return nullptr
57 0 : if (!frame)
58 0 : return nullptr;
59 :
60 0 : return frame->GetContentInsertionFrame();
61 : }
62 :
63 0 : virtual bool IsFrameOfType(uint32_t aFlags) const override
64 : {
65 0 : return nsContainerFrame::IsFrameOfType(aFlags &
66 0 : ~(nsIFrame::eCanContainOverflowContainers));
67 : }
68 :
69 : virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
70 : const nsRect& aDirtyRect,
71 : const nsDisplayListSet& aLists) override;
72 :
73 : /**
74 : * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not
75 : * handled by our prev-in-flow, and any columns sitting on our own
76 : * overflow list, and put them in our primary child list for reflowing.
77 : */
78 : void DrainOverflowColumns();
79 :
80 : // Return the column-content frame.
81 : void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
82 :
83 : #ifdef DEBUG_FRAME_DUMP
84 0 : virtual nsresult GetFrameName(nsAString& aResult) const override {
85 0 : return MakeFrameName(NS_LITERAL_STRING("ColumnSet"), aResult);
86 : }
87 : #endif
88 :
89 : nsRect CalculateBounds(const nsPoint& aOffset);
90 : void CreateBorderRenderers(nsTArray<nsCSSBorderRenderer>& aBorderRenderers,
91 : gfxContext* aCtx,
92 : const nsRect& aDirtyRect,
93 : const nsPoint& aPt);
94 :
95 : protected:
96 : nscoord mLastBalanceBSize;
97 : nsReflowStatus mLastFrameStatus;
98 :
99 : /**
100 : * These are the parameters that control the layout of columns.
101 : */
102 : struct ReflowConfig {
103 : // The number of columns that we want to balance across. If we're not
104 : // balancing, this will be set to INT32_MAX.
105 : int32_t mBalanceColCount;
106 :
107 : // The inline-size of each individual column.
108 : nscoord mColISize;
109 :
110 : // The amount of inline-size that is expected to be left over after all the
111 : // columns and column gaps are laid out.
112 : nscoord mExpectedISizeLeftOver;
113 :
114 : // The width (inline-size) of each column gap.
115 : nscoord mColGap;
116 :
117 : // The maximum bSize of any individual column during a reflow iteration.
118 : // This parameter is set during each iteration of the binary search for
119 : // the best column block-size.
120 : nscoord mColMaxBSize;
121 :
122 : // A boolean controlling whether or not we are balancing. This should be
123 : // equivalent to mBalanceColCount == INT32_MAX.
124 : bool mIsBalancing;
125 :
126 : // The last known column block-size that was 'feasible'. A column bSize is
127 : // feasible if all child content fits within the specified bSize.
128 : nscoord mKnownFeasibleBSize;
129 :
130 : // The last known block-size that was 'infeasible'. A column bSize is
131 : // infeasible if not all child content fits within the specified bSize.
132 : nscoord mKnownInfeasibleBSize;
133 :
134 : // block-size of the column set frame
135 : nscoord mComputedBSize;
136 :
137 : // The block-size "consumed" by previous-in-flows.
138 : // The computed block-size should be equal to the block-size of the element
139 : // (i.e. the computed block-size itself) plus the consumed block-size.
140 : nscoord mConsumedBSize;
141 : };
142 :
143 : /**
144 : * Some data that is better calculated during reflow
145 : */
146 : struct ColumnBalanceData {
147 : // The maximum "content block-size" of any column
148 : nscoord mMaxBSize;
149 : // The sum of the "content block-size" for all columns
150 : nscoord mSumBSize;
151 : // The "content block-size" of the last column
152 : nscoord mLastBSize;
153 : // The maximum "content block-size" of all columns that overflowed
154 : // their available block-size
155 : nscoord mMaxOverflowingBSize;
156 : // This flag determines whether the last reflow of children exceeded the
157 : // computed block-size of the column set frame. If so, we set the bSize to
158 : // this maximum allowable bSize, and continue reflow without balancing.
159 : bool mHasExcessBSize;
160 :
161 0 : void Reset() {
162 0 : mMaxBSize = mSumBSize = mLastBSize = mMaxOverflowingBSize = 0;
163 0 : mHasExcessBSize = false;
164 0 : }
165 : };
166 :
167 : bool ReflowColumns(ReflowOutput& aDesiredSize,
168 : const ReflowInput& aReflowInput,
169 : nsReflowStatus& aReflowStatus,
170 : ReflowConfig& aConfig,
171 : bool aLastColumnUnbounded,
172 : nsCollapsingMargin* aCarriedOutBEndMargin,
173 : ColumnBalanceData& aColData);
174 :
175 : /**
176 : * The basic reflow strategy is to call this function repeatedly to
177 : * obtain specific parameters that determine the layout of the
178 : * columns. This function will compute those parameters from the CSS
179 : * style. This function will also be responsible for implementing
180 : * the state machine that controls column balancing.
181 : */
182 : ReflowConfig ChooseColumnStrategy(const ReflowInput& aReflowInput,
183 : bool aForceAuto, nscoord aFeasibleBSize,
184 : nscoord aInfeasibleBSize);
185 :
186 : /**
187 : * Perform the binary search for the best balance height for this column set.
188 : *
189 : * @param aReflowInput The input parameters for the current reflow iteration.
190 : * @param aPresContext The presentation context in which the current reflow
191 : * iteration is occurring.
192 : * @param aConfig The ReflowConfig object associated with this column set
193 : * frame, generated by ChooseColumnStrategy().
194 : * @param aColData A data structure used to keep track of data needed between
195 : * successive iterations of the balancing process.
196 : * @param aDesiredSize The final output size of the column set frame (output
197 : * of reflow procedure).
198 : * @param aOutMargin The bottom margin of the column set frame that may be
199 : * carried out from reflow (and thus collapsed).
200 : * @param aUnboundedLastColumn A boolean value indicating that the last column
201 : * can be of any height. Used during the first iteration of the
202 : * balancing procedure to measure the height of all content in
203 : * descendant frames of the column set.
204 : * @param aRunWasFeasible An input/output parameter indicating whether or not
205 : * the last iteration of the balancing loop was a feasible height to
206 : * fit all content from descendant frames.
207 : * @param aStatus A final reflow status of the column set frame, passed in as
208 : * an output parameter.
209 : */
210 : void FindBestBalanceBSize(const ReflowInput& aReflowInput,
211 : nsPresContext* aPresContext,
212 : ReflowConfig& aConfig,
213 : ColumnBalanceData& aColData,
214 : ReflowOutput& aDesiredSize,
215 : nsCollapsingMargin& aOutMargin,
216 : bool& aUnboundedLastColumn,
217 : bool& aRunWasFeasible,
218 : nsReflowStatus& aStatus);
219 : /**
220 : * Reflow column children. Returns true iff the content that was reflowed
221 : * fit into the mColMaxBSize.
222 : */
223 : bool ReflowChildren(ReflowOutput& aDesiredSize,
224 : const ReflowInput& aReflowInput,
225 : nsReflowStatus& aStatus,
226 : const ReflowConfig& aConfig,
227 : bool aLastColumnUnbounded,
228 : nsCollapsingMargin* aCarriedOutBEndMargin,
229 : ColumnBalanceData& aColData);
230 :
231 : void ForEachColumn(const std::function<void(const nsRect& lineRect)>& aSetLineRect,
232 : const nsPoint& aPt);
233 : };
234 :
235 : #endif // nsColumnSetFrame_h___
|