/src/mozilla-central/layout/generic/nsColumnSetFrame.h
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 | | |
7 | | #ifndef nsColumnSetFrame_h___ |
8 | | #define nsColumnSetFrame_h___ |
9 | | |
10 | | /* rendering object for css3 multi-column layout */ |
11 | | |
12 | | #include "mozilla/Attributes.h" |
13 | | #include "nsContainerFrame.h" |
14 | | #include "nsIFrameInlines.h" // for methods used by IS_TRUE_OVERFLOW_CONTAINER |
15 | | |
16 | | /** |
17 | | * nsColumnSetFrame implements CSS multi-column layout. |
18 | | * @note nsColumnSetFrame keeps true overflow containers in the normal flow |
19 | | * child lists (i.e. the principal and overflow lists). |
20 | | */ |
21 | | class nsColumnSetFrame final : public nsContainerFrame |
22 | | { |
23 | | public: |
24 | | NS_DECL_FRAMEARENA_HELPERS(nsColumnSetFrame) |
25 | | |
26 | | explicit nsColumnSetFrame(ComputedStyle* aStyle); |
27 | | |
28 | | virtual void Reflow(nsPresContext* aPresContext, |
29 | | ReflowOutput& aDesiredSize, |
30 | | const ReflowInput& aReflowInput, |
31 | | nsReflowStatus& aStatus) override; |
32 | | |
33 | | #ifdef DEBUG |
34 | | virtual void SetInitialChildList(ChildListID aListID, |
35 | | nsFrameList& aChildList) override; |
36 | | virtual void AppendFrames(ChildListID aListID, |
37 | | nsFrameList& aFrameList) override; |
38 | | virtual void InsertFrames(ChildListID aListID, |
39 | | nsIFrame* aPrevFrame, |
40 | | nsFrameList& aFrameList) override; |
41 | | virtual void RemoveFrame(ChildListID aListID, |
42 | | nsIFrame* aOldFrame) override; |
43 | | #endif |
44 | | |
45 | | virtual nscoord GetMinISize(gfxContext *aRenderingContext) override; |
46 | | virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override; |
47 | | |
48 | | /** |
49 | | * Retrieve the available height for content of this frame. The available content |
50 | | * height is the available height for the frame, minus borders and padding. |
51 | | */ |
52 | | virtual nscoord GetAvailableContentBSize(const ReflowInput& aReflowInput); |
53 | | |
54 | 0 | virtual nsContainerFrame* GetContentInsertionFrame() override { |
55 | 0 | nsIFrame* frame = PrincipalChildList().FirstChild(); |
56 | 0 |
|
57 | 0 | // if no children return nullptr |
58 | 0 | if (!frame) |
59 | 0 | return nullptr; |
60 | 0 | |
61 | 0 | return frame->GetContentInsertionFrame(); |
62 | 0 | } |
63 | | |
64 | | virtual bool IsFrameOfType(uint32_t aFlags) const override |
65 | 0 | { |
66 | 0 | return nsContainerFrame::IsFrameOfType(aFlags & |
67 | 0 | ~(nsIFrame::eCanContainOverflowContainers)); |
68 | 0 | } |
69 | | |
70 | | virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
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 | | virtual nsresult GetFrameName(nsAString& aResult) const override { |
85 | | return MakeFrameName(NS_LITERAL_STRING("ColumnSet"), aResult); |
86 | | } |
87 | | #endif |
88 | | |
89 | | nsRect CalculateColumnRuleBounds(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 ForEachColumnRule(const std::function<void(const nsRect& lineRect)>& aSetLineRect, |
232 | | const nsPoint& aPt); |
233 | | |
234 | | static nscoord ClampUsedColumnWidth(const nsStyleCoord& aColumnWidth); |
235 | | }; |
236 | | |
237 | | #endif // nsColumnSetFrame_h___ |