зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
1fba551310
Коммит
74c687f2ca
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче