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/. */
7 #ifndef nsColumnSetFrame_h___
8 #define nsColumnSetFrame_h___
10 /* rendering object for css3 multi-column layout */
12 #include "mozilla/Attributes.h"
13 #include "nsContainerFrame.h"
15 class nsCSSBorderRenderer
;
18 * nsColumnSetFrame implements CSS multi-column layout.
19 * @note nsColumnSetFrame keeps true overflow containers in the normal flow
20 * child lists (i.e. the principal and overflow lists).
22 class nsColumnSetFrame final
: public nsContainerFrame
{
24 NS_DECL_FRAMEARENA_HELPERS(nsColumnSetFrame
)
26 explicit nsColumnSetFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
);
28 void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
29 const ReflowInput
& aReflowInput
,
30 nsReflowStatus
& aStatus
) override
;
33 void SetInitialChildList(ChildListID aListID
,
34 nsFrameList
&& aChildList
) override
;
35 void AppendFrames(ChildListID aListID
, nsFrameList
&& aFrameList
) override
;
36 void InsertFrames(ChildListID aListID
, nsIFrame
* aPrevFrame
,
37 const nsLineList::iterator
* aPrevFrameLine
,
38 nsFrameList
&& aFrameList
) override
;
39 void RemoveFrame(DestroyContext
&, ChildListID
, nsIFrame
*) override
;
42 nscoord
GetMinISize(gfxContext
* aRenderingContext
) override
;
43 nscoord
GetPrefISize(gfxContext
* aRenderingContext
) override
;
45 nsContainerFrame
* GetContentInsertionFrame() override
{
46 nsIFrame
* frame
= PrincipalChildList().FirstChild();
48 // if no children return nullptr
49 if (!frame
) return nullptr;
51 return frame
->GetContentInsertionFrame();
54 void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
55 const nsDisplayListSet
& aLists
) override
;
58 * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not
59 * handled by our prev-in-flow, and any columns sitting on our own
60 * overflow list, and put them in our primary child list for reflowing.
62 void DrainOverflowColumns();
64 // Return the column-content frame.
65 void AppendDirectlyOwnedAnonBoxes(nsTArray
<OwnedAnonBox
>& aResult
) override
;
67 #ifdef DEBUG_FRAME_DUMP
68 nsresult
GetFrameName(nsAString
& aResult
) const override
{
69 return MakeFrameName(u
"ColumnSet"_ns
, aResult
);
73 void CreateBorderRenderers(nsTArray
<nsCSSBorderRenderer
>& aBorderRenderers
,
74 gfxContext
* aCtx
, const nsRect
& aDirtyRect
,
77 Maybe
<nscoord
> GetNaturalBaselineBOffset(
78 mozilla::WritingMode aWM
, BaselineSharingGroup aBaselineGroup
,
79 BaselineExportContext aExportContext
) const override
;
82 nscoord mLastBalanceBSize
;
83 nsReflowStatus mLastFrameStatus
;
86 * These are the parameters that control the layout of columns.
89 // The optimal number of columns that we want to use. This is computed from
90 // column-count, column-width, available inline-size, etc.
91 int32_t mUsedColCount
= INT32_MAX
;
93 // The inline-size of each individual column.
94 nscoord mColISize
= NS_UNCONSTRAINEDSIZE
;
96 // The amount of inline-size that is expected to be left over after all the
97 // columns and column gaps are laid out.
98 nscoord mExpectedISizeLeftOver
= 0;
100 // The width (inline-size) of each column gap.
101 nscoord mColGap
= NS_UNCONSTRAINEDSIZE
;
103 // The available block-size of each individual column. This parameter is set
104 // during each iteration of the binary search for the best column
106 nscoord mColBSize
= NS_UNCONSTRAINEDSIZE
;
108 // A boolean controlling whether or not we are balancing.
109 bool mIsBalancing
= false;
111 // A boolean controlling whether or not we are forced to fill columns
113 bool mForceAuto
= false;
115 // A boolean indicates whether or not we are in the last attempt to reflow
116 // columns. We set it to true at the end of FindBestBalanceBSize().
117 bool mIsLastBalancingReflow
= false;
119 // The last known column block-size that was 'feasible'. A column bSize is
120 // feasible if all child content fits within the specified bSize.
121 nscoord mKnownFeasibleBSize
= NS_UNCONSTRAINEDSIZE
;
123 // The last known block-size that was 'infeasible'. A column bSize is
124 // infeasible if not all child content fits within the specified bSize.
125 nscoord mKnownInfeasibleBSize
= 0;
128 // Collect various block-size data calculated in ReflowChildren(), which are
129 // mainly used for column balancing. This is the output of ReflowChildren()
130 // and ReflowColumns().
131 struct ColumnBalanceData
{
132 // The maximum "content block-size" of any column
133 nscoord mMaxBSize
= 0;
135 // The sum of the "content block-size" for all columns
136 nscoord mSumBSize
= 0;
138 // The "content block-size" of the last column
139 nscoord mLastBSize
= 0;
141 // The maximum "content block-size" of all columns that overflowed
142 // their available block-size
143 nscoord mMaxOverflowingBSize
= 0;
145 // The number of columns (starting from 1 because we have at least one
146 // column). It can be less than ReflowConfig::mUsedColCount.
147 int32_t mColCount
= 1;
149 // This flag indicates the content that was reflowed fits into the
150 // mColMaxBSize in ReflowConfig.
151 bool mFeasible
= false;
154 ColumnBalanceData
ReflowColumns(ReflowOutput
& aDesiredSize
,
155 const ReflowInput
& aReflowInput
,
156 nsReflowStatus
& aStatus
,
157 const ReflowConfig
& aConfig
,
158 bool aUnboundedLastColumn
);
161 * The basic reflow strategy is to call this function repeatedly to
162 * obtain specific parameters that determine the layout of the
163 * columns. This function will compute those parameters from the CSS
164 * style. This function will also be responsible for implementing
165 * the state machine that controls column balancing.
167 ReflowConfig
ChooseColumnStrategy(const ReflowInput
& aReflowInput
,
168 bool aForceAuto
) const;
171 * Perform the binary search for the best balance block-size for this column
174 * @param aReflowInput The input parameters for the current reflow iteration.
175 * @param aPresContext The presentation context in which the current reflow
176 * iteration is occurring.
177 * @param aConfig The ReflowConfig object associated with this column set
178 * frame, generated by ChooseColumnStrategy().
179 * @param aColData A data structure used to keep track of data needed between
180 * successive iterations of the balancing process.
181 * @param aDesiredSize The final output size of the column set frame (output
182 * of reflow procedure).
183 * @param aUnboundedLastColumn A boolean value indicating that the last column
184 * can be of any block-size. Used during the first iteration of the
185 * balancing procedure to measure the block-size of all content in
186 * descendant frames of the column set.
187 * @param aStatus A final reflow status of the column set frame, passed in as
188 * an output parameter.
190 void FindBestBalanceBSize(const ReflowInput
& aReflowInput
,
191 nsPresContext
* aPresContext
, ReflowConfig
& aConfig
,
192 ColumnBalanceData aColData
,
193 ReflowOutput
& aDesiredSize
,
194 bool aUnboundedLastColumn
, nsReflowStatus
& aStatus
);
196 void ForEachColumnRule(
197 const std::function
<void(const nsRect
& lineRect
)>& aSetLineRect
,
198 const nsPoint
& aPt
) const;
201 #endif // nsColumnSetFrame_h___