Change mCBReflowState to mean the containing block of _this_ reflow state

instead of the containing block of kids.  Fix the containing block calculations
for various cases of absolutely positioned descendants of relatively positioned
inlines (eg make "right" and "bottom" work in those situations).  Bug 135082,
r+sr=dbaron
This commit is contained in:
bzbarsky%mit.edu 2004-04-24 17:56:23 +00:00
Родитель 1fba551310
Коммит 74c687f2ca
10 изменённых файлов: 206 добавлений и 202 удалений

Просмотреть файл

@ -170,9 +170,7 @@ struct nsHTMLReflowState {
nsLineLayout* mLineLayout;
// The appropriate reflow state for the containing block (for
// percentage widths, etc.) of any *children* of this reflow state's
// frame. In other words, this is the nearest containing block reflow
// state that is *either* this frame or an ancestor thereof.
// percentage widths, etc.) of this reflow state's frame.
const nsHTMLReflowState *mCBReflowState;
// The computed width specifies the frame's content area width, and it does
@ -263,13 +261,9 @@ struct nsHTMLReflowState {
static const char* ReasonToString(nsReflowReason aReason);
#endif
// A simple copy constructor. (It fixes up |mCBReflowState|, which
// can point to |this|, to point to the copy's |this|.)
nsHTMLReflowState(const nsHTMLReflowState& aOther);
// A simple assignment operator. It does the same fixups as the
// copy-consturctor.
nsHTMLReflowState& operator=(const nsHTMLReflowState& aOther);
// Note: The copy constructor is written by the compiler automatically. You
// can use that and then override specific values if you want, or you can
// call Init as desired...
// Initialize a <b>root</b> reflow state with a rendering context to
// use for measuring things.
@ -322,12 +316,10 @@ struct nsHTMLReflowState {
nsMargin* aBorder = nsnull,
nsMargin* aPadding = nsnull);
/**
* First find the containing block's reflow state using
* GetContainingBlockReflowState, then ask the containing block for
* it's content width using GetContentWidth
* Find the content width of the containing block of aReflowState
*/
static nscoord
GetContainingBlockContentWidth(const nsHTMLReflowState* aParentRS);
GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
/**
* Get the page box reflow state, starting from a frames
@ -385,7 +377,7 @@ protected:
nsIFrame* aPlaceholderFrame,
nsIFrame* aBlockFrame,
nsMargin& aBlockContentArea,
nsIFrame* aAbsoluteContainingBlockFrame,
const nsHTMLReflowState* cbrs,
nsHypotheticalBox& aHypotheticalBox);
void InitAbsoluteConstraints(nsIPresContext* aPresContext,

Просмотреть файл

@ -89,29 +89,6 @@ nsHTMLReflowState::ReasonToString(nsReflowReason aReason)
}
#endif
nsHTMLReflowState::nsHTMLReflowState(const nsHTMLReflowState& aOther)
{
// Use assignment operator below.
*this = aOther;
}
nsHTMLReflowState&
nsHTMLReflowState::operator=(const nsHTMLReflowState &aOther)
{
// Copy everything.
// XXX This won't work anymore if someone adds member variables that
// have nontrivial constructors or assignment operators (e.g.,
// nsCOMPtr).
memcpy(this, &aOther, sizeof(*this));
// Fix up the |mCBReflowState| member, which should continue to point
// to |this|.
if (aOther.mCBReflowState == &aOther)
mCBReflowState = this;
return *this;
}
// Initialize a <b>root</b> reflow state with a rendering context to
// use for measuring things.
nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
@ -338,17 +315,26 @@ nsHTMLReflowState::Init(nsIPresContext* aPresContext,
void nsHTMLReflowState::InitCBReflowState()
{
if (frame->IsContainingBlock()) {
// a block inside a table cell needs to use the table cell
if (parentReflowState) {
if (IS_TABLE_CELL(parentReflowState->frame->GetType())) {
mCBReflowState = parentReflowState;
return;
}
}
mCBReflowState = this;
if (!parentReflowState) {
mCBReflowState = nsnull;
return;
}
if (parentReflowState->frame->IsContainingBlock() ||
// Absolutely positioned frames should always be kids of the frames that
// determine their containing block
(NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE)) {
// a block inside a table cell needs to use the table cell
if (parentReflowState->parentReflowState &&
IS_TABLE_CELL(parentReflowState->parentReflowState->frame->GetType())) {
mCBReflowState = parentReflowState->parentReflowState;
} else {
mCBReflowState = parentReflowState;
}
return;
}
mCBReflowState = parentReflowState->mCBReflowState;
}
@ -360,9 +346,9 @@ nsHTMLReflowState::GetPageBoxReflowState(const nsHTMLReflowState* aParentRS)
}
nscoord
nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aParentRS)
nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState)
{
const nsHTMLReflowState* rs = aParentRS->mCBReflowState;
const nsHTMLReflowState* rs = aReflowState->mCBReflowState;
if (!rs)
return 0;
return rs->mComputedWidth;
@ -728,7 +714,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
nsIFrame* aBlockFrame,
nsMargin& aBlockContentArea,
nsIFrame* aAbsoluteContainingBlockFrame,
const nsHTMLReflowState* cbrs,
nsHypotheticalBox& aHypotheticalBox)
{
NS_ASSERTION(mStyleDisplay->mOriginalDisplay != NS_STYLE_DISPLAY_NONE,
@ -793,6 +779,8 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// Get the placeholder x-offset and y-offset in the coordinate
// space of the block frame that contains it
// XXXbz the placeholder is not fully reflown yet if our containing block is
// relatively positioned...
nsPoint placeholderOffset;
GetPlaceholderOffset(aPlaceholderFrame, aBlockFrame, placeholderOffset);
@ -815,7 +803,8 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// the line containing the placeholder frame, unless all the frames
// before it are empty. In that case, it would have been just before
// this line.
// XXXbz why the special-casing if we are the last line box?
// XXXbz the line box is not fully reflown yet if our containing block is
// relatively positioned...
if (lineBox != blockFrame->end_lines()) {
nsIFrame * firstFrame = lineBox->mFirstChild;
while (firstFrame != aPlaceholderFrame) {
@ -893,8 +882,20 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// The current coordinate space is that of the nearest block to the placeholder.
// Convert to the coordinate space of the absolute containing block
if (aBlockFrame != aAbsoluteContainingBlockFrame) {
nsIFrame* parent = aBlockFrame;
nsIFrame* absoluteContainingBlock = cbrs->frame;
if (aBlockFrame != absoluteContainingBlock) {
nsIFrame* parent;
nsIFrame* stop;
if (NS_FRAME_GET_TYPE(cbrs->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
// The absolute containing block is an inline frame... so it will be a
// descendant of aBlockFrame
parent = absoluteContainingBlock;
stop = aBlockFrame;
} else {
// aBlockFrame may be a descendant of absoluteContainingBlock
parent = aBlockFrame;
stop = absoluteContainingBlock;
}
do {
nsPoint origin = parent->GetPosition();
@ -904,20 +905,25 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// Move up the tree one level
parent = parent->GetParent();
} while (parent && (parent != aAbsoluteContainingBlockFrame));
} while (parent && parent != stop);
}
// The specified offsets are relative to the absolute containing block's padding
// edge, and our current values are relative to the border edge so translate
const nsStyleBorder* borderStyle =
aAbsoluteContainingBlockFrame->GetStyleBorder();
nsMargin border;
if (!borderStyle->GetBorder(border)) {
NS_NOTYETIMPLEMENTED("percentage border");
// The specified offsets are relative to the absolute containing block's
// padding edge or content edge, and our current values are relative to the
// border edge, so translate.
if (NS_FRAME_GET_TYPE(cbrs->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
// content edge
const nsMargin& borderPadding = cbrs->mComputedBorderPadding;
aHypotheticalBox.mLeft -= borderPadding.left;
aHypotheticalBox.mRight -= borderPadding.right;
aHypotheticalBox.mTop -= borderPadding.top;
} else {
// padding edge
nsMargin border = cbrs->mComputedBorderPadding - cbrs->mComputedPadding;
aHypotheticalBox.mLeft -= border.left;
aHypotheticalBox.mRight -= border.right;
aHypotheticalBox.mTop -= border.top;
}
aHypotheticalBox.mLeft -= border.left;
aHypotheticalBox.mRight -= border.left;
aHypotheticalBox.mTop -= border.top;
}
void
@ -951,7 +957,7 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
(eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()))) {
CalculateHypotheticalBox(aPresContext, placeholderFrame, blockFrame,
blockContentArea, cbrs->frame, hypotheticalBox);
blockContentArea, cbrs, hypotheticalBox);
}
// Initialize the 'left' and 'right' computed offsets
@ -1097,6 +1103,8 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
mComputedBorderPadding.right -
mComputedMargin.right - mComputedOffsets.right;
mComputedWidth = PR_MAX(mComputedWidth, 0);
AdjustComputedWidth(PR_FALSE);
// XXX If the direction is rtl then we need to reevaluate left...
@ -1246,6 +1254,8 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
mComputedBorderPadding.bottom -
mComputedMargin.bottom - mComputedOffsets.bottom;
mComputedHeight = PR_MAX(mComputedHeight, 0);
AdjustComputedHeight(PR_FALSE);
}
@ -1271,6 +1281,16 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
}
}
}
// Now that we've solved for our auto offsets and so forth, we need to adjust
// the offsets to what the rest of layout actually expects them to be. The
// offsets as computed now are relative to the parent's padding edge if the
// parent is a block and the parent's content edge if the parent is an
// inline. We need them to be relative to the parent's padding edge for
// nsAbsoluteContainer reflow to work right.
if (NS_FRAME_GET_TYPE(cbrs->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
mComputedOffsets += cbrs->mComputedPadding;
}
}
static PRBool
@ -1439,37 +1459,22 @@ nsHTMLReflowState::ComputeContainingBlockRectangle(nsIPresContext* aPre
if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
// See if the ancestor is block-level or inline-level
if (NS_FRAME_GET_TYPE(aContainingBlockRS->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
// The CSS2 spec says that if the ancestor is inline-level, the containing
// block depends on the 'direction' property of the ancestor. For direction
// 'ltr', it's the top and left of the content edges of the first box and
// the bottom and right content edges of the last box
//
// XXX This is a pain because it isn't top-down and it requires that we've
// completely reflowed the ancestor. It also isn't clear what happens when
// a relatively positioned ancestor is split across pages. So instead use
// the computed width and height of the nearest block-level ancestor
const nsHTMLReflowState* cbrs = aContainingBlockRS;
while (cbrs) {
nsCSSFrameType type = NS_FRAME_GET_TYPE(cbrs->mFrameType);
if ((NS_CSS_FRAME_TYPE_BLOCK == type) ||
(NS_CSS_FRAME_TYPE_FLOATING == type) ||
(NS_CSS_FRAME_TYPE_ABSOLUTE == type)) {
aContainingBlockWidth = cbrs->mComputedWidth;
aContainingBlockHeight = cbrs->mComputedHeight;
if (NS_CSS_FRAME_TYPE_ABSOLUTE == type) {
aContainingBlockWidth += cbrs->mComputedPadding.left +
cbrs->mComputedPadding.right;
aContainingBlockHeight += cbrs->mComputedPadding.top +
cbrs->mComputedPadding.bottom;
}
break;
}
cbrs = (const nsHTMLReflowState*)cbrs->parentReflowState; // XXX cast
}
// Base our size on the actual size of the frame. In cases when this is
// completely bogus (eg initial reflow), this code shouldn't even be
// called, since the code in nsPositionedInlineFrame::Reflow will pass in
// the containing block dimensions to our constructor.
// XXXbz we should be taking the in-flows into account too, but
// that's very hard.
aContainingBlockWidth = aContainingBlockRS->frame->GetRect().width -
(aContainingBlockRS->mComputedBorderPadding.left +
aContainingBlockRS->mComputedBorderPadding.right);
NS_ASSERTION(aContainingBlockWidth >= 0,
"Negative containing block width!");
aContainingBlockHeight = aContainingBlockRS->frame->GetRect().height -
(aContainingBlockRS->mComputedBorderPadding.top +
aContainingBlockRS->mComputedBorderPadding.bottom);
NS_ASSERTION(aContainingBlockHeight >= 0,
"Negative containing block height!");
} else {
// If the ancestor is block-level, the containing block is formed by the
// padding edge of the ancestor
@ -1584,7 +1589,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
mComputedMaxWidth = mComputedMaxHeight = NS_UNCONSTRAINEDSIZE;
} else {
// Get the containing block reflow state
const nsHTMLReflowState* cbrs = parentReflowState->mCBReflowState;
const nsHTMLReflowState* cbrs = mCBReflowState;
NS_ASSERTION(nsnull != cbrs, "no containing block");
// If we weren't given a containing block width and height, then

Просмотреть файл

@ -170,9 +170,7 @@ struct nsHTMLReflowState {
nsLineLayout* mLineLayout;
// The appropriate reflow state for the containing block (for
// percentage widths, etc.) of any *children* of this reflow state's
// frame. In other words, this is the nearest containing block reflow
// state that is *either* this frame or an ancestor thereof.
// percentage widths, etc.) of this reflow state's frame.
const nsHTMLReflowState *mCBReflowState;
// The computed width specifies the frame's content area width, and it does
@ -263,13 +261,9 @@ struct nsHTMLReflowState {
static const char* ReasonToString(nsReflowReason aReason);
#endif
// A simple copy constructor. (It fixes up |mCBReflowState|, which
// can point to |this|, to point to the copy's |this|.)
nsHTMLReflowState(const nsHTMLReflowState& aOther);
// A simple assignment operator. It does the same fixups as the
// copy-consturctor.
nsHTMLReflowState& operator=(const nsHTMLReflowState& aOther);
// Note: The copy constructor is written by the compiler automatically. You
// can use that and then override specific values if you want, or you can
// call Init as desired...
// Initialize a <b>root</b> reflow state with a rendering context to
// use for measuring things.
@ -322,12 +316,10 @@ struct nsHTMLReflowState {
nsMargin* aBorder = nsnull,
nsMargin* aPadding = nsnull);
/**
* First find the containing block's reflow state using
* GetContainingBlockReflowState, then ask the containing block for
* it's content width using GetContentWidth
* Find the content width of the containing block of aReflowState
*/
static nscoord
GetContainingBlockContentWidth(const nsHTMLReflowState* aParentRS);
GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
/**
* Get the page box reflow state, starting from a frames
@ -385,7 +377,7 @@ protected:
nsIFrame* aPlaceholderFrame,
nsIFrame* aBlockFrame,
nsMargin& aBlockContentArea,
nsIFrame* aAbsoluteContainingBlockFrame,
const nsHTMLReflowState* cbrs,
nsHypotheticalBox& aHypotheticalBox);
void InitAbsoluteConstraints(nsIPresContext* aPresContext,

Просмотреть файл

@ -1286,8 +1286,13 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
(eReflowReason_Incremental != aReflowState.reason ||
aReflowState.path->mReflowCommand ||
mRect != oldRect)) {
nscoord containingBlockWidth = -1;
nscoord containingBlockHeight = -1;
// The containing block for the abs pos kids is formed by our content edge.
nscoord containingBlockWidth = aDesiredSize.width -
(aReflowState.mComputedBorderPadding.left +
aReflowState.mComputedBorderPadding.right);
nscoord containingBlockHeight = aDesiredSize.height -
(aReflowState.mComputedBorderPadding.top +
aReflowState.mComputedBorderPadding.bottom);
nsRect childBounds;
rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState,

Просмотреть файл

@ -316,7 +316,7 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
}
else if (eStyleUnit_Percent == unit) {
nscoord width =
nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState->parentReflowState);
nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState);
if ((0 != width) && (NS_UNCONSTRAINEDSIZE != width)) {
indent = nscoord(mStyleText->mTextIndent.GetPercentValue() * width);
}

Просмотреть файл

@ -89,29 +89,6 @@ nsHTMLReflowState::ReasonToString(nsReflowReason aReason)
}
#endif
nsHTMLReflowState::nsHTMLReflowState(const nsHTMLReflowState& aOther)
{
// Use assignment operator below.
*this = aOther;
}
nsHTMLReflowState&
nsHTMLReflowState::operator=(const nsHTMLReflowState &aOther)
{
// Copy everything.
// XXX This won't work anymore if someone adds member variables that
// have nontrivial constructors or assignment operators (e.g.,
// nsCOMPtr).
memcpy(this, &aOther, sizeof(*this));
// Fix up the |mCBReflowState| member, which should continue to point
// to |this|.
if (aOther.mCBReflowState == &aOther)
mCBReflowState = this;
return *this;
}
// Initialize a <b>root</b> reflow state with a rendering context to
// use for measuring things.
nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
@ -338,17 +315,26 @@ nsHTMLReflowState::Init(nsIPresContext* aPresContext,
void nsHTMLReflowState::InitCBReflowState()
{
if (frame->IsContainingBlock()) {
// a block inside a table cell needs to use the table cell
if (parentReflowState) {
if (IS_TABLE_CELL(parentReflowState->frame->GetType())) {
mCBReflowState = parentReflowState;
return;
}
}
mCBReflowState = this;
if (!parentReflowState) {
mCBReflowState = nsnull;
return;
}
if (parentReflowState->frame->IsContainingBlock() ||
// Absolutely positioned frames should always be kids of the frames that
// determine their containing block
(NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE)) {
// a block inside a table cell needs to use the table cell
if (parentReflowState->parentReflowState &&
IS_TABLE_CELL(parentReflowState->parentReflowState->frame->GetType())) {
mCBReflowState = parentReflowState->parentReflowState;
} else {
mCBReflowState = parentReflowState;
}
return;
}
mCBReflowState = parentReflowState->mCBReflowState;
}
@ -360,9 +346,9 @@ nsHTMLReflowState::GetPageBoxReflowState(const nsHTMLReflowState* aParentRS)
}
nscoord
nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aParentRS)
nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState)
{
const nsHTMLReflowState* rs = aParentRS->mCBReflowState;
const nsHTMLReflowState* rs = aReflowState->mCBReflowState;
if (!rs)
return 0;
return rs->mComputedWidth;
@ -728,7 +714,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
nsIFrame* aBlockFrame,
nsMargin& aBlockContentArea,
nsIFrame* aAbsoluteContainingBlockFrame,
const nsHTMLReflowState* cbrs,
nsHypotheticalBox& aHypotheticalBox)
{
NS_ASSERTION(mStyleDisplay->mOriginalDisplay != NS_STYLE_DISPLAY_NONE,
@ -793,6 +779,8 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// Get the placeholder x-offset and y-offset in the coordinate
// space of the block frame that contains it
// XXXbz the placeholder is not fully reflown yet if our containing block is
// relatively positioned...
nsPoint placeholderOffset;
GetPlaceholderOffset(aPlaceholderFrame, aBlockFrame, placeholderOffset);
@ -815,7 +803,8 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// the line containing the placeholder frame, unless all the frames
// before it are empty. In that case, it would have been just before
// this line.
// XXXbz why the special-casing if we are the last line box?
// XXXbz the line box is not fully reflown yet if our containing block is
// relatively positioned...
if (lineBox != blockFrame->end_lines()) {
nsIFrame * firstFrame = lineBox->mFirstChild;
while (firstFrame != aPlaceholderFrame) {
@ -893,8 +882,20 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// The current coordinate space is that of the nearest block to the placeholder.
// Convert to the coordinate space of the absolute containing block
if (aBlockFrame != aAbsoluteContainingBlockFrame) {
nsIFrame* parent = aBlockFrame;
nsIFrame* absoluteContainingBlock = cbrs->frame;
if (aBlockFrame != absoluteContainingBlock) {
nsIFrame* parent;
nsIFrame* stop;
if (NS_FRAME_GET_TYPE(cbrs->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
// The absolute containing block is an inline frame... so it will be a
// descendant of aBlockFrame
parent = absoluteContainingBlock;
stop = aBlockFrame;
} else {
// aBlockFrame may be a descendant of absoluteContainingBlock
parent = aBlockFrame;
stop = absoluteContainingBlock;
}
do {
nsPoint origin = parent->GetPosition();
@ -904,20 +905,25 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsIPresContext* aPresContext,
// Move up the tree one level
parent = parent->GetParent();
} while (parent && (parent != aAbsoluteContainingBlockFrame));
} while (parent && parent != stop);
}
// The specified offsets are relative to the absolute containing block's padding
// edge, and our current values are relative to the border edge so translate
const nsStyleBorder* borderStyle =
aAbsoluteContainingBlockFrame->GetStyleBorder();
nsMargin border;
if (!borderStyle->GetBorder(border)) {
NS_NOTYETIMPLEMENTED("percentage border");
// The specified offsets are relative to the absolute containing block's
// padding edge or content edge, and our current values are relative to the
// border edge, so translate.
if (NS_FRAME_GET_TYPE(cbrs->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
// content edge
const nsMargin& borderPadding = cbrs->mComputedBorderPadding;
aHypotheticalBox.mLeft -= borderPadding.left;
aHypotheticalBox.mRight -= borderPadding.right;
aHypotheticalBox.mTop -= borderPadding.top;
} else {
// padding edge
nsMargin border = cbrs->mComputedBorderPadding - cbrs->mComputedPadding;
aHypotheticalBox.mLeft -= border.left;
aHypotheticalBox.mRight -= border.right;
aHypotheticalBox.mTop -= border.top;
}
aHypotheticalBox.mLeft -= border.left;
aHypotheticalBox.mRight -= border.left;
aHypotheticalBox.mTop -= border.top;
}
void
@ -951,7 +957,7 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
(eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()))) {
CalculateHypotheticalBox(aPresContext, placeholderFrame, blockFrame,
blockContentArea, cbrs->frame, hypotheticalBox);
blockContentArea, cbrs, hypotheticalBox);
}
// Initialize the 'left' and 'right' computed offsets
@ -1097,6 +1103,8 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
mComputedBorderPadding.right -
mComputedMargin.right - mComputedOffsets.right;
mComputedWidth = PR_MAX(mComputedWidth, 0);
AdjustComputedWidth(PR_FALSE);
// XXX If the direction is rtl then we need to reevaluate left...
@ -1246,6 +1254,8 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
mComputedBorderPadding.bottom -
mComputedMargin.bottom - mComputedOffsets.bottom;
mComputedHeight = PR_MAX(mComputedHeight, 0);
AdjustComputedHeight(PR_FALSE);
}
@ -1271,6 +1281,16 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext* aPresContext,
}
}
}
// Now that we've solved for our auto offsets and so forth, we need to adjust
// the offsets to what the rest of layout actually expects them to be. The
// offsets as computed now are relative to the parent's padding edge if the
// parent is a block and the parent's content edge if the parent is an
// inline. We need them to be relative to the parent's padding edge for
// nsAbsoluteContainer reflow to work right.
if (NS_FRAME_GET_TYPE(cbrs->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
mComputedOffsets += cbrs->mComputedPadding;
}
}
static PRBool
@ -1439,37 +1459,22 @@ nsHTMLReflowState::ComputeContainingBlockRectangle(nsIPresContext* aPre
if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
// See if the ancestor is block-level or inline-level
if (NS_FRAME_GET_TYPE(aContainingBlockRS->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
// The CSS2 spec says that if the ancestor is inline-level, the containing
// block depends on the 'direction' property of the ancestor. For direction
// 'ltr', it's the top and left of the content edges of the first box and
// the bottom and right content edges of the last box
//
// XXX This is a pain because it isn't top-down and it requires that we've
// completely reflowed the ancestor. It also isn't clear what happens when
// a relatively positioned ancestor is split across pages. So instead use
// the computed width and height of the nearest block-level ancestor
const nsHTMLReflowState* cbrs = aContainingBlockRS;
while (cbrs) {
nsCSSFrameType type = NS_FRAME_GET_TYPE(cbrs->mFrameType);
if ((NS_CSS_FRAME_TYPE_BLOCK == type) ||
(NS_CSS_FRAME_TYPE_FLOATING == type) ||
(NS_CSS_FRAME_TYPE_ABSOLUTE == type)) {
aContainingBlockWidth = cbrs->mComputedWidth;
aContainingBlockHeight = cbrs->mComputedHeight;
if (NS_CSS_FRAME_TYPE_ABSOLUTE == type) {
aContainingBlockWidth += cbrs->mComputedPadding.left +
cbrs->mComputedPadding.right;
aContainingBlockHeight += cbrs->mComputedPadding.top +
cbrs->mComputedPadding.bottom;
}
break;
}
cbrs = (const nsHTMLReflowState*)cbrs->parentReflowState; // XXX cast
}
// Base our size on the actual size of the frame. In cases when this is
// completely bogus (eg initial reflow), this code shouldn't even be
// called, since the code in nsPositionedInlineFrame::Reflow will pass in
// the containing block dimensions to our constructor.
// XXXbz we should be taking the in-flows into account too, but
// that's very hard.
aContainingBlockWidth = aContainingBlockRS->frame->GetRect().width -
(aContainingBlockRS->mComputedBorderPadding.left +
aContainingBlockRS->mComputedBorderPadding.right);
NS_ASSERTION(aContainingBlockWidth >= 0,
"Negative containing block width!");
aContainingBlockHeight = aContainingBlockRS->frame->GetRect().height -
(aContainingBlockRS->mComputedBorderPadding.top +
aContainingBlockRS->mComputedBorderPadding.bottom);
NS_ASSERTION(aContainingBlockHeight >= 0,
"Negative containing block height!");
} else {
// If the ancestor is block-level, the containing block is formed by the
// padding edge of the ancestor
@ -1584,7 +1589,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
mComputedMaxWidth = mComputedMaxHeight = NS_UNCONSTRAINEDSIZE;
} else {
// Get the containing block reflow state
const nsHTMLReflowState* cbrs = parentReflowState->mCBReflowState;
const nsHTMLReflowState* cbrs = mCBReflowState;
NS_ASSERTION(nsnull != cbrs, "no containing block");
// If we weren't given a containing block width and height, then

Просмотреть файл

@ -1286,8 +1286,13 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
(eReflowReason_Incremental != aReflowState.reason ||
aReflowState.path->mReflowCommand ||
mRect != oldRect)) {
nscoord containingBlockWidth = -1;
nscoord containingBlockHeight = -1;
// The containing block for the abs pos kids is formed by our content edge.
nscoord containingBlockWidth = aDesiredSize.width -
(aReflowState.mComputedBorderPadding.left +
aReflowState.mComputedBorderPadding.right);
nscoord containingBlockHeight = aDesiredSize.height -
(aReflowState.mComputedBorderPadding.top +
aReflowState.mComputedBorderPadding.bottom);
nsRect childBounds;
rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState,

Просмотреть файл

@ -316,7 +316,7 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
}
else if (eStyleUnit_Percent == unit) {
nscoord width =
nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState->parentReflowState);
nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState);
if ((0 != width) && (NS_UNCONSTRAINEDSIZE != width)) {
indent = nscoord(mStyleText->mTextIndent.GetPercentValue() * width);
}

Просмотреть файл

@ -525,7 +525,7 @@ GetContainingBlockSize(const nsHTMLReflowState& aOuterRS)
{
nsSize size(0,0);
const nsHTMLReflowState* containRS =
aOuterRS.parentReflowState->mCBReflowState;
aOuterRS.mCBReflowState;
if (containRS) {
size.width = containRS->mComputedWidth;

Просмотреть файл

@ -525,7 +525,7 @@ GetContainingBlockSize(const nsHTMLReflowState& aOuterRS)
{
nsSize size(0,0);
const nsHTMLReflowState* containRS =
aOuterRS.parentReflowState->mCBReflowState;
aOuterRS.mCBReflowState;
if (containRS) {
size.width = containRS->mComputedWidth;