зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1054046: Cache flex items' tentative cross size from reflow state, to avoid creating another reflow state later on just for that piece of information. r=mats
This commit is contained in:
Родитель
aef4530afb
Коммит
428b9cacfe
|
@ -263,6 +263,7 @@ public:
|
||||||
FlexItem(nsHTMLReflowState& aFlexItemReflowState,
|
FlexItem(nsHTMLReflowState& aFlexItemReflowState,
|
||||||
float aFlexGrow, float aFlexShrink, nscoord aMainBaseSize,
|
float aFlexGrow, float aFlexShrink, nscoord aMainBaseSize,
|
||||||
nscoord aMainMinSize, nscoord aMainMaxSize,
|
nscoord aMainMinSize, nscoord aMainMaxSize,
|
||||||
|
nscoord aTentativeCrossSize,
|
||||||
nscoord aCrossMinSize, nscoord aCrossMaxSize,
|
nscoord aCrossMinSize, nscoord aCrossMaxSize,
|
||||||
const FlexboxAxisTracker& aAxisTracker);
|
const FlexboxAxisTracker& aAxisTracker);
|
||||||
|
|
||||||
|
@ -984,9 +985,14 @@ nsFlexContainerFrame::GenerateFlexItemForChild(
|
||||||
// This is enforced by the nsHTMLReflowState where these values come from:
|
// This is enforced by the nsHTMLReflowState where these values come from:
|
||||||
MOZ_ASSERT(mainMinSize <= mainMaxSize, "min size is larger than max size");
|
MOZ_ASSERT(mainMinSize <= mainMaxSize, "min size is larger than max size");
|
||||||
|
|
||||||
// CROSS MIN/MAX SIZE
|
// CROSS SIZES (tentative cross size, min/max cross size)
|
||||||
// ------------------
|
// ------------------------------------------------------
|
||||||
|
// Grab the cross size from the reflow state. This might be the right value,
|
||||||
|
// or we might resolve it to something else in SizeItemInCrossAxis(); hence,
|
||||||
|
// it's tentative. See comment under "Cross Size Determination" for more.
|
||||||
|
nscoord tentativeCrossSize = GET_CROSS_COMPONENT(aAxisTracker,
|
||||||
|
childRS.ComputedWidth(),
|
||||||
|
childRS.ComputedHeight());
|
||||||
nscoord crossMinSize = GET_CROSS_COMPONENT(aAxisTracker,
|
nscoord crossMinSize = GET_CROSS_COMPONENT(aAxisTracker,
|
||||||
childRS.ComputedMinWidth(),
|
childRS.ComputedMinWidth(),
|
||||||
childRS.ComputedMinHeight());
|
childRS.ComputedMinHeight());
|
||||||
|
@ -1028,7 +1034,7 @@ nsFlexContainerFrame::GenerateFlexItemForChild(
|
||||||
// (Set min and max main-sizes to that size, too, to keep us from
|
// (Set min and max main-sizes to that size, too, to keep us from
|
||||||
// clamping to any other size later on.)
|
// clamping to any other size later on.)
|
||||||
flexBaseSize = mainMinSize = mainMaxSize = widgetMainMinSize;
|
flexBaseSize = mainMinSize = mainMaxSize = widgetMainMinSize;
|
||||||
crossMinSize = crossMaxSize = widgetCrossMinSize;
|
tentativeCrossSize = crossMinSize = crossMaxSize = widgetCrossMinSize;
|
||||||
isFixedSizeWidget = true;
|
isFixedSizeWidget = true;
|
||||||
} else {
|
} else {
|
||||||
// Variable-size widget: ensure our min/max sizes are at least as large
|
// Variable-size widget: ensure our min/max sizes are at least as large
|
||||||
|
@ -1036,6 +1042,9 @@ nsFlexContainerFrame::GenerateFlexItemForChild(
|
||||||
mainMinSize = std::max(mainMinSize, widgetMainMinSize);
|
mainMinSize = std::max(mainMinSize, widgetMainMinSize);
|
||||||
mainMaxSize = std::max(mainMaxSize, widgetMainMinSize);
|
mainMaxSize = std::max(mainMaxSize, widgetMainMinSize);
|
||||||
|
|
||||||
|
if (tentativeCrossSize != NS_INTRINSICSIZE) {
|
||||||
|
tentativeCrossSize = std::max(tentativeCrossSize, widgetCrossMinSize);
|
||||||
|
}
|
||||||
crossMinSize = std::max(crossMinSize, widgetCrossMinSize);
|
crossMinSize = std::max(crossMinSize, widgetCrossMinSize);
|
||||||
crossMaxSize = std::max(crossMaxSize, widgetCrossMinSize);
|
crossMaxSize = std::max(crossMaxSize, widgetCrossMinSize);
|
||||||
}
|
}
|
||||||
|
@ -1045,6 +1054,7 @@ nsFlexContainerFrame::GenerateFlexItemForChild(
|
||||||
FlexItem* item = new FlexItem(childRS,
|
FlexItem* item = new FlexItem(childRS,
|
||||||
flexGrow, flexShrink, flexBaseSize,
|
flexGrow, flexShrink, flexBaseSize,
|
||||||
mainMinSize, mainMaxSize,
|
mainMinSize, mainMaxSize,
|
||||||
|
tentativeCrossSize,
|
||||||
crossMinSize, crossMaxSize,
|
crossMinSize, crossMaxSize,
|
||||||
aAxisTracker);
|
aAxisTracker);
|
||||||
|
|
||||||
|
@ -1424,6 +1434,7 @@ nsFlexContainerFrame::
|
||||||
FlexItem::FlexItem(nsHTMLReflowState& aFlexItemReflowState,
|
FlexItem::FlexItem(nsHTMLReflowState& aFlexItemReflowState,
|
||||||
float aFlexGrow, float aFlexShrink, nscoord aFlexBaseSize,
|
float aFlexGrow, float aFlexShrink, nscoord aFlexBaseSize,
|
||||||
nscoord aMainMinSize, nscoord aMainMaxSize,
|
nscoord aMainMinSize, nscoord aMainMaxSize,
|
||||||
|
nscoord aTentativeCrossSize,
|
||||||
nscoord aCrossMinSize, nscoord aCrossMaxSize,
|
nscoord aCrossMinSize, nscoord aCrossMaxSize,
|
||||||
const FlexboxAxisTracker& aAxisTracker)
|
const FlexboxAxisTracker& aAxisTracker)
|
||||||
: mFrame(aFlexItemReflowState.frame),
|
: mFrame(aFlexItemReflowState.frame),
|
||||||
|
@ -1436,7 +1447,7 @@ FlexItem::FlexItem(nsHTMLReflowState& aFlexItemReflowState,
|
||||||
mCrossMinSize(aCrossMinSize),
|
mCrossMinSize(aCrossMinSize),
|
||||||
mCrossMaxSize(aCrossMaxSize),
|
mCrossMaxSize(aCrossMaxSize),
|
||||||
mMainPosn(0),
|
mMainPosn(0),
|
||||||
mCrossSize(0),
|
mCrossSize(aTentativeCrossSize),
|
||||||
mCrossPosn(0),
|
mCrossPosn(0),
|
||||||
mAscent(0),
|
mAscent(0),
|
||||||
mShareOfWeightSoFar(0.0f),
|
mShareOfWeightSoFar(0.0f),
|
||||||
|
@ -3249,17 +3260,17 @@ nsFlexContainerFrame::SizeItemInCrossAxis(
|
||||||
nsHTMLReflowState& aChildReflowState,
|
nsHTMLReflowState& aChildReflowState,
|
||||||
FlexItem& aItem)
|
FlexItem& aItem)
|
||||||
{
|
{
|
||||||
// In vertical flexbox (with horizontal cross-axis), we can just trust the
|
|
||||||
// reflow state's computed-width as our cross-size. We also don't need to
|
|
||||||
// record the baseline because we'll have converted any "align-self:baseline"
|
|
||||||
// items to be "align-self:flex-start" in the FlexItem constructor.
|
|
||||||
// FIXME: Once we support writing-mode (vertical text), we will be able to
|
|
||||||
// have baseline-aligned items in a vertical flexbox, and we'll need to
|
|
||||||
// record baseline information here.
|
|
||||||
if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) {
|
if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) {
|
||||||
MOZ_ASSERT(aItem.GetAlignSelf() != NS_STYLE_ALIGN_ITEMS_BASELINE,
|
// XXXdholbert NOTE: For now, we should never hit this case, due to a
|
||||||
"In vert flex container, we depend on FlexItem constructor to "
|
// !IsAxisHorizontal(aAxisTracker.GetCrossAxis()) check that guards this
|
||||||
"convert 'align-self: baseline' to 'align-self: flex-start'");
|
// call in the caller. BUT, when we add support for vertical writing-modes,
|
||||||
|
// (in bug 1079155 or a dependency), we'll relax that check, and we'll need
|
||||||
|
// to be able to measure the baseline & width (given our resolved height)
|
||||||
|
// of vertical-writing-mode flex items here.
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Caller should use tentative cross size instead "
|
||||||
|
"of calling SizeItemInCrossAxis");
|
||||||
|
// (But if we do happen to get here, just trust the passed-in reflow state
|
||||||
|
// for our cross size [width].)
|
||||||
aItem.SetCrossSize(aChildReflowState.ComputedWidth());
|
aItem.SetCrossSize(aChildReflowState.ComputedWidth());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3499,9 +3510,25 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
|
||||||
nscoord sumLineCrossSizes = 0;
|
nscoord sumLineCrossSizes = 0;
|
||||||
for (FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
|
for (FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
|
||||||
for (FlexItem* item = line->GetFirstItem(); item; item = item->getNext()) {
|
for (FlexItem* item = line->GetFirstItem(); item; item = item->getNext()) {
|
||||||
// (If the item's already been stretched, or it's a strut, then it
|
// Note that we may already have the correct cross size. (We guess at it
|
||||||
// already knows its cross size. Don't bother trying to recalculate it.)
|
// in GenerateFlexItemForChild(), and we also may resolve it early for
|
||||||
if (!item->IsStretched() && !item->IsStrut()) {
|
// stretched flex items.)
|
||||||
|
//
|
||||||
|
// We can skip measuring an item's cross size here in a few scenarios:
|
||||||
|
// (A) If the flex item has already been stretched, then we're imposing
|
||||||
|
// the container's cross size on it; no need to measure.
|
||||||
|
// (B) If the flex item is a "strut", then it's just a placeholder with a
|
||||||
|
// predetermined cross size; no need to measure.
|
||||||
|
// (C) If the item's main-size can't affect its cross-size, then the
|
||||||
|
// item's tentative cross size (which we got from the reflow state in
|
||||||
|
// GenerateFlexItemForChild()) is correct. So, no need to re-measure.
|
||||||
|
// (For now, this is equivalent to checking if the cross-axis is
|
||||||
|
// horizontal, because until we enable vertical writing-modes, an
|
||||||
|
// element's computed width can't be influenced by its computed
|
||||||
|
// height.)
|
||||||
|
if (!item->IsStretched() && // !A
|
||||||
|
!item->IsStrut() && // !B
|
||||||
|
!IsAxisHorizontal(aAxisTracker.GetCrossAxis())) { // !C
|
||||||
WritingMode wm = item->Frame()->GetWritingMode();
|
WritingMode wm = item->Frame()->GetWritingMode();
|
||||||
LogicalSize availSize = aReflowState.ComputedSize(wm);
|
LogicalSize availSize = aReflowState.ComputedSize(wm);
|
||||||
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
||||||
|
@ -3511,6 +3538,10 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
|
||||||
if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) {
|
if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) {
|
||||||
childReflowState.SetComputedWidth(item->GetMainSize());
|
childReflowState.SetComputedWidth(item->GetMainSize());
|
||||||
} else {
|
} else {
|
||||||
|
// XXXdholbert NOTE: For now, we'll never hit this case, due to the
|
||||||
|
// !IsAxisHorizontal(aAxisTracker.GetCrossAxis()) check above. But
|
||||||
|
// when we add support for vertical writing modes, we'll relax that
|
||||||
|
// check and be able to hit this code.
|
||||||
childReflowState.SetComputedHeight(item->GetMainSize());
|
childReflowState.SetComputedHeight(item->GetMainSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче