Bug 1152913 part 3: Make flexbox's PositionTracker classes track whether axis is reversed, & directly convert flex item final sizes/positions to logical coords. r=mats

This commit is contained in:
Daniel Holbert 2015-04-16 12:01:14 -07:00
parent ff13e8c018
commit e3066d1874

View File

@ -226,36 +226,58 @@ public:
/**
* Converts a "flex-relative" point (a main-axis & cross-axis coordinate)
* into a "physical" x,y point.
*
* In the simplest case where the main-axis is left-to-right and the
* cross-axis is top-to-bottom, this just returns
* nsPoint(aMainCoord, aCrossCoord).
* into a LogicalPoint, using the flex container's writing mode.
*
* @arg aMainCoord The main-axis coordinate -- i.e an offset from the
* main-start edge of the container's content box.
* main-start edge of the flex container's content box.
* @arg aCrossCoord The cross-axis coordinate -- i.e an offset from the
* cross-start edge of the container's content box.
* @return A nsPoint representing the same position (in coordinates
* relative to the container's content box).
* cross-start edge of the flex container's content box.
* @arg aContainerMainSize The main size of flex container's content box.
* @arg aContainerCrossSize The cross size of flex container's content box.
* @return A LogicalPoint, with the flex container's writing mode, that
* represents the same position. The logical coordinates are
* relative to the flex container's content box.
*/
nsPoint PhysicalPointFromFlexRelativePoint(nscoord aMainCoord,
nscoord aCrossCoord,
nscoord aContainerMainSize,
nscoord aContainerCrossSize) const {
nscoord physicalCoordInMainAxis =
PhysicalCoordFromFlexRelativeCoord(aMainCoord, aContainerMainSize,
mMainAxis);
nscoord physicalCoordInCrossAxis =
PhysicalCoordFromFlexRelativeCoord(aCrossCoord, aContainerCrossSize,
mCrossAxis);
LogicalPoint
LogicalPointFromFlexRelativePoint(nscoord aMainCoord,
nscoord aCrossCoord,
nscoord aContainerMainSize,
nscoord aContainerCrossSize) const {
nscoord logicalCoordInMainAxis = mIsMainAxisReversed ?
aContainerMainSize - aMainCoord : aMainCoord;
nscoord logicalCoordInCrossAxis = mIsCrossAxisReversed ?
aContainerCrossSize - aCrossCoord : aCrossCoord;
return IsMainAxisHorizontal() ?
nsPoint(physicalCoordInMainAxis, physicalCoordInCrossAxis) :
nsPoint(physicalCoordInCrossAxis, physicalCoordInMainAxis);
return mIsRowOriented ?
LogicalPoint(mWM, logicalCoordInMainAxis, logicalCoordInCrossAxis) :
LogicalPoint(mWM, logicalCoordInCrossAxis, logicalCoordInMainAxis);
}
/**
* Converts a "flex-relative" size (a main-axis & cross-axis size)
* into a LogicalSize, using the flex container's writing mode.
*
* @arg aMainSize The main-axis size.
* @arg aCrossSize The cross-axis size.
* @return A LogicalSize, with the flex container's writing mode, that
* represents the same size.
*/
LogicalSize LogicalSizeFromFlexRelativeSizes(nscoord aMainSize,
nscoord aCrossSize) const {
return mIsRowOriented ?
LogicalSize(mWM, aMainSize, aCrossSize) :
LogicalSize(mWM, aCrossSize, aMainSize);
}
/**
* Converts a "flex-relative" size (a main-axis & cross-axis size)
* into nsSize (using physical coordinates).
*
* @arg aMainSize The main-axis size.
* @arg aCrossSize The cross-axis size.
* @return A nsSize that represents the same size, using the corresponding
* physical coordinates.
*/
nsSize PhysicalSizeFromFlexRelativeSizes(nscoord aMainSize,
nscoord aCrossSize) const {
return IsMainAxisHorizontal() ?
@ -1733,28 +1755,32 @@ public:
// Advances our current position from the start side of a child frame's
// border-box to the frame's upper or left edge (depending on our axis).
// (Note that this is a no-op if our axis grows in positive direction.)
// (Note that this is a no-op if our axis grows in the same direction as
// the corresponding logical axis.)
void EnterChildFrame(nscoord aChildFrameSize)
{
if (!AxisGrowsInPositiveDirection(mAxis))
if (mIsAxisReversed) {
mPosition += aChildFrameSize;
}
}
// Advances our current position from a frame's upper or left border-box edge
// (whichever is in the axis we're tracking) to the 'end' side of the frame
// in the axis that we're tracking. (Note that this is a no-op if our axis
// grows in the negative direction.)
// is reversed with respect to the corresponding logical axis.)
void ExitChildFrame(nscoord aChildFrameSize)
{
if (AxisGrowsInPositiveDirection(mAxis))
if (!mIsAxisReversed) {
mPosition += aChildFrameSize;
}
}
protected:
// Protected constructor, to be sure we're only instantiated via a subclass.
explicit PositionTracker(AxisOrientationType aAxis)
PositionTracker(AxisOrientationType aAxis, bool aIsAxisReversed)
: mPosition(0),
mAxis(aAxis)
mAxis(aAxis),
mIsAxisReversed(aIsAxisReversed)
{}
// Delete copy-constructor & reassignment operator, to prevent accidental
@ -1764,7 +1790,12 @@ protected:
// Member data:
nscoord mPosition; // The position we're tracking
const AxisOrientationType mAxis; // The axis along which we're moving
// XXXdholbert [BEGIN DEPRECATED]
const AxisOrientationType mAxis; // The axis along which we're moving.
// XXXdholbert [END DEPRECATED]
const bool mIsAxisReversed; // Is the axis along which we're moving reversed
// (e.g. LTR vs RTL) with respect to the
// corresponding axis on the flex container's WM?
};
// Tracks our position in the main axis, when we're laying out flex items.
@ -2383,7 +2414,8 @@ MainAxisPositionTracker::
const FlexLine* aLine,
uint8_t aJustifyContent,
nscoord aContentBoxMainSize)
: PositionTracker(aAxisTracker.GetMainAxis()),
: PositionTracker(aAxisTracker.GetMainAxis(),
aAxisTracker.IsMainAxisReversed()),
mPackingSpaceRemaining(aContentBoxMainSize), // we chip away at this below
mNumAutoMarginsInMainAxis(0),
mNumPackingSpacesRemaining(0),
@ -2534,7 +2566,8 @@ CrossAxisPositionTracker::
nscoord aContentBoxCrossSize,
bool aIsCrossSizeDefinite,
const FlexboxAxisTracker& aAxisTracker)
: PositionTracker(aAxisTracker.GetCrossAxis()),
: PositionTracker(aAxisTracker.GetCrossAxis(),
aAxisTracker.IsCrossAxisReversed()),
mPackingSpaceRemaining(0),
mNumPackingSpacesRemaining(0),
mAlignContent(aAlignContent)
@ -2687,7 +2720,8 @@ CrossAxisPositionTracker::TraversePackingSpace()
SingleLineCrossAxisPositionTracker::
SingleLineCrossAxisPositionTracker(const FlexboxAxisTracker& aAxisTracker)
: PositionTracker(aAxisTracker.GetCrossAxis())
: PositionTracker(aAxisTracker.GetCrossAxis(),
aAxisTracker.IsCrossAxisReversed())
{
}
@ -3733,49 +3767,55 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
// Before giving each child a final reflow, calculate the origin of the
// flex container's content box (with respect to its border-box), so that
// we can compute our flex item's final positions.
nsMargin containerBorderPadding(aReflowState.ComputedPhysicalBorderPadding());
containerBorderPadding.ApplySkipSides(GetSkipSides(&aReflowState));
const nsPoint containerContentBoxOrigin(containerBorderPadding.left,
containerBorderPadding.top);
WritingMode outerWM = aReflowState.GetWritingMode();
WritingMode flexWM = aReflowState.GetWritingMode();
LogicalMargin containerBP = aReflowState.ComputedLogicalBorderPadding();
// Unconditionally skip block-end border & padding for now, regardless of
// writing-mode/GetLogicalSkipSides. We add it lower down, after we've
// established baseline and decided whether bottom border-padding fits (if
// we're fragmented).
const LogicalSides skipSides =
GetLogicalSkipSides(&aReflowState) | LogicalSides(eLogicalSideBitsBEnd);
containerBP.ApplySkipSides(skipSides);
const LogicalPoint containerContentBoxOrigin(flexWM,
containerBP.IStart(flexWM),
containerBP.BStart(flexWM));
nscoord containerWidth = aAxisTracker.IsMainAxisHorizontal() ?
aContentBoxMainSize : contentBoxCrossSize;
containerWidth += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
// FINAL REFLOW: Give each child frame another chance to reflow, now that
// we know its final size and position.
for (const FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
for (const FlexItem* item = line->GetFirstItem(); item;
item = item->getNext()) {
nsPoint physicalPosn = aAxisTracker.PhysicalPointFromFlexRelativePoint(
LogicalPoint framePos = aAxisTracker.LogicalPointFromFlexRelativePoint(
item->GetMainPosition(),
item->GetCrossPosition(),
aContentBoxMainSize,
contentBoxCrossSize);
// Adjust physicalPosn to be relative to the container's border-box
// Adjust framePos to be relative to the container's border-box
// (i.e. its frame rect), instead of the container's content-box:
physicalPosn += containerContentBoxOrigin;
//XXX Can we calculate the logical position more directly instead
// of this double conversion?
nsSize finalFlexedPhysicalSize =
aAxisTracker.PhysicalSizeFromFlexRelativeSizes(item->GetMainSize(),
item->GetCrossSize());
LogicalPoint framePos(outerWM, physicalPosn,
containerWidth - finalFlexedPhysicalSize.width -
item->GetBorderPadding().LeftRight());
framePos += containerContentBoxOrigin;
// (Intentionally snapshotting this before ApplyRelativePositioning, to
// maybe use for setting the flex container's baseline.)
const nscoord itemNormalBPos = framePos.B(outerWM);
const nscoord itemNormalBPos = framePos.B(flexWM);
// Check if we actually need to reflow the item -- if we already reflowed
// it with the right size, we can just reposition it as-needed.
bool itemNeedsReflow = true; // (Start out assuming the worst.)
if (item->HadMeasuringReflow()) {
LogicalSize finalFlexItemCBSize =
aAxisTracker.LogicalSizeFromFlexRelativeSizes(item->GetMainSize(),
item->GetCrossSize());
// We've already reflowed the child once. Was the size we gave it in
// that reflow the same as its final (post-flexing/stretching) size?
if (finalFlexedPhysicalSize ==
item->Frame()->GetContentRectRelativeToSelf().Size()) {
if (finalFlexItemCBSize ==
LogicalSize(flexWM,
item->Frame()->GetContentRectRelativeToSelf().Size())) {
// Even if our size hasn't changed, some of our descendants might
// care that our height is now considered "definite" (whereas it
// wasn't in our previous "measuring" reflow), if they have a
@ -3806,6 +3846,11 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
}
}
// XXXdholbert preserving the physical-coords var "containerBorderPadding"
// for now, while it has usages; removing it & its usages in bug 1155312.
nsMargin containerBorderPadding(aReflowState.ComputedPhysicalBorderPadding());
containerBorderPadding.ApplySkipSides(GetSkipSides(&aReflowState));
nsSize desiredContentBoxSize =
aAxisTracker.PhysicalSizeFromFlexRelativeSizes(aContentBoxMainSize,
contentBoxCrossSize);