Bug 666041 patch 7: implementation of flex container class for CSS3 flexbox. r=dbaron

This commit is contained in:
Daniel Holbert 2012-09-29 23:38:46 -07:00
parent 3544930bb5
commit bd68c21394
5 changed files with 2289 additions and 16 deletions

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@
#define nsFlexContainerFrame_h___
#include "nsContainerFrame.h"
#include "nsTArray.h"
#include "mozilla/Types.h"
nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
@ -18,6 +19,11 @@ nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
typedef nsContainerFrame nsFlexContainerFrameSuper;
class FlexItem;
class FlexboxAxisTracker;
class MainAxisPositionTracker;
class SingleLineCrossAxisPositionTracker;
class nsFlexContainerFrame : public nsFlexContainerFrameSuper {
NS_DECL_FRAMEARENA_HELPERS
NS_DECL_QUERYFRAME_TARGET(nsFlexContainerFrame)
@ -27,20 +33,89 @@ class nsFlexContainerFrame : public nsFlexContainerFrameSuper {
friend nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
public:
// nsIFrame overrides
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus) MOZ_OVERRIDE;
virtual nscoord
GetMinWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE;
virtual nscoord
GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE;
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
#endif
#endif // DEBUG
// Flexbox-specific public methods
bool IsHorizontal();
protected:
// Protected constructor & destructor
nsFlexContainerFrame(nsStyleContext* aContext) : nsFlexContainerFrameSuper(aContext) {}
nsFlexContainerFrame(nsStyleContext* aContext) :
nsFlexContainerFrameSuper(aContext),
mCachedContentBoxCrossSize(nscoord_MIN),
mCachedAscent(nscoord_MIN)
{}
virtual ~nsFlexContainerFrame();
// Protected nsIFrame overrides:
virtual void DestroyFrom(nsIFrame* aDestructRoot);
// Protected flex-container-specific methods / member-vars
#ifdef DEBUG
void SanityCheckAnonymousFlexItems() const;
#endif // DEBUG
// Returns nsresult because we might have to reflow aChildFrame (to get its
// vertical intrinsic size in a vertical flexbox), and if that reflow fails
// (returns a failure nsresult), we want to bail out.
nsresult AppendFlexItemForChild(nsPresContext* aPresContext,
nsIFrame* aChildFrame,
const nsHTMLReflowState& aParentReflowState,
const FlexboxAxisTracker& aAxisTracker,
nsTArray<FlexItem>& aFlexItems);
// Runs the "resolve the flexible lengths" algorithm, distributing
// |aFlexContainerMainSize| among the |aItems| and freezing them.
void ResolveFlexibleLengths(const FlexboxAxisTracker& aAxisTracker,
nscoord aFlexContainerMainSize,
nsTArray<FlexItem>& aItems);
nsresult GenerateFlexItems(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
const FlexboxAxisTracker& aAxisTracker,
nsTArray<FlexItem>& aItems);
nscoord ComputeFlexContainerMainSize(const nsHTMLReflowState& aReflowState,
const FlexboxAxisTracker& aAxisTracker,
const nsTArray<FlexItem>& aFlexItems);
void PositionItemInMainAxis(MainAxisPositionTracker& aMainAxisPosnTracker,
FlexItem& aItem);
nsresult SizeItemInCrossAxis(nsPresContext* aPresContext,
const FlexboxAxisTracker& aAxisTracker,
const nsHTMLReflowState& aChildReflowState,
FlexItem& aItem);
void PositionItemInCrossAxis(
nscoord aLineStartPosition,
SingleLineCrossAxisPositionTracker& aLineCrossAxisPosnTracker,
FlexItem& aItem);
// Cached values from running flexbox layout algorithm, used in setting our
// reflow metrics w/out actually reflowing all of our children, in any
// reflows where we're not dirty:
nscoord mCachedContentBoxCrossSize; // cross size of our content-box size
nscoord mCachedAscent; // our ascent, in prev. reflow.
};
#endif /* nsFlexContainerFrame_h___ */

View File

@ -22,9 +22,7 @@ FRAME_ID(nsFieldSetFrame)
FRAME_ID(nsFileControlFrame)
FRAME_ID(nsFirstLetterFrame)
FRAME_ID(nsFirstLineFrame)
#ifdef MOZ_FLEXBOX
FRAME_ID(nsFlexContainerFrame)
#endif // MOZ_FLEXBOX
FRAME_ID(nsFormControlFrame)
FRAME_ID(nsFrame)
FRAME_ID(nsGfxButtonControlFrame)

