зеркало из https://github.com/mozilla/gecko-dev.git
224 строки
9.0 KiB
C++
224 строки
9.0 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* 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/. */
|
|
|
|
/* rendering object for css3 multi-column layout */
|
|
|
|
#include "mozilla/Attributes.h"
|
|
#include "nsContainerFrame.h"
|
|
|
|
class nsColumnSetFrame : public nsContainerFrame {
|
|
public:
|
|
NS_DECL_FRAMEARENA_HELPERS
|
|
|
|
nsColumnSetFrame(nsStyleContext* aContext);
|
|
|
|
NS_IMETHOD SetInitialChildList(ChildListID aListID,
|
|
nsFrameList& aChildList) MOZ_OVERRIDE;
|
|
|
|
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
const nsHTMLReflowState& aReflowState,
|
|
nsReflowStatus& aStatus) MOZ_OVERRIDE;
|
|
|
|
NS_IMETHOD AppendFrames(ChildListID aListID,
|
|
nsFrameList& aFrameList) MOZ_OVERRIDE;
|
|
NS_IMETHOD InsertFrames(ChildListID aListID,
|
|
nsIFrame* aPrevFrame,
|
|
nsFrameList& aFrameList) MOZ_OVERRIDE;
|
|
NS_IMETHOD RemoveFrame(ChildListID aListID,
|
|
nsIFrame* aOldFrame) MOZ_OVERRIDE;
|
|
|
|
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
|
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
|
|
|
/**
|
|
* Retrieve the available height for content of this frame. The available content
|
|
* height is the available height for the frame, minus borders and padding.
|
|
*/
|
|
virtual nscoord GetAvailableContentHeight(const nsHTMLReflowState& aReflowState);
|
|
|
|
virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
|
|
nsIFrame* frame = GetFirstPrincipalChild();
|
|
|
|
// if no children return nullptr
|
|
if (!frame)
|
|
return nullptr;
|
|
|
|
return frame->GetContentInsertionFrame();
|
|
}
|
|
|
|
virtual nsresult StealFrame(nsPresContext* aPresContext,
|
|
nsIFrame* aChild,
|
|
bool aForceNormal) MOZ_OVERRIDE
|
|
{ // nsColumnSetFrame keeps overflow containers in main child list
|
|
return nsContainerFrame::StealFrame(aPresContext, aChild, true);
|
|
}
|
|
|
|
virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
|
|
{
|
|
return nsContainerFrame::IsFrameOfType(aFlags &
|
|
~(nsIFrame::eCanContainOverflowContainers));
|
|
}
|
|
|
|
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
const nsRect& aDirtyRect,
|
|
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
|
|
|
|
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
|
|
|
virtual void PaintColumnRule(nsRenderingContext* aCtx,
|
|
const nsRect& aDirtyRect,
|
|
const nsPoint& aPt);
|
|
|
|
#ifdef DEBUG
|
|
NS_IMETHOD GetFrameName(nsAString& aResult) const MOZ_OVERRIDE {
|
|
return MakeFrameName(NS_LITERAL_STRING("ColumnSet"), aResult);
|
|
}
|
|
#endif
|
|
|
|
protected:
|
|
nscoord mLastBalanceHeight;
|
|
nsReflowStatus mLastFrameStatus;
|
|
|
|
/**
|
|
* These are the parameters that control the layout of columns.
|
|
*/
|
|
struct ReflowConfig {
|
|
// The number of columns that we want to balance across. If we're not
|
|
// balancing, this will be set to INT32_MAX.
|
|
int32_t mBalanceColCount;
|
|
|
|
// The width of each individual column.
|
|
nscoord mColWidth;
|
|
|
|
// The amount of width that is expected to be left over after all the
|
|
// columns and column gaps are laid out.
|
|
nscoord mExpectedWidthLeftOver;
|
|
|
|
// The width of each column gap.
|
|
nscoord mColGap;
|
|
|
|
// The maximum height of any individual column during a reflow iteration.
|
|
// This parameter is set during each iteration of the binary search for
|
|
// the best column height.
|
|
nscoord mColMaxHeight;
|
|
|
|
// A boolean controlling whether or not we are balancing. This should be
|
|
// equivalent to mBalanceColCount == INT32_MAX.
|
|
bool mIsBalancing;
|
|
|
|
// The last known column height that was 'feasible'. A column height is
|
|
// feasible if all child content fits within the specified height.
|
|
nscoord mKnownFeasibleHeight;
|
|
|
|
// The last known height that was 'infeasible'. A column height is
|
|
// infeasible if not all child content fits within the specified height.
|
|
nscoord mKnownInfeasibleHeight;
|
|
|
|
// Height of the column set frame
|
|
nscoord mComputedHeight;
|
|
|
|
// The height "consumed" by previous-in-flows.
|
|
// The computed height should be equal to the height of the element (i.e.
|
|
// the computed height itself) plus the consumed height.
|
|
nscoord mConsumedHeight;
|
|
};
|
|
|
|
/**
|
|
* Some data that is better calculated during reflow
|
|
*/
|
|
struct ColumnBalanceData {
|
|
// The maximum "content height" of any column
|
|
nscoord mMaxHeight;
|
|
// The sum of the "content heights" for all columns
|
|
nscoord mSumHeight;
|
|
// The "content height" of the last column
|
|
nscoord mLastHeight;
|
|
// The maximum "content height" of all columns that overflowed
|
|
// their available height
|
|
nscoord mMaxOverflowingHeight;
|
|
// This flag determines whether the last reflow of children exceeded the
|
|
// computed height of the column set frame. If so, we set the height to
|
|
// this maximum allowable height, and continue reflow without balancing.
|
|
bool mHasExcessHeight;
|
|
|
|
void Reset() {
|
|
mMaxHeight = mSumHeight = mLastHeight = mMaxOverflowingHeight = 0;
|
|
mHasExcessHeight = false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 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();
|
|
|
|
bool ReflowColumns(nsHTMLReflowMetrics& aDesiredSize,
|
|
const nsHTMLReflowState& aReflowState,
|
|
nsReflowStatus& aReflowStatus,
|
|
ReflowConfig& aConfig,
|
|
bool aLastColumnUnbounded,
|
|
nsCollapsingMargin* aCarriedOutBottomMargin,
|
|
ColumnBalanceData& aColData);
|
|
|
|
/**
|
|
* 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 nsHTMLReflowState& aReflowState,
|
|
bool aForceAuto, nscoord aFeasibleHeight,
|
|
nscoord aInfeasibleHeight);
|
|
|
|
/**
|
|
* Perform the binary search for the best balance height for this column set.
|
|
*
|
|
* @param aReflowState 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 aOutMargin The bottom margin of the column set frame that may be
|
|
* carried out from reflow (and thus collapsed).
|
|
* @param aUnboundedLastColumn A boolean value indicating that the last column
|
|
* can be of any height. Used during the first iteration of the
|
|
* balancing procedure to measure the height of all content in
|
|
* descendant frames of the column set.
|
|
* @param aRunWasFeasible An input/output parameter indicating whether or not
|
|
* the last iteration of the balancing loop was a feasible height to
|
|
* fit all content from descendant frames.
|
|
* @param aStatus A final reflow status of the column set frame, passed in as
|
|
* an output parameter.
|
|
*/
|
|
void FindBestBalanceHeight(const nsHTMLReflowState& aReflowState,
|
|
nsPresContext* aPresContext,
|
|
ReflowConfig& aConfig,
|
|
ColumnBalanceData& aColData,
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
nsCollapsingMargin& aOutMargin,
|
|
bool& aUnboundedLastColumn,
|
|
bool& aRunWasFeasible,
|
|
nsReflowStatus& aStatus);
|
|
/**
|
|
* Reflow column children. Returns true iff the content that was reflowed
|
|
* fit into the mColMaxHeight.
|
|
*/
|
|
bool ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
|
const nsHTMLReflowState& aReflowState,
|
|
nsReflowStatus& aStatus,
|
|
const ReflowConfig& aConfig,
|
|
bool aLastColumnUnbounded,
|
|
nsCollapsingMargin* aCarriedOutBottomMargin,
|
|
ColumnBalanceData& aColData);
|
|
};
|