mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 789096 patch 8: use logical coordinates in nsBlockReflowState. r=jfkthame
This commit is contained in:
parent
50badd6444
commit
82f2df73ba
File diff suppressed because it is too large
Load Diff
@ -232,36 +232,34 @@ public:
|
||||
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsRect ComputeTightBounds(gfxContext* aContext) const MOZ_OVERRIDE;
|
||||
|
||||
|
||||
virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Compute the final height of this frame.
|
||||
* Compute the final block size of this frame.
|
||||
*
|
||||
* @param aReflowState Data structure passed from parent during reflow.
|
||||
* @param aReflowStatus A pointed to the reflow status for when we're finished
|
||||
* doing reflow. this will get set appropriately if the height causes
|
||||
* us to exceed the current available (page) height.
|
||||
* @param aContentHeight The height of content, precomputed outside of this
|
||||
* function. The final height that is used in aMetrics will be set to
|
||||
* either this or the available height, whichever is larger, in the
|
||||
* case where our available height is constrained, and we overflow that
|
||||
* available height.
|
||||
* @param aReflowStatus A pointer to the reflow status for when we're finished
|
||||
* doing reflow. this will get set appropriately if the block-size
|
||||
* causes us to exceed the current available (page) block-size.
|
||||
* @param aContentBSize The block-size of content, precomputed outside of this
|
||||
* function. The final block-size that is used in aMetrics will be set
|
||||
* to either this or the available block-size, whichever is larger, in
|
||||
* the case where our available block-size is constrained, and we
|
||||
* overflow that available block-size.
|
||||
* @param aBorderPadding The margins representing the border padding for block
|
||||
* frames. Can be 0.
|
||||
* @param aMetrics Out parameter for final height. Taken as an
|
||||
* nsHTMLReflowMetrics object so that aMetrics can be passed in
|
||||
* directly during reflow.
|
||||
* @param aConsumed The height already consumed by our previous-in-flows.
|
||||
* @param aFinalSize Out parameter for final block-size.
|
||||
* @param aConsumed The block-size already consumed by our previous-in-flows.
|
||||
*/
|
||||
void ComputeFinalHeight(const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus* aStatus,
|
||||
nscoord aContentHeight,
|
||||
const nsMargin& aBorderPadding,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nscoord aConsumed);
|
||||
void ComputeFinalBSize(const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus* aStatus,
|
||||
nscoord aContentBSize,
|
||||
const mozilla::LogicalMargin& aBorderPadding,
|
||||
mozilla::LogicalSize& aFinalSize,
|
||||
nscoord aConsumed);
|
||||
|
||||
virtual void Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -297,14 +295,14 @@ public:
|
||||
* line includes the margin-top of a line with clearance (in which
|
||||
* case we must avoid collapsing that margin with our bottom margin)
|
||||
*/
|
||||
bool CheckForCollapsedBottomMarginFromClearanceLine();
|
||||
bool CheckForCollapsedBEndMarginFromClearanceLine();
|
||||
|
||||
static nsresult GetCurrentLine(nsBlockReflowState *aState, nsLineBox **aOutCurrentLine);
|
||||
|
||||
/**
|
||||
* Determine if this block is a margin root at the top/bottom edges.
|
||||
*/
|
||||
void IsMarginRoot(bool* aTopMarginRoot, bool* aBottomMarginRoot);
|
||||
void IsMarginRoot(bool* aBStartMarginRoot, bool* aBEndMarginRoot);
|
||||
|
||||
static bool BlockNeedsFloatManager(nsIFrame* aBlock);
|
||||
|
||||
@ -638,8 +636,8 @@ protected:
|
||||
//----------------------------------------
|
||||
// Methods for individual frame reflow
|
||||
|
||||
bool ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine);
|
||||
bool ShouldApplyBStartMargin(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine);
|
||||
|
||||
void ReflowBlockFrame(nsBlockReflowState& aState,
|
||||
line_iterator aLine,
|
||||
|
@ -27,37 +27,41 @@ using namespace mozilla::layout;
|
||||
nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
nsPresContext* aPresContext,
|
||||
nsBlockFrame* aFrame,
|
||||
bool aTopMarginRoot,
|
||||
bool aBottomMarginRoot,
|
||||
bool aBStartMarginRoot,
|
||||
bool aBEndMarginRoot,
|
||||
bool aBlockNeedsFloatManager,
|
||||
nscoord aConsumedHeight)
|
||||
nscoord aConsumedBSize)
|
||||
: mBlock(aFrame),
|
||||
mPresContext(aPresContext),
|
||||
mReflowState(aReflowState),
|
||||
mContentArea(aReflowState.GetWritingMode()),
|
||||
mPushedFloats(nullptr),
|
||||
mOverflowTracker(nullptr),
|
||||
mPrevBottomMargin(),
|
||||
mBorderPadding(mReflowState.ComputedLogicalBorderPadding()),
|
||||
mPrevBEndMargin(),
|
||||
mLineNumber(0),
|
||||
mFlags(0),
|
||||
mFloatBreakType(NS_STYLE_CLEAR_NONE),
|
||||
mConsumedHeight(aConsumedHeight)
|
||||
mConsumedBSize(aConsumedBSize)
|
||||
{
|
||||
WritingMode wm = aReflowState.GetWritingMode();
|
||||
SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nullptr);
|
||||
SetFlag(BRS_ISOVERFLOWCONTAINER,
|
||||
IS_TRUE_OVERFLOW_CONTAINER(aFrame));
|
||||
|
||||
mBorderPadding = mReflowState.ComputedPhysicalBorderPadding();
|
||||
aFrame->ApplySkipSides(mBorderPadding, &aReflowState);
|
||||
mContainerWidth = aReflowState.ComputedWidth() + mBorderPadding.LeftRight();
|
||||
aFrame->ApplyLogicalSkipSides(mBorderPadding, &aReflowState);
|
||||
|
||||
if (aTopMarginRoot || 0 != mBorderPadding.top) {
|
||||
SetFlag(BRS_ISTOPMARGINROOT, true);
|
||||
// Note that mContainerWidth is the physical width!
|
||||
mContainerWidth = aReflowState.ComputedWidth() + mBorderPadding.LeftRight(wm);
|
||||
|
||||
if (aBStartMarginRoot || 0 != mBorderPadding.BStart(wm)) {
|
||||
SetFlag(BRS_ISBSTARTMARGINROOT, true);
|
||||
}
|
||||
if (aBottomMarginRoot || 0 != mBorderPadding.bottom) {
|
||||
SetFlag(BRS_ISBOTTOMMARGINROOT, true);
|
||||
if (aBEndMarginRoot || 0 != mBorderPadding.BEnd(wm)) {
|
||||
SetFlag(BRS_ISBENDMARGINROOT, true);
|
||||
}
|
||||
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||
SetFlag(BRS_APPLYTOPMARGIN, true);
|
||||
if (GetFlag(BRS_ISBSTARTMARGINROOT)) {
|
||||
SetFlag(BRS_APPLYBSTARTMARGIN, true);
|
||||
}
|
||||
if (aBlockNeedsFloatManager) {
|
||||
SetFlag(BRS_FLOAT_MGR, true);
|
||||
@ -77,11 +81,11 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
|
||||
mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
|
||||
|
||||
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedWidth(),
|
||||
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedISize(),
|
||||
"have unconstrained width; this should only result from "
|
||||
"very large sizes, not attempts at intrinsic width "
|
||||
"calculation");
|
||||
mContentArea.width = aReflowState.ComputedWidth();
|
||||
mContentArea.ISize(wm) = aReflowState.ComputedISize();
|
||||
|
||||
// Compute content area height. Unlike the width, if we have a
|
||||
// specified style height we ignore it since extra content is
|
||||
@ -89,21 +93,21 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
// specified style height then we may end up limiting our height if
|
||||
// the availableHeight is constrained (this situation occurs when we
|
||||
// are paginated).
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableHeight()) {
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableBSize()) {
|
||||
// We are in a paginated situation. The bottom edge is just inside
|
||||
// the bottom border and padding. The content area height doesn't
|
||||
// include either border or padding edge.
|
||||
mBottomEdge = aReflowState.AvailableHeight() - mBorderPadding.bottom;
|
||||
mContentArea.height = std::max(0, mBottomEdge - mBorderPadding.top);
|
||||
mBEndEdge = aReflowState.AvailableBSize() - mBorderPadding.BEnd(wm);
|
||||
mContentArea.BSize(wm) = std::max(0, mBEndEdge - mBorderPadding.BStart(wm));
|
||||
}
|
||||
else {
|
||||
// When we are not in a paginated situation then we always use
|
||||
// an constrained height.
|
||||
SetFlag(BRS_UNCONSTRAINEDHEIGHT, true);
|
||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||
SetFlag(BRS_UNCONSTRAINEDBSIZE, true);
|
||||
mContentArea.BSize(wm) = mBEndEdge = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
mContentArea.x = mBorderPadding.left;
|
||||
mY = mContentArea.y = mBorderPadding.top;
|
||||
mContentArea.IStart(wm) = mBorderPadding.IStart(wm);
|
||||
mBCoord = mContentArea.BStart(wm) = mBorderPadding.BStart(wm);
|
||||
|
||||
mPrevChild = nullptr;
|
||||
mCurrentLine = aFrame->end_lines();
|
||||
@ -112,13 +116,13 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsBlockReflowState::GetConsumedHeight()
|
||||
nsBlockReflowState::GetConsumedBSize()
|
||||
{
|
||||
if (mConsumedHeight == NS_INTRINSICSIZE) {
|
||||
mConsumedHeight = mBlock->GetConsumedHeight();
|
||||
if (mConsumedBSize == NS_INTRINSICSIZE) {
|
||||
mConsumedBSize = mBlock->GetConsumedBSize();
|
||||
}
|
||||
|
||||
return mConsumedHeight;
|
||||
return mConsumedBSize;
|
||||
}
|
||||
|
||||
void
|
||||
@ -127,31 +131,33 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
||||
nscoord& aLeftResult,
|
||||
nscoord& aRightResult)
|
||||
{
|
||||
nsRect contentArea =
|
||||
mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
|
||||
// The frame is clueless about the float manager and therefore we
|
||||
// only give it free space. An example is a table frame - the
|
||||
// tables do not flow around floats.
|
||||
// However, we can let its margins intersect floats.
|
||||
NS_ASSERTION(aFloatAvailableSpace.x >= mContentArea.x, "bad avail space rect x");
|
||||
NS_ASSERTION(aFloatAvailableSpace.x >= contentArea.x, "bad avail space rect x");
|
||||
NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
|
||||
aFloatAvailableSpace.XMost() <= mContentArea.XMost(),
|
||||
aFloatAvailableSpace.XMost() <= contentArea.XMost(),
|
||||
"bad avail space rect width");
|
||||
|
||||
nscoord leftOffset, rightOffset;
|
||||
if (aFloatAvailableSpace.width == mContentArea.width) {
|
||||
if (aFloatAvailableSpace.width == contentArea.width) {
|
||||
// We don't need to compute margins when there are no floats around.
|
||||
leftOffset = 0;
|
||||
rightOffset = 0;
|
||||
} else {
|
||||
nsMargin frameMargin;
|
||||
nsCSSOffsetState os(aFrame, mReflowState.rendContext, mContentArea.width);
|
||||
nsCSSOffsetState os(aFrame, mReflowState.rendContext, contentArea.width);
|
||||
frameMargin = os.ComputedPhysicalMargin();
|
||||
|
||||
nscoord leftFloatXOffset = aFloatAvailableSpace.x - mContentArea.x;
|
||||
nscoord leftFloatXOffset = aFloatAvailableSpace.x - contentArea.x;
|
||||
leftOffset = std::max(leftFloatXOffset, frameMargin.left) -
|
||||
frameMargin.left;
|
||||
leftOffset = std::max(leftOffset, 0); // in case of negative margin
|
||||
nscoord rightFloatXOffset =
|
||||
mContentArea.XMost() - aFloatAvailableSpace.XMost();
|
||||
contentArea.XMost() - aFloatAvailableSpace.XMost();
|
||||
rightOffset = std::max(rightFloatXOffset, frameMargin.right) -
|
||||
frameMargin.right;
|
||||
rightOffset = std::max(rightOffset, 0); // in case of negative margin
|
||||
@ -174,11 +180,16 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
printf("CBAS frame=%p has floats %d\n",
|
||||
aFrame, aFloatAvailableSpace.mHasFloats);
|
||||
#endif
|
||||
aResult.y = mY;
|
||||
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||
WritingMode wm = mReflowState.GetWritingMode();
|
||||
LogicalRect result(wm);
|
||||
LogicalRect floatAvailSpace = LogicalRect(wm,
|
||||
aFloatAvailableSpace.mRect,
|
||||
mContainerWidth); //??mReflowState.AvailableWidth());
|
||||
result.BStart(wm) = mBCoord;
|
||||
result.BSize(wm) = GetFlag(BRS_UNCONSTRAINEDBSIZE)
|
||||
? NS_UNCONSTRAINEDSIZE
|
||||
: mReflowState.AvailableHeight() - mY;
|
||||
// mY might be greater than mBottomEdge if the block's top margin pushes
|
||||
: mReflowState.AvailableBSize() - mBCoord;
|
||||
// mBCoord might be greater than mBEndEdge if the block's top margin pushes
|
||||
// it off the page/column. Negative available height can confuse other code
|
||||
// and is nonsense in principle.
|
||||
|
||||
@ -207,15 +218,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floats
|
||||
// The child block will flow around the float. Therefore
|
||||
// give it all of the available space.
|
||||
aResult.x = mContentArea.x;
|
||||
aResult.width = mContentArea.width;
|
||||
result.IStart(wm) = ContentIStart();
|
||||
result.ISize(wm) = ContentISize();
|
||||
break;
|
||||
case NS_STYLE_FLOAT_EDGE_MARGIN:
|
||||
{
|
||||
// The child block's margins should be placed adjacent to,
|
||||
// but not overlap the float.
|
||||
aResult.x = aFloatAvailableSpace.mRect.x;
|
||||
aResult.width = aFloatAvailableSpace.mRect.width;
|
||||
result.IStart(wm) = floatAvailSpace.IStart(wm);
|
||||
result.ISize(wm) = floatAvailSpace.ISize(wm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -224,16 +235,20 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
// Since there are no floats present the float-edge property
|
||||
// doesn't matter therefore give the block element all of the
|
||||
// available space since it will flow around the float itself.
|
||||
aResult.x = mContentArea.x;
|
||||
aResult.width = mContentArea.width;
|
||||
result.IStart(wm) = ContentIStart();
|
||||
result.ISize(wm) = ContentISize();
|
||||
}
|
||||
aResult = result.GetPhysicalRect(wm, mContainerWidth);
|
||||
}
|
||||
else {
|
||||
aResult = result.GetPhysicalRect(wm, mContainerWidth);
|
||||
nsRect contentArea =
|
||||
mContentArea.GetPhysicalRect(wm, mContainerWidth);
|
||||
nscoord leftOffset, rightOffset;
|
||||
ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
|
||||
leftOffset, rightOffset);
|
||||
aResult.x = mContentArea.x + leftOffset;
|
||||
aResult.width = mContentArea.width - leftOffset - rightOffset;
|
||||
aResult.x = contentArea.x + leftOffset;
|
||||
aResult.width = contentArea.width - leftOffset - rightOffset;
|
||||
}
|
||||
|
||||
#ifdef REALLY_NOISY_REFLOW
|
||||
@ -243,7 +258,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
|
||||
nsFlowAreaRect
|
||||
nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
||||
nscoord aY,
|
||||
nscoord aBCoord,
|
||||
nsFloatManager::SavedState *aState) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -254,11 +269,13 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
||||
"bad coord system");
|
||||
#endif
|
||||
|
||||
nscoord height = (mContentArea.height == nscoord_MAX)
|
||||
? nscoord_MAX : std::max(mContentArea.YMost() - aY, 0);
|
||||
nsRect contentArea =
|
||||
mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
|
||||
nscoord height = (contentArea.height == nscoord_MAX)
|
||||
? nscoord_MAX : std::max(contentArea.YMost() - aBCoord, 0);
|
||||
nsFlowAreaRect result =
|
||||
mFloatManager->GetFlowArea(aY, nsFloatManager::BAND_FROM_POINT,
|
||||
height, mContentArea, aState);
|
||||
mFloatManager->GetFlowArea(aBCoord, nsFloatManager::BAND_FROM_POINT,
|
||||
height, contentArea, aState);
|
||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||
if (result.mRect.width < 0)
|
||||
result.mRect.width = 0;
|
||||
@ -275,8 +292,8 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
||||
}
|
||||
|
||||
nsFlowAreaRect
|
||||
nsBlockReflowState::GetFloatAvailableSpaceForHeight(
|
||||
nscoord aY, nscoord aHeight,
|
||||
nsBlockReflowState::GetFloatAvailableSpaceForBSize(
|
||||
nscoord aBCoord, nscoord aBSize,
|
||||
nsFloatManager::SavedState *aState) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -286,10 +303,11 @@ nsBlockReflowState::GetFloatAvailableSpaceForHeight(
|
||||
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
|
||||
"bad coord system");
|
||||
#endif
|
||||
|
||||
nsRect contentArea =
|
||||
mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
|
||||
nsFlowAreaRect result =
|
||||
mFloatManager->GetFlowArea(aY, nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
||||
aHeight, mContentArea, aState);
|
||||
mFloatManager->GetFlowArea(aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
||||
aBSize, contentArea, aState);
|
||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||
if (result.mRect.width < 0)
|
||||
result.mRect.width = 0;
|
||||
@ -314,21 +332,21 @@ nsBlockReflowState::GetFloatAvailableSpaceForHeight(
|
||||
*
|
||||
* The reconstruction involves walking backward through the line list to
|
||||
* find any collapsed margins preceding the line that would have been in
|
||||
* the reflow state's |mPrevBottomMargin| when we reflowed that line in
|
||||
* the reflow state's |mPrevBEndMargin| when we reflowed that line in
|
||||
* a full reflow (under the rule in CSS2 that all adjacent vertical
|
||||
* margins of blocks collapse).
|
||||
*/
|
||||
void
|
||||
nsBlockReflowState::ReconstructMarginAbove(nsLineList::iterator aLine)
|
||||
nsBlockReflowState::ReconstructMarginBefore(nsLineList::iterator aLine)
|
||||
{
|
||||
mPrevBottomMargin.Zero();
|
||||
mPrevBEndMargin.Zero();
|
||||
nsBlockFrame *block = mBlock;
|
||||
|
||||
nsLineList::iterator firstLine = block->begin_lines();
|
||||
for (;;) {
|
||||
--aLine;
|
||||
if (aLine->IsBlock()) {
|
||||
mPrevBottomMargin = aLine->GetCarriedOutBottomMargin();
|
||||
mPrevBEndMargin = aLine->GetCarriedOutBEndMargin();
|
||||
break;
|
||||
}
|
||||
if (!aLine->IsEmpty()) {
|
||||
@ -337,8 +355,8 @@ nsBlockReflowState::ReconstructMarginAbove(nsLineList::iterator aLine)
|
||||
if (aLine == firstLine) {
|
||||
// If the top margin was carried out (and thus already applied),
|
||||
// set it to zero. Either way, we're done.
|
||||
if (!GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||
mPrevBottomMargin.Zero();
|
||||
if (!GetFlag(BRS_ISBSTARTMARGINROOT)) {
|
||||
mPrevBEndMargin.Zero();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -374,14 +392,14 @@ nsBlockReflowState::AppendPushedFloat(nsIFrame* aFloatCont)
|
||||
/**
|
||||
* Restore information about floats into the float manager for an
|
||||
* incremental reflow, and simultaneously push the floats by
|
||||
* |aDeltaY|, which is the amount |aLine| was pushed relative to its
|
||||
* |aDeltaBCoord|, which is the amount |aLine| was pushed relative to its
|
||||
* parent. The recovery of state is one of the things that makes
|
||||
* incremental reflow O(N^2) and this state should really be kept
|
||||
* around, attached to the frame tree.
|
||||
*/
|
||||
void
|
||||
nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
||||
nscoord aDeltaY)
|
||||
nscoord aDeltaBCoord)
|
||||
{
|
||||
if (aLine->HasFloats()) {
|
||||
// Place the floats into the space-manager again. Also slide
|
||||
@ -389,8 +407,8 @@ nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
||||
nsFloatCache* fc = aLine->GetFirstFloat();
|
||||
while (fc) {
|
||||
nsIFrame* floatFrame = fc->mFloat;
|
||||
if (aDeltaY != 0) {
|
||||
floatFrame->MovePositionBy(nsPoint(0, aDeltaY));
|
||||
if (aDeltaBCoord != 0) {
|
||||
floatFrame->MovePositionBy(nsPoint(0, aDeltaBCoord));
|
||||
nsContainerFrame::PositionFrameView(floatFrame);
|
||||
nsContainerFrame::PositionChildViews(floatFrame);
|
||||
}
|
||||
@ -403,8 +421,8 @@ nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
||||
tx, ty, mFloatManagerX, mFloatManagerY);
|
||||
nsFrame::ListTag(stdout, floatFrame);
|
||||
nsRect region = nsFloatManager::GetRegionFor(floatFrame);
|
||||
printf(" aDeltaY=%d region={%d,%d,%d,%d}\n",
|
||||
aDeltaY, region.x, region.y, region.width, region.height);
|
||||
printf(" aDeltaBCoord=%d region={%d,%d,%d,%d}\n",
|
||||
aDeltaBCoord, region.x, region.y, region.width, region.height);
|
||||
}
|
||||
#endif
|
||||
mFloatManager->AddFloat(floatFrame,
|
||||
@ -421,7 +439,7 @@ nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
||||
* reflow so it is O(N*M) where M is the number of incremental reflow
|
||||
* passes. That's bad. Don't do stuff here.
|
||||
*
|
||||
* When this function is called, |aLine| has just been slid by |aDeltaY|
|
||||
* When this function is called, |aLine| has just been slid by |aDeltaBCoord|
|
||||
* and the purpose of RecoverStateFrom is to ensure that the
|
||||
* nsBlockReflowState is in the same state that it would have been in
|
||||
* had the line just been reflowed.
|
||||
@ -430,14 +448,14 @@ nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
||||
*/
|
||||
void
|
||||
nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
|
||||
nscoord aDeltaY)
|
||||
nscoord aDeltaBCoord)
|
||||
{
|
||||
// Make the line being recovered the current line
|
||||
mCurrentLine = aLine;
|
||||
|
||||
// Place floats for this line into the float manager
|
||||
if (aLine->HasFloats() || aLine->IsBlock()) {
|
||||
RecoverFloats(aLine, aDeltaY);
|
||||
RecoverFloats(aLine, aDeltaBCoord);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
|
||||
@ -521,8 +539,8 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
|
||||
placed = FlowAndPlaceFloat(aFloat);
|
||||
if (placed) {
|
||||
// Pass on updated available space to the current inline reflow engine
|
||||
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
|
||||
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mY),
|
||||
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mBCoord);
|
||||
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mBCoord),
|
||||
floatAvailSpace.mRect.Size());
|
||||
aLineLayout->UpdateBand(availSpace, aFloat);
|
||||
// Record this float in the current-line list
|
||||
@ -587,13 +605,13 @@ bool
|
||||
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
{
|
||||
// Save away the Y coordinate before placing the float. We will
|
||||
// restore mY at the end after placing the float. This is
|
||||
// necessary because any adjustments to mY during the float
|
||||
// restore mBCoord at the end after placing the float. This is
|
||||
// necessary because any adjustments to mBCoord during the float
|
||||
// placement are for the float only, not for any non-floating
|
||||
// content.
|
||||
AutoRestore<nscoord> restoreY(mY);
|
||||
AutoRestore<nscoord> restoreBCoord(mBCoord);
|
||||
// FIXME: Should give AutoRestore a getter for the value to avoid this.
|
||||
const nscoord saveY = mY;
|
||||
const nscoord saveBCoord = mBCoord;
|
||||
|
||||
// Grab the float's display information
|
||||
const nsStyleDisplay* floatDisplay = aFloat->StyleDisplay();
|
||||
@ -603,17 +621,17 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
|
||||
// Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
|
||||
// ``above'' another float that preceded it in the flow.
|
||||
mY = std::max(mFloatManager->GetLowestFloatTop(), mY);
|
||||
mBCoord = std::max(mFloatManager->GetLowestFloatTop(), mBCoord);
|
||||
|
||||
// See if the float should clear any preceding floats...
|
||||
// XXX We need to mark this float somehow so that it gets reflowed
|
||||
// when floats are inserted before it.
|
||||
if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
|
||||
// XXXldb Does this handle vertical margins correctly?
|
||||
mY = ClearFloats(mY, floatDisplay->mBreakType);
|
||||
mBCoord = ClearFloats(mBCoord, floatDisplay->mBreakType);
|
||||
}
|
||||
// Get the band of available space
|
||||
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mBCoord);
|
||||
nsRect adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
||||
floatAvailableSpace.mRect, aFloat);
|
||||
|
||||
@ -678,11 +696,11 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
|
||||
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
||||
|
||||
mY += floatAvailableSpace.mRect.height;
|
||||
mBCoord += floatAvailableSpace.mRect.height;
|
||||
if (adjustedAvailableSpace.height != NS_UNCONSTRAINEDSIZE) {
|
||||
adjustedAvailableSpace.height -= floatAvailableSpace.mRect.height;
|
||||
}
|
||||
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||
floatAvailableSpace = GetFloatAvailableSpace(mBCoord);
|
||||
} else {
|
||||
// This quirk matches the one in nsBlockFrame::AdjustFloatAvailableSpace
|
||||
// IE handles float tables in a very special way
|
||||
@ -720,10 +738,10 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
}
|
||||
|
||||
// the table does not fit anymore in this line so advance to next band
|
||||
mY += floatAvailableSpace.mRect.height;
|
||||
mBCoord += floatAvailableSpace.mRect.height;
|
||||
// To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
|
||||
// get a new width for the new band.
|
||||
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||
floatAvailableSpace = GetFloatAvailableSpace(mBCoord);
|
||||
adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
||||
floatAvailableSpace.mRect, aFloat);
|
||||
floatMarginWidth = FloatMarginWidth(mReflowState,
|
||||
@ -760,12 +778,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
// containing block is the content edge of the block box, this
|
||||
// means the margin edge of the float can't be higher than the
|
||||
// content edge of the block that contains it.)
|
||||
floatY = std::max(mY, mContentArea.y);
|
||||
floatY = std::max(mBCoord, ContentBStart());
|
||||
|
||||
// Reflow the float after computing its vertical position so it knows
|
||||
// where to break.
|
||||
if (!isLetter) {
|
||||
bool pushedDown = mY != saveY;
|
||||
bool pushedDown = mBCoord != saveBCoord;
|
||||
mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin,
|
||||
floatOffsets, pushedDown, reflowStatus);
|
||||
}
|
||||
@ -781,11 +799,11 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
// Likewise, if none of the float fit, and it needs to be pushed in
|
||||
// its entirety to the next page (NS_FRAME_IS_TRUNCATED or
|
||||
// NS_INLINE_IS_BREAK_BEFORE), we need to do the same.
|
||||
if ((mContentArea.height != NS_UNCONSTRAINEDSIZE &&
|
||||
if ((ContentBSize() != NS_UNCONSTRAINEDSIZE &&
|
||||
adjustedAvailableSpace.height == NS_UNCONSTRAINEDSIZE &&
|
||||
!mustPlaceFloat &&
|
||||
aFloat->GetSize().height + floatMargin.TopBottom() >
|
||||
mContentArea.YMost() - floatY) ||
|
||||
ContentBEnd() - floatY) ||
|
||||
NS_FRAME_IS_TRUNCATED(reflowStatus) ||
|
||||
NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
|
||||
PushFloatPastBreak(aFloat);
|
||||
@ -795,12 +813,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
// We can't use aFloat->ShouldAvoidBreakInside(mReflowState) here since
|
||||
// its mIsTopOfPage may be true even though the float isn't at the
|
||||
// top when floatY > 0.
|
||||
if (mContentArea.height != NS_UNCONSTRAINEDSIZE &&
|
||||
if (ContentBSize() != NS_UNCONSTRAINEDSIZE &&
|
||||
!mustPlaceFloat && (!mReflowState.mFlags.mIsTopOfPage || floatY > 0) &&
|
||||
NS_STYLE_PAGE_BREAK_AVOID == aFloat->StyleDisplay()->mBreakInside &&
|
||||
(!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus) ||
|
||||
aFloat->GetSize().height + floatMargin.TopBottom() >
|
||||
mContentArea.YMost() - floatY) &&
|
||||
ContentBEnd() - floatY) &&
|
||||
!aFloat->GetPrevInFlow()) {
|
||||
PushFloatPastBreak(aFloat);
|
||||
return false;
|
||||
@ -834,8 +852,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
nsRect region = nsFloatManager::CalculateRegionFor(aFloat, floatMargin);
|
||||
// if the float split, then take up all of the vertical height
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
|
||||
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
|
||||
region.height = std::max(region.height, mContentArea.height - floatY);
|
||||
(NS_UNCONSTRAINEDSIZE != ContentBSize())) {
|
||||
region.height = std::max(region.height, ContentBSize() - floatY);
|
||||
}
|
||||
DebugOnly<nsresult> rv =
|
||||
mFloatManager->AddFloat(aFloat, region);
|
||||
@ -937,36 +955,36 @@ nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList,
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsBlockReflowState::ClearFloats(nscoord aY, uint8_t aBreakType,
|
||||
nsBlockReflowState::ClearFloats(nscoord aBCoord, uint8_t aBreakType,
|
||||
nsIFrame *aReplacedBlock,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("clear floats: in: aY=%d\n", aY);
|
||||
printf("clear floats: in: aBCoord=%d\n", aBCoord);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOISY_FLOAT_CLEARING
|
||||
printf("nsBlockReflowState::ClearFloats: aY=%d breakType=%d\n",
|
||||
aY, aBreakType);
|
||||
printf("nsBlockReflowState::ClearFloats: aBCoord=%d breakType=%d\n",
|
||||
aBCoord, aBreakType);
|
||||
mFloatManager->List(stdout);
|
||||
#endif
|
||||
|
||||
if (!mFloatManager->HasAnyFloats()) {
|
||||
return aY;
|
||||
return aBCoord;
|
||||
}
|
||||
|
||||
nscoord newY = aY;
|
||||
nscoord newBCoord = aBCoord;
|
||||
|
||||
if (aBreakType != NS_STYLE_CLEAR_NONE) {
|
||||
newY = mFloatManager->ClearFloats(newY, aBreakType, aFlags);
|
||||
newBCoord = mFloatManager->ClearFloats(newBCoord, aBreakType, aFlags);
|
||||
}
|
||||
|
||||
if (aReplacedBlock) {
|
||||
for (;;) {
|
||||
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newY);
|
||||
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newBCoord);
|
||||
if (!floatAvailableSpace.mHasFloats) {
|
||||
// If there aren't any floats here, then we always fit.
|
||||
// We check this before calling WidthToClearPastFloats, which is
|
||||
@ -976,18 +994,18 @@ nsBlockReflowState::ClearFloats(nscoord aY, uint8_t aBreakType,
|
||||
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
|
||||
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
|
||||
aReplacedBlock);
|
||||
if (std::max(floatAvailableSpace.mRect.x - mContentArea.x,
|
||||
if (std::max(floatAvailableSpace.mRect.x - ContentIStart(),
|
||||
replacedWidth.marginLeft) +
|
||||
replacedWidth.borderBoxWidth +
|
||||
std::max(mContentArea.XMost() - floatAvailableSpace.mRect.XMost(),
|
||||
std::max(ContentIEnd() - floatAvailableSpace.mRect.XMost(),
|
||||
replacedWidth.marginRight) <=
|
||||
mContentArea.width) {
|
||||
ContentISize()) {
|
||||
break;
|
||||
}
|
||||
// See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
|
||||
if (floatAvailableSpace.mRect.height > 0) {
|
||||
// See if there's room in the next band.
|
||||
newY += floatAvailableSpace.mRect.height;
|
||||
newBCoord += floatAvailableSpace.mRect.height;
|
||||
} else {
|
||||
if (mReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
|
||||
// Stop trying to clear here; we'll just get pushed to the
|
||||
@ -995,7 +1013,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, uint8_t aBreakType,
|
||||
break;
|
||||
}
|
||||
NS_NOTREACHED("avail space rect with zero height!");
|
||||
newY += 1;
|
||||
newBCoord += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1003,10 +1021,10 @@ nsBlockReflowState::ClearFloats(nscoord aY, uint8_t aBreakType,
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("clear floats: out: y=%d\n", newY);
|
||||
printf("clear floats: out: y=%d\n", newBCoord);
|
||||
}
|
||||
#endif
|
||||
|
||||
return newY;
|
||||
return newBCoord;
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,10 @@ class nsFrameList;
|
||||
class nsOverflowContinuationTracker;
|
||||
|
||||
// block reflow state flags
|
||||
#define BRS_UNCONSTRAINEDHEIGHT 0x00000001
|
||||
#define BRS_ISTOPMARGINROOT 0x00000002 // Is this frame a root for top/bottom margin collapsing?
|
||||
#define BRS_ISBOTTOMMARGINROOT 0x00000004
|
||||
#define BRS_APPLYTOPMARGIN 0x00000008 // See ShouldApplyTopMargin
|
||||
#define BRS_UNCONSTRAINEDBSIZE 0x00000001
|
||||
#define BRS_ISBSTARTMARGINROOT 0x00000002 // Is this frame a root for block
|
||||
#define BRS_ISBENDMARGINROOT 0x00000004 // direction start/end margin collapsing?
|
||||
#define BRS_APPLYBSTARTMARGIN 0x00000008 // See ShouldApplyTopMargin
|
||||
#define BRS_ISFIRSTINFLOW 0x00000010
|
||||
// Set when mLineAdjacentToTop is valid
|
||||
#define BRS_HAVELINEADJACENTTOTOP 0x00000020
|
||||
@ -39,9 +39,9 @@ public:
|
||||
nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
nsPresContext* aPresContext,
|
||||
nsBlockFrame* aFrame,
|
||||
bool aTopMarginRoot, bool aBottomMarginRoot,
|
||||
bool aBStartMarginRoot, bool aBEndMarginRoot,
|
||||
bool aBlockNeedsFloatManager,
|
||||
nscoord aConsumedHeight = NS_INTRINSICSIZE);
|
||||
nscoord aConsumedBSize = NS_INTRINSICSIZE);
|
||||
|
||||
/**
|
||||
* Get the available reflow space (the area not occupied by floats)
|
||||
@ -49,19 +49,19 @@ public:
|
||||
* our coordinate system, which is the content box, with (0, 0) in the
|
||||
* upper left.
|
||||
*
|
||||
* Returns whether there are floats present at the given vertical
|
||||
* coordinate and within the width of the content rect.
|
||||
* Returns whether there are floats present at the given block-direction
|
||||
* coordinate and within the inline size of the content rect.
|
||||
*/
|
||||
nsFlowAreaRect GetFloatAvailableSpace() const
|
||||
{ return GetFloatAvailableSpace(mY); }
|
||||
nsFlowAreaRect GetFloatAvailableSpace(nscoord aY) const
|
||||
{ return GetFloatAvailableSpaceWithState(aY, nullptr); }
|
||||
{ return GetFloatAvailableSpace(mBCoord); }
|
||||
nsFlowAreaRect GetFloatAvailableSpace(nscoord aBCoord) const
|
||||
{ return GetFloatAvailableSpaceWithState(aBCoord, nullptr); }
|
||||
nsFlowAreaRect
|
||||
GetFloatAvailableSpaceWithState(nscoord aY,
|
||||
GetFloatAvailableSpaceWithState(nscoord aBCoord,
|
||||
nsFloatManager::SavedState *aState) const;
|
||||
nsFlowAreaRect
|
||||
GetFloatAvailableSpaceForHeight(nscoord aY, nscoord aHeight,
|
||||
nsFloatManager::SavedState *aState) const;
|
||||
GetFloatAvailableSpaceForBSize(nscoord aBCoord, nscoord aBSize,
|
||||
nsFloatManager::SavedState *aState) const;
|
||||
|
||||
/*
|
||||
* The following functions all return true if they were able to
|
||||
@ -71,11 +71,11 @@ public:
|
||||
* they are not associated with a line box).
|
||||
*/
|
||||
bool AddFloat(nsLineLayout* aLineLayout,
|
||||
nsIFrame* aFloat,
|
||||
nscoord aAvailableWidth);
|
||||
nsIFrame* aFloat,
|
||||
nscoord aAvailableISize);
|
||||
private:
|
||||
bool CanPlaceFloat(nscoord aFloatWidth,
|
||||
const nsFlowAreaRect& aFloatAvailableSpace);
|
||||
bool CanPlaceFloat(nscoord aFloatISize,
|
||||
const nsFlowAreaRect& aFloatAvailableSpace);
|
||||
public:
|
||||
bool FlowAndPlaceFloat(nsIFrame* aFloat);
|
||||
private:
|
||||
@ -84,40 +84,40 @@ public:
|
||||
void PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats,
|
||||
nsLineBox* aLine);
|
||||
|
||||
// Returns the first coordinate >= aY that clears the
|
||||
// floats indicated by aBreakType and has enough width between floats
|
||||
// Returns the first coordinate >= aBCoord that clears the
|
||||
// floats indicated by aBreakType and has enough inline size between floats
|
||||
// (or no floats remaining) to accomodate aReplacedBlock.
|
||||
nscoord ClearFloats(nscoord aY, uint8_t aBreakType,
|
||||
nscoord ClearFloats(nscoord aBCoord, uint8_t aBreakType,
|
||||
nsIFrame *aReplacedBlock = nullptr,
|
||||
uint32_t aFlags = 0);
|
||||
|
||||
bool IsAdjacentWithTop() const {
|
||||
return mY == mBorderPadding.top;
|
||||
return mBCoord == mBorderPadding.BStart(mReflowState.GetWritingMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return mBlock's computed physical border+padding with GetSkipSides applied.
|
||||
*/
|
||||
const nsMargin& BorderPadding() const {
|
||||
const mozilla::LogicalMargin& BorderPadding() const {
|
||||
return mBorderPadding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the height "consumed" by any previous-in-flows.
|
||||
* Retrieve the block-direction size "consumed" by any previous-in-flows.
|
||||
*/
|
||||
nscoord GetConsumedHeight();
|
||||
nscoord GetConsumedBSize();
|
||||
|
||||
// Reconstruct the previous bottom margin that goes above |aLine|.
|
||||
void ReconstructMarginAbove(nsLineList::iterator aLine);
|
||||
// Reconstruct the previous block-end margin that goes before |aLine|.
|
||||
void ReconstructMarginBefore(nsLineList::iterator aLine);
|
||||
|
||||
// Caller must have called GetAvailableSpace for the correct position
|
||||
// (which need not be the current mY).
|
||||
// (which need not be the current mBCoord).
|
||||
void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
||||
const nsRect& aFloatAvailableSpace,
|
||||
nscoord& aLeftResult,
|
||||
nscoord& aRightResult);
|
||||
|
||||
// Caller must have called GetAvailableSpace for the current mY
|
||||
// Caller must have called GetAvailableSpace for the current mBCoord
|
||||
void ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisplay,
|
||||
const nsFlowAreaRect& aFloatAvailableSpace,
|
||||
@ -125,10 +125,10 @@ public:
|
||||
nsRect& aResult);
|
||||
|
||||
protected:
|
||||
void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaY);
|
||||
void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaBCoord);
|
||||
|
||||
public:
|
||||
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaY);
|
||||
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord);
|
||||
|
||||
void AdvanceToNextLine() {
|
||||
if (GetFlag(BRS_LINE_LAYOUT_EMPTY)) {
|
||||
@ -168,17 +168,36 @@ public:
|
||||
// block, not floats inside of it.
|
||||
nsFloatManager::SavedState mFloatManagerStateBefore;
|
||||
|
||||
nscoord mBottomEdge;
|
||||
nscoord mBEndEdge;
|
||||
|
||||
// The content area to reflow child frames within. This is within
|
||||
// this frame's coordinate system, which means mContentArea.x ==
|
||||
// BorderPadding().left and mContentArea.y == BorderPadding().top.
|
||||
// The height may be NS_UNCONSTRAINEDSIZE, which indicates that there
|
||||
// this frame's coordinate system and writing mode, which means
|
||||
// mContentArea.IStart == BorderPadding().IStart and
|
||||
// mContentArea.BStart == BorderPadding().BStart.
|
||||
// The block size may be NS_UNCONSTRAINEDSIZE, which indicates that there
|
||||
// is no page/column boundary below (the common case).
|
||||
// mContentArea.YMost() should only be called after checking that
|
||||
// mContentArea.height is not NS_UNCONSTRAINEDSIZE; otherwise
|
||||
// mContentArea.BEnd() should only be called after checking that
|
||||
// mContentArea.BSize is not NS_UNCONSTRAINEDSIZE; otherwise
|
||||
// coordinate overflow may occur.
|
||||
nsRect mContentArea;
|
||||
mozilla::LogicalRect mContentArea;
|
||||
nscoord ContentIStart() {
|
||||
return mContentArea.IStart(mReflowState.GetWritingMode());
|
||||
}
|
||||
nscoord ContentISize() {
|
||||
return mContentArea.ISize(mReflowState.GetWritingMode());
|
||||
}
|
||||
nscoord ContentIEnd() {
|
||||
return mContentArea.IEnd(mReflowState.GetWritingMode());
|
||||
}
|
||||
nscoord ContentBStart() {
|
||||
return mContentArea.BStart(mReflowState.GetWritingMode());
|
||||
}
|
||||
nscoord ContentBSize() {
|
||||
return mContentArea.BSize(mReflowState.GetWritingMode());
|
||||
}
|
||||
nscoord ContentBEnd() {
|
||||
return mContentArea.BEnd(mReflowState.GetWritingMode());
|
||||
}
|
||||
nscoord mContainerWidth;
|
||||
|
||||
// Continuation out-of-flow float frames that need to move to our
|
||||
@ -210,11 +229,11 @@ public:
|
||||
// always before the current line.
|
||||
nsLineList::iterator mLineAdjacentToTop;
|
||||
|
||||
// The current Y coordinate in the block
|
||||
nscoord mY;
|
||||
// The current block-direction coordinate in the block
|
||||
nscoord mBCoord;
|
||||
|
||||
// mBlock's computed physical border+padding with GetSkipSides applied.
|
||||
nsMargin mBorderPadding;
|
||||
mozilla::LogicalMargin mBorderPadding;
|
||||
|
||||
// The overflow areas of all floats placed so far
|
||||
nsOverflowAreas mFloatOverflowAreas;
|
||||
@ -226,7 +245,7 @@ public:
|
||||
nsIFrame* mPrevChild;
|
||||
|
||||
// The previous child frames collapsed bottom margin value.
|
||||
nsCollapsingMargin mPrevBottomMargin;
|
||||
nsCollapsingMargin mPrevBEndMargin;
|
||||
|
||||
// The current next-in-flow for the block. When lines are pulled
|
||||
// from a next-in-flow, this is used to know which next-in-flow to
|
||||
@ -258,8 +277,8 @@ public:
|
||||
|
||||
uint8_t mFloatBreakType;
|
||||
|
||||
// The amount of computed height "consumed" by previous-in-flows.
|
||||
nscoord mConsumedHeight;
|
||||
// The amount of computed block-direction size "consumed" by previous-in-flows.
|
||||
nscoord mConsumedBSize;
|
||||
|
||||
void SetFlag(uint32_t aFlag, bool aValue)
|
||||
{
|
||||
|
@ -177,13 +177,13 @@ nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState,
|
||||
availContentWidth = aReflowState.ComputedWidth();
|
||||
}
|
||||
|
||||
nscoord consumedHeight = GetConsumedHeight();
|
||||
nscoord consumedBSize = GetConsumedBSize();
|
||||
|
||||
// The effective computed height is the height of the current continuation
|
||||
// of the column set frame. This should be the same as the computed height
|
||||
// if we have an unconstrained available height.
|
||||
nscoord computedHeight = GetEffectiveComputedHeight(aReflowState,
|
||||
consumedHeight);
|
||||
nscoord computedBSize = GetEffectiveComputedBSize(aReflowState,
|
||||
consumedBSize);
|
||||
nscoord colHeight = GetAvailableContentHeight(aReflowState);
|
||||
|
||||
if (aReflowState.ComputedHeight() != NS_INTRINSICSIZE) {
|
||||
@ -298,7 +298,7 @@ nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState,
|
||||
#endif
|
||||
ReflowConfig config = { numColumns, colWidth, expectedWidthLeftOver, colGap,
|
||||
colHeight, isBalancing, knownFeasibleHeight,
|
||||
knownInfeasibleHeight, computedHeight, consumedHeight };
|
||||
knownInfeasibleHeight, computedBSize, consumedBSize };
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -2748,10 +2748,10 @@ nsFlexContainerFrame::GetMainSizeFromReflowState(
|
||||
if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) {
|
||||
// Horizontal case is easy -- our main size is our computed width
|
||||
// (which is already resolved).
|
||||
return aReflowState.ComputedWidth();
|
||||
return aReflowState.ComputedISize();
|
||||
}
|
||||
|
||||
return GetEffectiveComputedHeight(aReflowState);
|
||||
return GetEffectiveComputedBSize(aReflowState);
|
||||
}
|
||||
|
||||
// Returns the largest outer hypothetical main-size of any line in |aLines|.
|
||||
@ -2837,20 +2837,20 @@ nsFlexContainerFrame::ComputeCrossSize(const nsHTMLReflowState& aReflowState,
|
||||
// Cross axis is horizontal: our cross size is our computed width
|
||||
// (which is already resolved).
|
||||
*aIsDefinite = true;
|
||||
return aReflowState.ComputedWidth();
|
||||
return aReflowState.ComputedISize();
|
||||
}
|
||||
|
||||
nscoord effectiveComputedHeight = GetEffectiveComputedHeight(aReflowState);
|
||||
if (effectiveComputedHeight != NS_INTRINSICSIZE) {
|
||||
nscoord effectiveComputedBSize = GetEffectiveComputedBSize(aReflowState);
|
||||
if (effectiveComputedBSize != NS_INTRINSICSIZE) {
|
||||
// Cross-axis is vertical, and we have a fixed height:
|
||||
*aIsDefinite = true;
|
||||
if (aAvailableHeightForContent == NS_UNCONSTRAINEDSIZE ||
|
||||
effectiveComputedHeight < aAvailableHeightForContent) {
|
||||
effectiveComputedBSize < aAvailableHeightForContent) {
|
||||
// Not in a fragmenting context, OR no need to fragment because we have
|
||||
// more available height than we need. Either way, just use our fixed
|
||||
// height. (Note that the reflow state has already done the appropriate
|
||||
// min/max-height clamping.)
|
||||
return effectiveComputedHeight;
|
||||
return effectiveComputedBSize;
|
||||
}
|
||||
|
||||
// Fragmenting *and* our fixed height is too tall for available height:
|
||||
@ -2864,7 +2864,7 @@ nsFlexContainerFrame::ComputeCrossSize(const nsHTMLReflowState& aReflowState,
|
||||
if (aSumLineCrossSizes <= aAvailableHeightForContent) {
|
||||
return aAvailableHeightForContent;
|
||||
}
|
||||
return std::min(effectiveComputedHeight, aSumLineCrossSizes);
|
||||
return std::min(effectiveComputedBSize, aSumLineCrossSizes);
|
||||
}
|
||||
|
||||
// Cross axis is vertical and we have auto-height: shrink-wrap our line(s),
|
||||
|
@ -55,7 +55,7 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
nsMargin bp = aReflowState.ComputedPhysicalBorderPadding();
|
||||
ApplySkipSides(bp);
|
||||
nscoord contentHeight = GetEffectiveComputedHeight(aReflowState);
|
||||
nscoord contentHeight = GetEffectiveComputedBSize(aReflowState);
|
||||
if (contentHeight == NS_AUTOHEIGHT) {
|
||||
contentHeight = 0;
|
||||
}
|
||||
|
@ -240,6 +240,15 @@ public:
|
||||
return mBSize;
|
||||
}
|
||||
|
||||
// Set inline and block size from a LogicalSize, converting to our
|
||||
// writing mode as necessary.
|
||||
void SetSize(mozilla::WritingMode aWM, mozilla::LogicalSize aSize)
|
||||
{
|
||||
mozilla::LogicalSize convertedSize = aSize.ConvertTo(mWritingMode, aWM);
|
||||
mBSize = convertedSize.BSize(mWritingMode);
|
||||
mISize = convertedSize.ISize(mWritingMode);
|
||||
}
|
||||
|
||||
// Width and Height are physical dimensions, independent of writing mode.
|
||||
// Accessing these is slightly more expensive than accessing the logical
|
||||
// dimensions (once vertical writing mode support is enabled); as far as
|
||||
|
@ -243,8 +243,8 @@ nsLineBox::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
|
||||
str += nsPrintfCString("line %p: count=%d state=%s ",
|
||||
static_cast<const void*>(this), GetChildCount(),
|
||||
StateToString(cbuf, sizeof(cbuf)));
|
||||
if (IsBlock() && !GetCarriedOutBottomMargin().IsZero()) {
|
||||
str += nsPrintfCString("bm=%d ", GetCarriedOutBottomMargin().get());
|
||||
if (IsBlock() && !GetCarriedOutBEndMargin().IsZero()) {
|
||||
str += nsPrintfCString("bm=%d ", GetCarriedOutBEndMargin().get());
|
||||
}
|
||||
nsRect bounds = GetPhysicalBounds();
|
||||
str += nsPrintfCString("{%d,%d,%d,%d} ",
|
||||
@ -430,17 +430,17 @@ nsLineBox::RFindLineContaining(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
nsCollapsingMargin
|
||||
nsLineBox::GetCarriedOutBottomMargin() const
|
||||
nsLineBox::GetCarriedOutBEndMargin() const
|
||||
{
|
||||
NS_ASSERTION(IsBlock(),
|
||||
"GetCarriedOutBottomMargin called on non-block line.");
|
||||
"GetCarriedOutBEndMargin called on non-block line.");
|
||||
return (IsBlock() && mBlockData)
|
||||
? mBlockData->mCarriedOutBottomMargin
|
||||
? mBlockData->mCarriedOutBEndMargin
|
||||
: nsCollapsingMargin();
|
||||
}
|
||||
|
||||
bool
|
||||
nsLineBox::SetCarriedOutBottomMargin(nsCollapsingMargin aValue)
|
||||
nsLineBox::SetCarriedOutBEndMargin(nsCollapsingMargin aValue)
|
||||
{
|
||||
bool changed = false;
|
||||
if (IsBlock()) {
|
||||
@ -448,12 +448,12 @@ nsLineBox::SetCarriedOutBottomMargin(nsCollapsingMargin aValue)
|
||||
if (!mBlockData) {
|
||||
mBlockData = new ExtraBlockData(GetPhysicalBounds());
|
||||
}
|
||||
changed = aValue != mBlockData->mCarriedOutBottomMargin;
|
||||
mBlockData->mCarriedOutBottomMargin = aValue;
|
||||
changed = aValue != mBlockData->mCarriedOutBEndMargin;
|
||||
mBlockData->mCarriedOutBEndMargin = aValue;
|
||||
}
|
||||
else if (mBlockData) {
|
||||
changed = aValue != mBlockData->mCarriedOutBottomMargin;
|
||||
mBlockData->mCarriedOutBottomMargin = aValue;
|
||||
changed = aValue != mBlockData->mCarriedOutBEndMargin;
|
||||
mBlockData->mCarriedOutBEndMargin = aValue;
|
||||
MaybeFreeData();
|
||||
}
|
||||
}
|
||||
@ -471,7 +471,7 @@ nsLineBox::MaybeFreeData()
|
||||
mInlineData = nullptr;
|
||||
}
|
||||
}
|
||||
else if (mBlockData->mCarriedOutBottomMargin.IsZero()) {
|
||||
else if (mBlockData->mCarriedOutBEndMargin.IsZero()) {
|
||||
delete mBlockData;
|
||||
mBlockData = nullptr;
|
||||
}
|
||||
|
@ -427,10 +427,10 @@ public:
|
||||
return !IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
|
||||
}
|
||||
|
||||
// mCarriedOutBottomMargin value
|
||||
nsCollapsingMargin GetCarriedOutBottomMargin() const;
|
||||
// mCarriedOutBEndMargin value
|
||||
nsCollapsingMargin GetCarriedOutBEndMargin() const;
|
||||
// Returns true if the margin changed
|
||||
bool SetCarriedOutBottomMargin(nsCollapsingMargin aValue);
|
||||
bool SetCarriedOutBEndMargin(nsCollapsingMargin aValue);
|
||||
|
||||
// mFloats
|
||||
bool HasFloats() const {
|
||||
@ -647,10 +647,10 @@ public:
|
||||
struct ExtraBlockData : public ExtraData {
|
||||
ExtraBlockData(const nsRect& aBounds)
|
||||
: ExtraData(aBounds),
|
||||
mCarriedOutBottomMargin()
|
||||
mCarriedOutBEndMargin()
|
||||
{
|
||||
}
|
||||
nsCollapsingMargin mCarriedOutBottomMargin;
|
||||
nsCollapsingMargin mCarriedOutBEndMargin;
|
||||
};
|
||||
|
||||
struct ExtraInlineData : public ExtraData {
|
||||
|
@ -207,7 +207,7 @@ nsSplittableFrame::RemoveFromFlow(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsSplittableFrame::GetConsumedHeight() const
|
||||
nsSplittableFrame::GetConsumedBSize() const
|
||||
{
|
||||
nscoord height = 0;
|
||||
for (nsIFrame* prev = GetPrevInFlow(); prev; prev = prev->GetPrevInFlow()) {
|
||||
@ -217,22 +217,22 @@ nsSplittableFrame::GetConsumedHeight() const
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsSplittableFrame::GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState,
|
||||
nscoord aConsumedHeight) const
|
||||
nsSplittableFrame::GetEffectiveComputedBSize(const nsHTMLReflowState& aReflowState,
|
||||
nscoord aConsumedBSize) const
|
||||
{
|
||||
nscoord height = aReflowState.ComputedHeight();
|
||||
if (height == NS_INTRINSICSIZE) {
|
||||
nscoord bSize = aReflowState.ComputedBSize();
|
||||
if (bSize == NS_INTRINSICSIZE) {
|
||||
return NS_INTRINSICSIZE;
|
||||
}
|
||||
|
||||
if (aConsumedHeight == NS_INTRINSICSIZE) {
|
||||
aConsumedHeight = GetConsumedHeight();
|
||||
if (aConsumedBSize == NS_INTRINSICSIZE) {
|
||||
aConsumedBSize = GetConsumedBSize();
|
||||
}
|
||||
|
||||
height -= aConsumedHeight;
|
||||
bSize -= aConsumedBSize;
|
||||
|
||||
// We may have stretched the frame beyond its computed height. Oh well.
|
||||
return std::max(0, height);
|
||||
return std::max(0, bSize);
|
||||
}
|
||||
|
||||
int
|
||||
@ -258,10 +258,10 @@ nsSplittableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) co
|
||||
// height, though, then we're going to need a next-in-flow, it just hasn't
|
||||
// been created yet.
|
||||
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState->AvailableHeight()) {
|
||||
nscoord effectiveCH = this->GetEffectiveComputedHeight(*aReflowState);
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState->AvailableBSize()) {
|
||||
nscoord effectiveCH = this->GetEffectiveComputedBSize(*aReflowState);
|
||||
if (effectiveCH != NS_INTRINSICSIZE &&
|
||||
effectiveCH > aReflowState->AvailableHeight()) {
|
||||
effectiveCH > aReflowState->AvailableBSize()) {
|
||||
// Our content height is going to exceed our available height, so we're
|
||||
// going to need a next-in-flow.
|
||||
skip |= LOGICAL_SIDE_B_END;
|
||||
|
@ -83,14 +83,14 @@ protected:
|
||||
* O(N^2)! So, use this function with caution and minimize the number
|
||||
* of calls to this method.
|
||||
*/
|
||||
nscoord GetConsumedHeight() const;
|
||||
nscoord GetConsumedBSize() const;
|
||||
|
||||
/**
|
||||
* Retrieve the effective computed height of this frame, which is the computed
|
||||
* height, minus the height consumed by any previous in-flows.
|
||||
* Retrieve the effective computed block size of this frame, which is the
|
||||
* computed block size, minus the block size consumed by any previous in-flows.
|
||||
*/
|
||||
nscoord GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState,
|
||||
nscoord aConsumed = NS_INTRINSICSIZE) const;
|
||||
nscoord GetEffectiveComputedBSize(const nsHTMLReflowState& aReflowState,
|
||||
nscoord aConsumed = NS_INTRINSICSIZE) const;
|
||||
|
||||
/**
|
||||
* @see nsIFrame::GetLogicalSkipSides()
|
||||
|
@ -2837,7 +2837,8 @@ nsTableFrame::PlaceRepeatedFooter(nsTableReflowState& aReflowState,
|
||||
kidAvailSize.height = aFooterHeight;
|
||||
nsHTMLReflowState footerReflowState(presContext,
|
||||
aReflowState.reflowState,
|
||||
aTfoot, kidAvailSize,
|
||||
aTfoot,
|
||||
kidAvailSize,
|
||||
-1, -1,
|
||||
nsHTMLReflowState::CALLER_WILL_INIT);
|
||||
InitChildReflowState(footerReflowState);
|
||||
|
Loading…
Reference in New Issue
Block a user