View File

@ -16,6 +16,7 @@
#include "nsFontMetrics.h"
#include "nsBlockFrame.h"
#include "nsLineBox.h"
#include "nsFlexContainerFrame.h"
#include "nsImageFrame.h"
#include "nsTableFrame.h"
#include "nsTableCellFrame.h"
@ -687,6 +688,9 @@ nsHTMLReflowState::InitFrameType(nsIAtom* aFrameType)
case NS_STYLE_DISPLAY_LIST_ITEM:
case NS_STYLE_DISPLAY_TABLE:
case NS_STYLE_DISPLAY_TABLE_CAPTION:
#ifdef MOZ_FLEXBOX
case NS_STYLE_DISPLAY_FLEX:
#endif // MOZ_FLEXBOX
frameType = NS_CSS_FRAME_TYPE_BLOCK;
break;
@ -696,6 +700,9 @@ nsHTMLReflowState::InitFrameType(nsIAtom* aFrameType)
case NS_STYLE_DISPLAY_INLINE_BOX:
case NS_STYLE_DISPLAY_INLINE_GRID:
case NS_STYLE_DISPLAY_INLINE_STACK:
#ifdef MOZ_FLEXBOX
case NS_STYLE_DISPLAY_INLINE_FLEX:
#endif // MOZ_FLEXBOX
frameType = NS_CSS_FRAME_TYPE_INLINE;
break;
@ -1799,6 +1806,20 @@ IsSideCaption(nsIFrame* aFrame, const nsStyleDisplay* aStyleDisplay)
captionSide == NS_STYLE_CAPTION_SIDE_RIGHT;
}
#ifdef MOZ_FLEXBOX
static nsFlexContainerFrame*
GetFlexContainer(nsIFrame* aFrame)
{
nsIFrame* parent = aFrame->GetParent();
if (!parent ||
parent->GetType() != nsGkAtoms::flexContainerFrame) {
return nullptr;
}
return static_cast<nsFlexContainerFrame*>(parent);
}
#endif // MOZ_FLEXBOX
// XXX refactor this code to have methods for each set of properties
// we are computing: width,height,line-height; margin; offsets
@ -2010,11 +2031,22 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
computeSizeFlags |= nsIFrame::eShrinkWrap;
}
// If we're inside of a flexbox that needs to measure our auto height,
// pass that information along to ComputeSize().
if (mFlags.mIsFlexContainerMeasuringHeight) {
computeSizeFlags |= nsIFrame::eUseAutoHeight;
#ifdef MOZ_FLEXBOX
const nsFlexContainerFrame* flexContainerFrame = GetFlexContainer(frame);
if (flexContainerFrame) {
computeSizeFlags |= nsIFrame::eShrinkWrap;
// If we're inside of a flex container that needs to measure our
// auto height, pass that information along to ComputeSize().
if (mFlags.mIsFlexContainerMeasuringHeight) {
computeSizeFlags |= nsIFrame::eUseAutoHeight;
}
} else {
MOZ_ASSERT(!mFlags.mIsFlexContainerMeasuringHeight,
"We're not in a flex container, so the flag "
"'mIsFlexContainerMeasuringHeight' shouldn't be set");
}
#endif // MOZ_FLEXBOX
nsSize size =
frame->ComputeSize(rendContext,
@ -2037,9 +2069,14 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
NS_ASSERTION(mComputedHeight == NS_UNCONSTRAINEDSIZE ||
mComputedHeight >= 0, "Bogus height");
// Exclude inline tables from the block margin calculations
if (isBlock && !IsSideCaption(frame, mStyleDisplay) &&
frame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE)
// Exclude inline tables and flex items from the block margin calculations
if (isBlock &&
!IsSideCaption(frame, mStyleDisplay) &&
mStyleDisplay->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE
#ifdef MOZ_FLEXBOX
&& !flexContainerFrame
#endif // MOZ_FLEXBOX
)
CalculateBlockSideMargins(availableWidth, mComputedWidth, aFrameType);
}
}

View File

@ -41,6 +41,7 @@
page-break-after: inherit;
vertical-align: inherit; /* needed for inline-table */
line-height: inherit; /* needed for vertical-align on inline-table */
-moz-align-self: inherit; /* needed for "align-self: auto" to work on table */
/* Bug 722777 */
-moz-transform: inherit;
-moz-transform-origin: inherit;