forked from mirrors/gecko-dev
		
	 103218a88d
			
		
	
	
		103218a88d
		
	
	
	
	
		
			
			First/Last Baseline should be from highest/lowest baseline in all columns and spanners. Differential Revision: https://phabricator.services.mozilla.com/D171261
		
			
				
	
	
		
			201 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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(ChildListID aListID, nsIFrame* aOldFrame) 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) 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___
 |