Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* rendering object for css3 multi-column layout */ |
michael@0 | 7 | |
michael@0 | 8 | #include "mozilla/Attributes.h" |
michael@0 | 9 | #include "nsContainerFrame.h" |
michael@0 | 10 | |
michael@0 | 11 | class nsColumnSetFrame : public nsContainerFrame { |
michael@0 | 12 | public: |
michael@0 | 13 | NS_DECL_FRAMEARENA_HELPERS |
michael@0 | 14 | |
michael@0 | 15 | nsColumnSetFrame(nsStyleContext* aContext); |
michael@0 | 16 | |
michael@0 | 17 | virtual nsresult SetInitialChildList(ChildListID aListID, |
michael@0 | 18 | nsFrameList& aChildList) MOZ_OVERRIDE; |
michael@0 | 19 | |
michael@0 | 20 | virtual nsresult Reflow(nsPresContext* aPresContext, |
michael@0 | 21 | nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 22 | const nsHTMLReflowState& aReflowState, |
michael@0 | 23 | nsReflowStatus& aStatus) MOZ_OVERRIDE; |
michael@0 | 24 | |
michael@0 | 25 | virtual nsresult AppendFrames(ChildListID aListID, |
michael@0 | 26 | nsFrameList& aFrameList) MOZ_OVERRIDE; |
michael@0 | 27 | virtual nsresult InsertFrames(ChildListID aListID, |
michael@0 | 28 | nsIFrame* aPrevFrame, |
michael@0 | 29 | nsFrameList& aFrameList) MOZ_OVERRIDE; |
michael@0 | 30 | virtual nsresult RemoveFrame(ChildListID aListID, |
michael@0 | 31 | nsIFrame* aOldFrame) MOZ_OVERRIDE; |
michael@0 | 32 | |
michael@0 | 33 | virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; |
michael@0 | 34 | virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; |
michael@0 | 35 | |
michael@0 | 36 | /** |
michael@0 | 37 | * Retrieve the available height for content of this frame. The available content |
michael@0 | 38 | * height is the available height for the frame, minus borders and padding. |
michael@0 | 39 | */ |
michael@0 | 40 | virtual nscoord GetAvailableContentHeight(const nsHTMLReflowState& aReflowState); |
michael@0 | 41 | |
michael@0 | 42 | virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE { |
michael@0 | 43 | nsIFrame* frame = GetFirstPrincipalChild(); |
michael@0 | 44 | |
michael@0 | 45 | // if no children return nullptr |
michael@0 | 46 | if (!frame) |
michael@0 | 47 | return nullptr; |
michael@0 | 48 | |
michael@0 | 49 | return frame->GetContentInsertionFrame(); |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | virtual nsresult StealFrame(nsIFrame* aChild, bool aForceNormal) MOZ_OVERRIDE |
michael@0 | 53 | { // nsColumnSetFrame keeps overflow containers in main child list |
michael@0 | 54 | return nsContainerFrame::StealFrame(aChild, true); |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE |
michael@0 | 58 | { |
michael@0 | 59 | return nsContainerFrame::IsFrameOfType(aFlags & |
michael@0 | 60 | ~(nsIFrame::eCanContainOverflowContainers)); |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
michael@0 | 64 | const nsRect& aDirtyRect, |
michael@0 | 65 | const nsDisplayListSet& aLists) MOZ_OVERRIDE; |
michael@0 | 66 | |
michael@0 | 67 | virtual nsIAtom* GetType() const MOZ_OVERRIDE; |
michael@0 | 68 | |
michael@0 | 69 | virtual void PaintColumnRule(nsRenderingContext* aCtx, |
michael@0 | 70 | const nsRect& aDirtyRect, |
michael@0 | 71 | const nsPoint& aPt); |
michael@0 | 72 | |
michael@0 | 73 | #ifdef DEBUG_FRAME_DUMP |
michael@0 | 74 | virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { |
michael@0 | 75 | return MakeFrameName(NS_LITERAL_STRING("ColumnSet"), aResult); |
michael@0 | 76 | } |
michael@0 | 77 | #endif |
michael@0 | 78 | |
michael@0 | 79 | protected: |
michael@0 | 80 | nscoord mLastBalanceHeight; |
michael@0 | 81 | nsReflowStatus mLastFrameStatus; |
michael@0 | 82 | |
michael@0 | 83 | /** |
michael@0 | 84 | * These are the parameters that control the layout of columns. |
michael@0 | 85 | */ |
michael@0 | 86 | struct ReflowConfig { |
michael@0 | 87 | // The number of columns that we want to balance across. If we're not |
michael@0 | 88 | // balancing, this will be set to INT32_MAX. |
michael@0 | 89 | int32_t mBalanceColCount; |
michael@0 | 90 | |
michael@0 | 91 | // The width of each individual column. |
michael@0 | 92 | nscoord mColWidth; |
michael@0 | 93 | |
michael@0 | 94 | // The amount of width that is expected to be left over after all the |
michael@0 | 95 | // columns and column gaps are laid out. |
michael@0 | 96 | nscoord mExpectedWidthLeftOver; |
michael@0 | 97 | |
michael@0 | 98 | // The width of each column gap. |
michael@0 | 99 | nscoord mColGap; |
michael@0 | 100 | |
michael@0 | 101 | // The maximum height of any individual column during a reflow iteration. |
michael@0 | 102 | // This parameter is set during each iteration of the binary search for |
michael@0 | 103 | // the best column height. |
michael@0 | 104 | nscoord mColMaxHeight; |
michael@0 | 105 | |
michael@0 | 106 | // A boolean controlling whether or not we are balancing. This should be |
michael@0 | 107 | // equivalent to mBalanceColCount == INT32_MAX. |
michael@0 | 108 | bool mIsBalancing; |
michael@0 | 109 | |
michael@0 | 110 | // The last known column height that was 'feasible'. A column height is |
michael@0 | 111 | // feasible if all child content fits within the specified height. |
michael@0 | 112 | nscoord mKnownFeasibleHeight; |
michael@0 | 113 | |
michael@0 | 114 | // The last known height that was 'infeasible'. A column height is |
michael@0 | 115 | // infeasible if not all child content fits within the specified height. |
michael@0 | 116 | nscoord mKnownInfeasibleHeight; |
michael@0 | 117 | |
michael@0 | 118 | // Height of the column set frame |
michael@0 | 119 | nscoord mComputedHeight; |
michael@0 | 120 | |
michael@0 | 121 | // The height "consumed" by previous-in-flows. |
michael@0 | 122 | // The computed height should be equal to the height of the element (i.e. |
michael@0 | 123 | // the computed height itself) plus the consumed height. |
michael@0 | 124 | nscoord mConsumedHeight; |
michael@0 | 125 | }; |
michael@0 | 126 | |
michael@0 | 127 | /** |
michael@0 | 128 | * Some data that is better calculated during reflow |
michael@0 | 129 | */ |
michael@0 | 130 | struct ColumnBalanceData { |
michael@0 | 131 | // The maximum "content height" of any column |
michael@0 | 132 | nscoord mMaxHeight; |
michael@0 | 133 | // The sum of the "content heights" for all columns |
michael@0 | 134 | nscoord mSumHeight; |
michael@0 | 135 | // The "content height" of the last column |
michael@0 | 136 | nscoord mLastHeight; |
michael@0 | 137 | // The maximum "content height" of all columns that overflowed |
michael@0 | 138 | // their available height |
michael@0 | 139 | nscoord mMaxOverflowingHeight; |
michael@0 | 140 | // This flag determines whether the last reflow of children exceeded the |
michael@0 | 141 | // computed height of the column set frame. If so, we set the height to |
michael@0 | 142 | // this maximum allowable height, and continue reflow without balancing. |
michael@0 | 143 | bool mHasExcessHeight; |
michael@0 | 144 | |
michael@0 | 145 | void Reset() { |
michael@0 | 146 | mMaxHeight = mSumHeight = mLastHeight = mMaxOverflowingHeight = 0; |
michael@0 | 147 | mHasExcessHeight = false; |
michael@0 | 148 | } |
michael@0 | 149 | }; |
michael@0 | 150 | |
michael@0 | 151 | /** |
michael@0 | 152 | * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not |
michael@0 | 153 | * handled by our prev-in-flow, and any columns sitting on our own |
michael@0 | 154 | * overflow list, and put them in our primary child list for reflowing. |
michael@0 | 155 | */ |
michael@0 | 156 | void DrainOverflowColumns(); |
michael@0 | 157 | |
michael@0 | 158 | bool ReflowColumns(nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 159 | const nsHTMLReflowState& aReflowState, |
michael@0 | 160 | nsReflowStatus& aReflowStatus, |
michael@0 | 161 | ReflowConfig& aConfig, |
michael@0 | 162 | bool aLastColumnUnbounded, |
michael@0 | 163 | nsCollapsingMargin* aCarriedOutBottomMargin, |
michael@0 | 164 | ColumnBalanceData& aColData); |
michael@0 | 165 | |
michael@0 | 166 | /** |
michael@0 | 167 | * The basic reflow strategy is to call this function repeatedly to |
michael@0 | 168 | * obtain specific parameters that determine the layout of the |
michael@0 | 169 | * columns. This function will compute those parameters from the CSS |
michael@0 | 170 | * style. This function will also be responsible for implementing |
michael@0 | 171 | * the state machine that controls column balancing. |
michael@0 | 172 | */ |
michael@0 | 173 | ReflowConfig ChooseColumnStrategy(const nsHTMLReflowState& aReflowState, |
michael@0 | 174 | bool aForceAuto, nscoord aFeasibleHeight, |
michael@0 | 175 | nscoord aInfeasibleHeight); |
michael@0 | 176 | |
michael@0 | 177 | /** |
michael@0 | 178 | * Perform the binary search for the best balance height for this column set. |
michael@0 | 179 | * |
michael@0 | 180 | * @param aReflowState The input parameters for the current reflow iteration. |
michael@0 | 181 | * @param aPresContext The presentation context in which the current reflow |
michael@0 | 182 | * iteration is occurring. |
michael@0 | 183 | * @param aConfig The ReflowConfig object associated with this column set |
michael@0 | 184 | * frame, generated by ChooseColumnStrategy(). |
michael@0 | 185 | * @param aColData A data structure used to keep track of data needed between |
michael@0 | 186 | * successive iterations of the balancing process. |
michael@0 | 187 | * @param aDesiredSize The final output size of the column set frame (output |
michael@0 | 188 | * of reflow procedure). |
michael@0 | 189 | * @param aOutMargin The bottom margin of the column set frame that may be |
michael@0 | 190 | * carried out from reflow (and thus collapsed). |
michael@0 | 191 | * @param aUnboundedLastColumn A boolean value indicating that the last column |
michael@0 | 192 | * can be of any height. Used during the first iteration of the |
michael@0 | 193 | * balancing procedure to measure the height of all content in |
michael@0 | 194 | * descendant frames of the column set. |
michael@0 | 195 | * @param aRunWasFeasible An input/output parameter indicating whether or not |
michael@0 | 196 | * the last iteration of the balancing loop was a feasible height to |
michael@0 | 197 | * fit all content from descendant frames. |
michael@0 | 198 | * @param aStatus A final reflow status of the column set frame, passed in as |
michael@0 | 199 | * an output parameter. |
michael@0 | 200 | */ |
michael@0 | 201 | void FindBestBalanceHeight(const nsHTMLReflowState& aReflowState, |
michael@0 | 202 | nsPresContext* aPresContext, |
michael@0 | 203 | ReflowConfig& aConfig, |
michael@0 | 204 | ColumnBalanceData& aColData, |
michael@0 | 205 | nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 206 | nsCollapsingMargin& aOutMargin, |
michael@0 | 207 | bool& aUnboundedLastColumn, |
michael@0 | 208 | bool& aRunWasFeasible, |
michael@0 | 209 | nsReflowStatus& aStatus); |
michael@0 | 210 | /** |
michael@0 | 211 | * Reflow column children. Returns true iff the content that was reflowed |
michael@0 | 212 | * fit into the mColMaxHeight. |
michael@0 | 213 | */ |
michael@0 | 214 | bool ReflowChildren(nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 215 | const nsHTMLReflowState& aReflowState, |
michael@0 | 216 | nsReflowStatus& aStatus, |
michael@0 | 217 | const ReflowConfig& aConfig, |
michael@0 | 218 | bool aLastColumnUnbounded, |
michael@0 | 219 | nsCollapsingMargin* aCarriedOutBottomMargin, |
michael@0 | 220 | ColumnBalanceData& aColData); |
michael@0 | 221 | }; |