diff options
Diffstat (limited to '')
-rw-r--r-- | layout/generic/nsColumnSetFrame.h | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/layout/generic/nsColumnSetFrame.h b/layout/generic/nsColumnSetFrame.h new file mode 100644 index 0000000000..20df72a07d --- /dev/null +++ b/layout/generic/nsColumnSetFrame.h @@ -0,0 +1,201 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsColumnSetFrame_h___ +#define nsColumnSetFrame_h___ + +/* rendering object for css3 multi-column layout */ + +#include "mozilla/Attributes.h" +#include "nsContainerFrame.h" + +class nsCSSBorderRenderer; + +/** + * nsColumnSetFrame implements CSS multi-column layout. + * @note nsColumnSetFrame keeps true overflow containers in the normal flow + * child lists (i.e. the principal and overflow lists). + */ +class nsColumnSetFrame final : public nsContainerFrame { + public: + NS_DECL_FRAMEARENA_HELPERS(nsColumnSetFrame) + + explicit nsColumnSetFrame(ComputedStyle* aStyle, nsPresContext* aPresContext); + + void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, + const ReflowInput& aReflowInput, + nsReflowStatus& aStatus) override; + +#ifdef DEBUG + void SetInitialChildList(ChildListID aListID, + nsFrameList&& aChildList) override; + void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override; + void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, + const nsLineList::iterator* aPrevFrameLine, + nsFrameList&& aFrameList) override; + void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override; +#endif + + nscoord GetMinISize(gfxContext* aRenderingContext) override; + nscoord GetPrefISize(gfxContext* aRenderingContext) override; + + nsContainerFrame* GetContentInsertionFrame() override { + nsIFrame* frame = PrincipalChildList().FirstChild(); + + // if no children return nullptr + if (!frame) return nullptr; + + return frame->GetContentInsertionFrame(); + } + + void BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aLists) override; + + /** + * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not + * handled by our prev-in-flow, and any columns sitting on our own + * overflow list, and put them in our primary child list for reflowing. + */ + void DrainOverflowColumns(); + + // Return the column-content frame. + void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override; + +#ifdef DEBUG_FRAME_DUMP + nsresult GetFrameName(nsAString& aResult) const override { + return MakeFrameName(u"ColumnSet"_ns, aResult); + } +#endif + + void CreateBorderRenderers(nsTArray<nsCSSBorderRenderer>& aBorderRenderers, + gfxContext* aCtx, const nsRect& aDirtyRect, + const nsPoint& aPt); + + Maybe<nscoord> GetNaturalBaselineBOffset( + mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup, + BaselineExportContext aExportContext) const override; + + protected: + nscoord mLastBalanceBSize; + nsReflowStatus mLastFrameStatus; + + /** + * These are the parameters that control the layout of columns. + */ + struct ReflowConfig { + // The optimal number of columns that we want to use. This is computed from + // column-count, column-width, available inline-size, etc. + int32_t mUsedColCount = INT32_MAX; + + // The inline-size of each individual column. + nscoord mColISize = NS_UNCONSTRAINEDSIZE; + + // The amount of inline-size that is expected to be left over after all the + // columns and column gaps are laid out. + nscoord mExpectedISizeLeftOver = 0; + + // The width (inline-size) of each column gap. + nscoord mColGap = NS_UNCONSTRAINEDSIZE; + + // The available block-size of each individual column. This parameter is set + // during each iteration of the binary search for the best column + // block-size. + nscoord mColBSize = NS_UNCONSTRAINEDSIZE; + + // A boolean controlling whether or not we are balancing. + bool mIsBalancing = false; + + // A boolean controlling whether or not we are forced to fill columns + // sequentially. + bool mForceAuto = false; + + // A boolean indicates whether or not we are in the last attempt to reflow + // columns. We set it to true at the end of FindBestBalanceBSize(). + bool mIsLastBalancingReflow = false; + + // The last known column block-size that was 'feasible'. A column bSize is + // feasible if all child content fits within the specified bSize. + nscoord mKnownFeasibleBSize = NS_UNCONSTRAINEDSIZE; + + // The last known block-size that was 'infeasible'. A column bSize is + // infeasible if not all child content fits within the specified bSize. + nscoord mKnownInfeasibleBSize = 0; + }; + + // Collect various block-size data calculated in ReflowChildren(), which are + // mainly used for column balancing. This is the output of ReflowChildren() + // and ReflowColumns(). + struct ColumnBalanceData { + // The maximum "content block-size" of any column + nscoord mMaxBSize = 0; + + // The sum of the "content block-size" for all columns + nscoord mSumBSize = 0; + + // The "content block-size" of the last column + nscoord mLastBSize = 0; + + // The maximum "content block-size" of all columns that overflowed + // their available block-size + nscoord mMaxOverflowingBSize = 0; + + // The number of columns (starting from 1 because we have at least one + // column). It can be less than ReflowConfig::mUsedColCount. + int32_t mColCount = 1; + + // This flag indicates the content that was reflowed fits into the + // mColMaxBSize in ReflowConfig. + bool mFeasible = false; + }; + + ColumnBalanceData ReflowColumns(ReflowOutput& aDesiredSize, + const ReflowInput& aReflowInput, + nsReflowStatus& aStatus, + const ReflowConfig& aConfig, + bool aUnboundedLastColumn); + + /** + * The basic reflow strategy is to call this function repeatedly to + * obtain specific parameters that determine the layout of the + * columns. This function will compute those parameters from the CSS + * style. This function will also be responsible for implementing + * the state machine that controls column balancing. + */ + ReflowConfig ChooseColumnStrategy(const ReflowInput& aReflowInput, + bool aForceAuto) const; + + /** + * Perform the binary search for the best balance block-size for this column + * set. + * + * @param aReflowInput The input parameters for the current reflow iteration. + * @param aPresContext The presentation context in which the current reflow + * iteration is occurring. + * @param aConfig The ReflowConfig object associated with this column set + * frame, generated by ChooseColumnStrategy(). + * @param aColData A data structure used to keep track of data needed between + * successive iterations of the balancing process. + * @param aDesiredSize The final output size of the column set frame (output + * of reflow procedure). + * @param aUnboundedLastColumn A boolean value indicating that the last column + * can be of any block-size. Used during the first iteration of the + * balancing procedure to measure the block-size of all content in + * descendant frames of the column set. + * @param aStatus A final reflow status of the column set frame, passed in as + * an output parameter. + */ + void FindBestBalanceBSize(const ReflowInput& aReflowInput, + nsPresContext* aPresContext, ReflowConfig& aConfig, + ColumnBalanceData aColData, + ReflowOutput& aDesiredSize, + bool aUnboundedLastColumn, nsReflowStatus& aStatus); + + void ForEachColumnRule( + const std::function<void(const nsRect& lineRect)>& aSetLineRect, + const nsPoint& aPt) const; +}; + +#endif // nsColumnSetFrame_h___ |