1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsColumnSetFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,221 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* rendering object for css3 multi-column layout */ 1.10 + 1.11 +#include "mozilla/Attributes.h" 1.12 +#include "nsContainerFrame.h" 1.13 + 1.14 +class nsColumnSetFrame : public nsContainerFrame { 1.15 +public: 1.16 + NS_DECL_FRAMEARENA_HELPERS 1.17 + 1.18 + nsColumnSetFrame(nsStyleContext* aContext); 1.19 + 1.20 + virtual nsresult SetInitialChildList(ChildListID aListID, 1.21 + nsFrameList& aChildList) MOZ_OVERRIDE; 1.22 + 1.23 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.24 + nsHTMLReflowMetrics& aDesiredSize, 1.25 + const nsHTMLReflowState& aReflowState, 1.26 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.27 + 1.28 + virtual nsresult AppendFrames(ChildListID aListID, 1.29 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.30 + virtual nsresult InsertFrames(ChildListID aListID, 1.31 + nsIFrame* aPrevFrame, 1.32 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.33 + virtual nsresult RemoveFrame(ChildListID aListID, 1.34 + nsIFrame* aOldFrame) MOZ_OVERRIDE; 1.35 + 1.36 + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.37 + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.38 + 1.39 + /** 1.40 + * Retrieve the available height for content of this frame. The available content 1.41 + * height is the available height for the frame, minus borders and padding. 1.42 + */ 1.43 + virtual nscoord GetAvailableContentHeight(const nsHTMLReflowState& aReflowState); 1.44 + 1.45 + virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE { 1.46 + nsIFrame* frame = GetFirstPrincipalChild(); 1.47 + 1.48 + // if no children return nullptr 1.49 + if (!frame) 1.50 + return nullptr; 1.51 + 1.52 + return frame->GetContentInsertionFrame(); 1.53 + } 1.54 + 1.55 + virtual nsresult StealFrame(nsIFrame* aChild, bool aForceNormal) MOZ_OVERRIDE 1.56 + { // nsColumnSetFrame keeps overflow containers in main child list 1.57 + return nsContainerFrame::StealFrame(aChild, true); 1.58 + } 1.59 + 1.60 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.61 + { 1.62 + return nsContainerFrame::IsFrameOfType(aFlags & 1.63 + ~(nsIFrame::eCanContainOverflowContainers)); 1.64 + } 1.65 + 1.66 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.67 + const nsRect& aDirtyRect, 1.68 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.69 + 1.70 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.71 + 1.72 + virtual void PaintColumnRule(nsRenderingContext* aCtx, 1.73 + const nsRect& aDirtyRect, 1.74 + const nsPoint& aPt); 1.75 + 1.76 +#ifdef DEBUG_FRAME_DUMP 1.77 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { 1.78 + return MakeFrameName(NS_LITERAL_STRING("ColumnSet"), aResult); 1.79 + } 1.80 +#endif 1.81 + 1.82 +protected: 1.83 + nscoord mLastBalanceHeight; 1.84 + nsReflowStatus mLastFrameStatus; 1.85 + 1.86 + /** 1.87 + * These are the parameters that control the layout of columns. 1.88 + */ 1.89 + struct ReflowConfig { 1.90 + // The number of columns that we want to balance across. If we're not 1.91 + // balancing, this will be set to INT32_MAX. 1.92 + int32_t mBalanceColCount; 1.93 + 1.94 + // The width of each individual column. 1.95 + nscoord mColWidth; 1.96 + 1.97 + // The amount of width that is expected to be left over after all the 1.98 + // columns and column gaps are laid out. 1.99 + nscoord mExpectedWidthLeftOver; 1.100 + 1.101 + // The width of each column gap. 1.102 + nscoord mColGap; 1.103 + 1.104 + // The maximum height of any individual column during a reflow iteration. 1.105 + // This parameter is set during each iteration of the binary search for 1.106 + // the best column height. 1.107 + nscoord mColMaxHeight; 1.108 + 1.109 + // A boolean controlling whether or not we are balancing. This should be 1.110 + // equivalent to mBalanceColCount == INT32_MAX. 1.111 + bool mIsBalancing; 1.112 + 1.113 + // The last known column height that was 'feasible'. A column height is 1.114 + // feasible if all child content fits within the specified height. 1.115 + nscoord mKnownFeasibleHeight; 1.116 + 1.117 + // The last known height that was 'infeasible'. A column height is 1.118 + // infeasible if not all child content fits within the specified height. 1.119 + nscoord mKnownInfeasibleHeight; 1.120 + 1.121 + // Height of the column set frame 1.122 + nscoord mComputedHeight; 1.123 + 1.124 + // The height "consumed" by previous-in-flows. 1.125 + // The computed height should be equal to the height of the element (i.e. 1.126 + // the computed height itself) plus the consumed height. 1.127 + nscoord mConsumedHeight; 1.128 + }; 1.129 + 1.130 + /** 1.131 + * Some data that is better calculated during reflow 1.132 + */ 1.133 + struct ColumnBalanceData { 1.134 + // The maximum "content height" of any column 1.135 + nscoord mMaxHeight; 1.136 + // The sum of the "content heights" for all columns 1.137 + nscoord mSumHeight; 1.138 + // The "content height" of the last column 1.139 + nscoord mLastHeight; 1.140 + // The maximum "content height" of all columns that overflowed 1.141 + // their available height 1.142 + nscoord mMaxOverflowingHeight; 1.143 + // This flag determines whether the last reflow of children exceeded the 1.144 + // computed height of the column set frame. If so, we set the height to 1.145 + // this maximum allowable height, and continue reflow without balancing. 1.146 + bool mHasExcessHeight; 1.147 + 1.148 + void Reset() { 1.149 + mMaxHeight = mSumHeight = mLastHeight = mMaxOverflowingHeight = 0; 1.150 + mHasExcessHeight = false; 1.151 + } 1.152 + }; 1.153 + 1.154 + /** 1.155 + * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not 1.156 + * handled by our prev-in-flow, and any columns sitting on our own 1.157 + * overflow list, and put them in our primary child list for reflowing. 1.158 + */ 1.159 + void DrainOverflowColumns(); 1.160 + 1.161 + bool ReflowColumns(nsHTMLReflowMetrics& aDesiredSize, 1.162 + const nsHTMLReflowState& aReflowState, 1.163 + nsReflowStatus& aReflowStatus, 1.164 + ReflowConfig& aConfig, 1.165 + bool aLastColumnUnbounded, 1.166 + nsCollapsingMargin* aCarriedOutBottomMargin, 1.167 + ColumnBalanceData& aColData); 1.168 + 1.169 + /** 1.170 + * The basic reflow strategy is to call this function repeatedly to 1.171 + * obtain specific parameters that determine the layout of the 1.172 + * columns. This function will compute those parameters from the CSS 1.173 + * style. This function will also be responsible for implementing 1.174 + * the state machine that controls column balancing. 1.175 + */ 1.176 + ReflowConfig ChooseColumnStrategy(const nsHTMLReflowState& aReflowState, 1.177 + bool aForceAuto, nscoord aFeasibleHeight, 1.178 + nscoord aInfeasibleHeight); 1.179 + 1.180 + /** 1.181 + * Perform the binary search for the best balance height for this column set. 1.182 + * 1.183 + * @param aReflowState The input parameters for the current reflow iteration. 1.184 + * @param aPresContext The presentation context in which the current reflow 1.185 + * iteration is occurring. 1.186 + * @param aConfig The ReflowConfig object associated with this column set 1.187 + * frame, generated by ChooseColumnStrategy(). 1.188 + * @param aColData A data structure used to keep track of data needed between 1.189 + * successive iterations of the balancing process. 1.190 + * @param aDesiredSize The final output size of the column set frame (output 1.191 + * of reflow procedure). 1.192 + * @param aOutMargin The bottom margin of the column set frame that may be 1.193 + * carried out from reflow (and thus collapsed). 1.194 + * @param aUnboundedLastColumn A boolean value indicating that the last column 1.195 + * can be of any height. Used during the first iteration of the 1.196 + * balancing procedure to measure the height of all content in 1.197 + * descendant frames of the column set. 1.198 + * @param aRunWasFeasible An input/output parameter indicating whether or not 1.199 + * the last iteration of the balancing loop was a feasible height to 1.200 + * fit all content from descendant frames. 1.201 + * @param aStatus A final reflow status of the column set frame, passed in as 1.202 + * an output parameter. 1.203 + */ 1.204 + void FindBestBalanceHeight(const nsHTMLReflowState& aReflowState, 1.205 + nsPresContext* aPresContext, 1.206 + ReflowConfig& aConfig, 1.207 + ColumnBalanceData& aColData, 1.208 + nsHTMLReflowMetrics& aDesiredSize, 1.209 + nsCollapsingMargin& aOutMargin, 1.210 + bool& aUnboundedLastColumn, 1.211 + bool& aRunWasFeasible, 1.212 + nsReflowStatus& aStatus); 1.213 + /** 1.214 + * Reflow column children. Returns true iff the content that was reflowed 1.215 + * fit into the mColMaxHeight. 1.216 + */ 1.217 + bool ReflowChildren(nsHTMLReflowMetrics& aDesiredSize, 1.218 + const nsHTMLReflowState& aReflowState, 1.219 + nsReflowStatus& aStatus, 1.220 + const ReflowConfig& aConfig, 1.221 + bool aLastColumnUnbounded, 1.222 + nsCollapsingMargin* aCarriedOutBottomMargin, 1.223 + ColumnBalanceData& aColData); 1.224 +};