Bug 1174553 part 3 - [css-grid] Implement the 'min-content' / 'max-content' sizing functions in layout. r=dholbert

This commit is contained in:
Mats Palmgren 2015-09-04 22:06:57 +02:00
parent c80456a8fb
commit 548b396dbb
7 changed files with 113 additions and 10 deletions

View File

@ -1599,7 +1599,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
aMetrics.SetSize(wm, finalSize);
#ifdef DEBUG_blocks
if (CRAZY_SIZE(aMetrics.Width()) || CRAZY_SIZE(aMetrics.Height())) {
if ((CRAZY_SIZE(aMetrics.Width()) || CRAZY_SIZE(aMetrics.Height())) &&
!GetParent()->IsCrazySizeAssertSuppressed()) {
ListTag(stdout);
printf(": WARNING: desired:%d,%d\n", aMetrics.Width(), aMetrics.Height());
}
@ -4411,7 +4412,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
#ifdef DEBUG
{
if (!GetParent()->IsCrazySizeAssertSuppressed()) {
static nscoord lastHeight = 0;
if (CRAZY_SIZE(aLine->BStart())) {
lastHeight = aLine->BStart();

View File

@ -308,8 +308,9 @@ nsBlockReflowContext::ReflowBlock(const LogicalRect& aSpace,
#ifdef DEBUG
if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
if (CRAZY_SIZE(mMetrics.ISize(mWritingMode)) ||
CRAZY_SIZE(mMetrics.BSize(mWritingMode))) {
if ((CRAZY_SIZE(mMetrics.ISize(mWritingMode)) ||
CRAZY_SIZE(mMetrics.BSize(mWritingMode))) &&
!mFrame->GetParent()->IsCrazySizeAssertSuppressed()) {
printf("nsBlockReflowContext: ");
nsFrame::ListTag(stdout, mFrame);
printf(" metrics=%d,%d!\n",

View File

@ -455,6 +455,14 @@ public:
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(ExcessOverflowContainersProperty)
#ifdef DEBUG
// Use this to suppress the CRAZY_SIZE assertions.
NS_DECLARE_FRAME_PROPERTY(DebugReflowingWithInfiniteISize, nullptr)
bool IsCrazySizeAssertSuppressed() const {
return Properties().Get(DebugReflowingWithInfiniteISize()) != nullptr;
}
#endif
protected:
explicit nsContainerFrame(nsStyleContext* aContext) : nsSplittableFrame(aContext) {}
~nsContainerFrame();

View File

@ -1268,6 +1268,85 @@ MinSize(nsIFrame* aChild, nsRenderingContext* aRC, WritingMode aCBWM,
return nsLayoutUtils::MinSizeContributionForAxis(axis, aRC, aChild,
aConstraint);
}
/**
* Return the [min|max]-content contribution of aChild to its parent (i.e.
* the child's margin-box) in aDimension.
*/
static nscoord
ContentContribution(nsIFrame* aChild,
const nsHTMLReflowState* aReflowState,
nsRenderingContext* aRC,
WritingMode aCBWM,
nsGridContainerFrame::Dimension aDimension,
nsLayoutUtils::IntrinsicISizeType aConstraint)
{
PhysicalAxis axis(((aDimension == nsGridContainerFrame::eColDimension) ==
aCBWM.IsVertical()) ? eAxisVertical : eAxisHorizontal);
nscoord size = nsLayoutUtils::IntrinsicForAxis(axis, aRC, aChild, aConstraint,
nsLayoutUtils::BAIL_IF_REFLOW_NEEDED);
if (size == NS_INTRINSIC_WIDTH_UNKNOWN) {
// We need to reflow the child to find its BSize contribution.
WritingMode wm = aChild->GetWritingMode();
nsContainerFrame* parent = aChild->GetParent();
nsPresContext* pc = aChild->PresContext();
Maybe<nsHTMLReflowState> dummyParentState;
const nsHTMLReflowState* rs = aReflowState;
if (!aReflowState) {
MOZ_ASSERT(!parent->HasAnyStateBits(NS_FRAME_IN_REFLOW));
dummyParentState.emplace(pc, parent, aRC,
LogicalSize(parent->GetWritingMode(), 0,
NS_UNCONSTRAINEDSIZE),
nsHTMLReflowState::DUMMY_PARENT_REFLOW_STATE);
rs = dummyParentState.ptr();
}
#ifdef DEBUG
// This will suppress various CRAZY_SIZE warnings for this reflow.
parent->Properties().Set(nsContainerFrame::DebugReflowingWithInfiniteISize(),
parent /* anything non-null will do */);
#endif
// XXX this will give mostly correct results for now (until bug 1174569).
LogicalSize availableSize(wm, INFINITE_ISIZE_COORD, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState childRS(pc, *rs, aChild, availableSize);
nsHTMLReflowMetrics childSize(childRS);
nsReflowStatus childStatus;
const uint32_t flags = NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW;
parent->ReflowChild(aChild, pc, childSize, childRS, wm,
LogicalPoint(wm), nsSize(), flags, childStatus);
parent->FinishReflowChild(aChild, pc, childSize, &childRS, wm,
LogicalPoint(wm), nsSize(), flags);
size = childSize.BSize(wm);
nsIFrame::IntrinsicISizeOffsetData offsets = aChild->IntrinsicBSizeOffsets();
size += offsets.hMargin;
size = nsLayoutUtils::AddPercents(aConstraint, size, offsets.hPctMargin);
#ifdef DEBUG
parent->Properties().Delete(nsContainerFrame::DebugReflowingWithInfiniteISize());
#endif
}
return std::max(size, 0);
}
static nscoord
MinContentContribution(nsIFrame* aChild,
const nsHTMLReflowState* aRS,
nsRenderingContext* aRC,
WritingMode aCBWM,
nsGridContainerFrame::Dimension aDimension)
{
return ContentContribution(aChild, aRS, aRC, aCBWM, aDimension,
nsLayoutUtils::MIN_ISIZE);
}
static nscoord
MaxContentContribution(nsIFrame* aChild,
const nsHTMLReflowState* aRS,
nsRenderingContext* aRC,
WritingMode aCBWM,
nsGridContainerFrame::Dimension aDimension)
{
return ContentContribution(aChild, aRS, aRC, aCBWM, aDimension,
nsLayoutUtils::PREF_ISIZE);
}
#endif
void

View File

@ -54,6 +54,9 @@ public:
nscoord mLimit;
};
// @note when used in a function that measures a child's size, eColDimension
// means we're calculating the child's contribution to the column sizing.
// (i.e. the child's inline size if its 'writing-mode' is horizontal)
enum Dimension { eColDimension, eRowDimension };
// @see nsAbsoluteContainingBlock::Reflow about this magic number

View File

@ -149,6 +149,12 @@ typedef uint32_t nsSplittableType;
// if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
// at least update AdjustComputedHeight/Width and test ad nauseum
// 1 million CSS pixels less than our max app unit measure.
// For reflowing with an "infinite" available inline space per [css-sizing].
// (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
// and leads to assertions)
#define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000*60))
//----------------------------------------------------------------------
enum nsSelectionAmount {

View File

@ -160,12 +160,14 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord,
"very large sizes, not attempts at intrinsic width "
"calculation");
#ifdef DEBUG
if ((aISize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aISize)) {
if ((aISize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aISize) &&
!LineContainerFrame()->GetParent()->IsCrazySizeAssertSuppressed()) {
nsFrame::ListTag(stdout, mBlockReflowState->frame);
printf(": Init: bad caller: width WAS %d(0x%x)\n",
aISize, aISize);
}
if ((aBSize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aBSize)) {
if ((aBSize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aBSize) &&
!LineContainerFrame()->GetParent()->IsCrazySizeAssertSuppressed()) {
nsFrame::ListTag(stdout, mBlockReflowState->frame);
printf(": Init: bad caller: height WAS %d(0x%x)\n",
aBSize, aBSize);
@ -327,13 +329,15 @@ nsLineLayout::UpdateBand(WritingMode aWM,
#endif
#ifdef DEBUG
if ((availSpace.ISize(lineWM) != NS_UNCONSTRAINEDSIZE) &&
CRAZY_SIZE(availSpace.ISize(lineWM))) {
CRAZY_SIZE(availSpace.ISize(lineWM)) &&
!LineContainerFrame()->GetParent()->IsCrazySizeAssertSuppressed()) {
nsFrame::ListTag(stdout, mBlockReflowState->frame);
printf(": UpdateBand: bad caller: ISize WAS %d(0x%x)\n",
availSpace.ISize(lineWM), availSpace.ISize(lineWM));
}
if ((availSpace.BSize(lineWM) != NS_UNCONSTRAINEDSIZE) &&
CRAZY_SIZE(availSpace.BSize(lineWM))) {
CRAZY_SIZE(availSpace.BSize(lineWM)) &&
!LineContainerFrame()->GetParent()->IsCrazySizeAssertSuppressed()) {
nsFrame::ListTag(stdout, mBlockReflowState->frame);
printf(": UpdateBand: bad caller: BSize WAS %d(0x%x)\n",
availSpace.BSize(lineWM), availSpace.BSize(lineWM));
@ -1045,8 +1049,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
// Note: break-before means ignore the reflow metrics since the
// frame will be reflowed another time.
if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
if (CRAZY_SIZE(metrics.ISize(lineWM)) ||
CRAZY_SIZE(metrics.BSize(lineWM))) {
if ((CRAZY_SIZE(metrics.ISize(lineWM)) ||
CRAZY_SIZE(metrics.BSize(lineWM))) &&
!LineContainerFrame()->GetParent()->IsCrazySizeAssertSuppressed()) {
printf("nsLineLayout: ");
nsFrame::ListTag(stdout, aFrame);
printf(" metrics=%d,%d!\n", metrics.Width(), metrics.Height());