Bug 480452. Make {ib} splits behave the same way with regard to margins, borders, and padding as inline frames that just have a line-break happening inside them do. r+sr=dbaron

This commit is contained in:
Boris Zbarsky 2009-05-11 22:04:58 -04:00
parent 4ce33a6c6d
commit 56ee16413d
19 changed files with 272 additions and 14 deletions

View File

@ -842,6 +842,29 @@ nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame,
(isLTR ? !firstFrameState->mHasContOnNextLines
: !firstFrameState->mHasContOnPrevLines);
if ((aIsLeftMost || aIsRightMost) &&
(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
// For ib splits, don't treat the first part as endmost or the
// last part as startmost.
if (nsLayoutUtils::FrameIsInFirstPartOfIBSplit(aFrame)) {
// We are not endmost
if (isLTR) {
aIsRightMost = PR_FALSE;
} else {
aIsLeftMost = PR_FALSE;
}
} else {
NS_ASSERTION(nsLayoutUtils::FrameIsInLastPartOfIBSplit(aFrame),
"How did that happen?");
// We are not startmost
if (isLTR) {
aIsLeftMost = PR_FALSE;
} else {
aIsRightMost = PR_FALSE;
}
}
}
// Reduce number of remaining frames of the continuation chain on the line.
firstFrameState->mFrameCount--;
}
@ -964,7 +987,8 @@ nsBidiPresUtils::RepositionInlineFrames(nsIFrame* aFirstChild) const
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
// have been reflowed, which is required for GetUsedMargin/Border/Padding
nsMargin margin = aFirstChild->GetUsedMargin();
if (!aFirstChild->GetPrevContinuation())
if (!aFirstChild->GetPrevContinuation() &&
!nsLayoutUtils::FrameIsInLastPartOfIBSplit(aFirstChild))
leftSpace = isLTR ? margin.left : margin.right;
nscoord left = aFirstChild->GetPosition().x - leftSpace;

View File

@ -499,9 +499,9 @@ SetFrameIsSpecial(nsIFrame* aFrame, nsIFrame* aSpecialSibling)
}
if (aSpecialSibling) {
// We should be the first-in-flow
NS_ASSERTION(!aFrame->GetPrevInFlow(),
"assigning special sibling to other than first-in-flow!");
// We should be the first continuation
NS_ASSERTION(!aFrame->GetPrevContinuation(),
"assigning special sibling to other than first continuation!");
// Store the "special sibling" (if we were given one) with the
// first frame in the flow.

View File

@ -1004,6 +1004,26 @@ public:
* @param aFrame The nsIFrame object, which uses text fragment data.
*/
static nsTextFragment* GetTextFragmentForPrinting(const nsIFrame* aFrame);
/**
* Return whether aFrame is an inline frame in the first part of an {ib}
* split.
*/
static PRBool FrameIsInFirstPartOfIBSplit(const nsIFrame* aFrame) {
return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
!aFrame->GetFirstContinuation()->
GetProperty(nsGkAtoms::IBSplitSpecialPrevSibling);
}
/**
* Return whether aFrame is an inline frame in the last part of an {ib}
* split.
*/
static PRBool FrameIsInLastPartOfIBSplit(const nsIFrame* aFrame) {
return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
!aFrame->GetFirstContinuation()->
GetProperty(nsGkAtoms::IBSplitSpecialSibling);
}
};
class nsAutoDisableGetUsedXAssertions

View File

@ -1,3 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -410,7 +411,10 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
nsLineLayout* lineLayout = aReflowState.mLineLayout;
PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
nscoord leftEdge = 0;
if (nsnull == GetPrevContinuation()) {
// Don't offset by our start borderpadding if we have a prev continuation or
// if we're in the last part of an {ib} split.
if (!GetPrevContinuation() &&
!nsLayoutUtils::FrameIsInLastPartOfIBSplit(this)) {
leftEdge = ltr ? aReflowState.mComputedBorderPadding.left
: aReflowState.mComputedBorderPadding.right;
}
@ -557,12 +561,28 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
// whitespace in an inline element don't affect the line-height.
aMetrics.width = lineLayout->EndSpan(this);
// Compute final width
if (nsnull == GetPrevContinuation()) {
// Compute final width.
// Make sure to not include our start border and padding if we have a prev
// continuation or if we're in the last part of an {ib} split.
if (!GetPrevContinuation() &&
!nsLayoutUtils::FrameIsInLastPartOfIBSplit(this)) {
aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.left
: aReflowState.mComputedBorderPadding.right;
}
if (NS_FRAME_IS_COMPLETE(aStatus) && (!GetNextContinuation() || GetNextInFlow())) {
/*
* We want to only apply the end border and padding if we're the last
* continuation and not in the first part of an {ib} split. To be the last
* continuation we have to be complete (so that we won't get a next-in-flow)
* and have no non-fluid continuations.
*
* FIXME the check for non-fluid continuations is not quite correct in the
* code (though the comment above describes it correctly); see bug 492469.
*/
if (NS_FRAME_IS_COMPLETE(aStatus) &&
(!GetNextContinuation() || GetNextInFlow()) &&
!nsLayoutUtils::FrameIsInFirstPartOfIBSplit(this)) {
aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.right
: aReflowState.mComputedBorderPadding.left;
}
@ -791,6 +811,28 @@ nsInlineFrame::GetSkipSides() const
// edge border render.
}
}
if (GetStateBits() & NS_FRAME_IS_SPECIAL) {
// The first part of an {ib} split should always skip the "end" side (as
// determined by this frame's direction) and the last part of such a split
// should alwas skip the "start" side. But figuring out which part of the
// split we are involves getting our first continuation, which might be
// expensive. So don't bother if we already have the relevant bits set.
PRBool ltr = (NS_STYLE_DIRECTION_LTR == GetStyleVisibility()->mDirection);
PRIntn startBit = (1 << (ltr ? NS_SIDE_LEFT : NS_SIDE_RIGHT));
PRIntn endBit = (1 << (ltr ? NS_SIDE_RIGHT : NS_SIDE_LEFT));
if (((startBit | endBit) & skip) != (startBit | endBit)) {
// We're missing one of the skip bits, so check whether we need to set it.
if (nsLayoutUtils::FrameIsInFirstPartOfIBSplit(this)) {
skip |= endBit;
} else {
NS_ASSERTION(nsLayoutUtils::FrameIsInLastPartOfIBSplit(this),
"How did that happen?");
skip |= startBit;
}
}
}
return skip;
}

View File

@ -1089,8 +1089,13 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd,
// XXXwaterson probably not the right way to get this; e.g., embeddings, etc.
PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
// Only apply start-margin on the first-in flow for inline frames
if (pfd->mFrame->GetPrevContinuation()) {
// Only apply start-margin on the first-in flow for inline frames,
// and make sure to not apply it to the last part of an ib split.
// Note that the ib special sibling annotations only live on the
// first continuation, but we don't want to apply the start margin
// for later continuations anyway.
if (pfd->mFrame->GetPrevContinuation() ||
nsLayoutUtils::FrameIsInLastPartOfIBSplit(pfd->mFrame)) {
// Zero this out so that when we compute the max-element-width of
// the frame we will properly avoid adding in the starting margin.
if (ltr)
@ -1156,11 +1161,23 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
// XXXwaterson this is probably not exactly right; e.g., embeddings, etc.
PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) || (pfd->mFrame->GetNextContinuation() && !pfd->mFrame->GetNextInFlow()))
/*
* We want to only apply the end margin if we're the last continuation and
* not in the first part of an {ib} split. In all other cases we want to
* zero it out. That means zeroing it out if any of these conditions hold:
* 1) The frame is not complete (in this case it will get a next-in-flow)
* 2) The frame is complete but has a non-fluid continuation. Note that if
* it has a fluid continuation, that continuation will get destroyed
* later, so we don't want to drop the end-margin in that case.
* // FIXME: bug 492469
* 3) The frame is in the first part of an {ib} split.
*
* However, none of that applies if this is a letter frame (XXXbz why?)
*/
if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
(pfd->mFrame->GetNextContinuation() && !pfd->mFrame->GetNextInFlow()) ||
nsLayoutUtils::FrameIsInFirstPartOfIBSplit(pfd->mFrame))
&& !pfd->GetFlag(PFD_ISLETTERFRAME)) {
// Only apply end margin for the last-in-flow. Zero this out so
// that when we compute the max-element-width of the frame we
// will properly avoid adding in the end margin.
if (ltr)
pfd->mMargin.right = 0;
else

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<body>
<div>
<span style="border: 2px solid; border-right-style: none; padding-left: 5px; margin-left: 30px;">One</span>
<br>
<span style="border: 2px solid; border-left-style: none; padding-right: 10px; margin-right: 60px;">Two</span>
</div>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<body>
<div>
<span style="border: 2px solid; border-left-style: none; padding-right: 10px; margin-right: 60px;">One</span>
<br>
<span style="border: 2px solid; border-right-style: none; padding-left: 5px; margin-left: 30px;">Two</span>
</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div><span>One<br>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div><span>One<div></div>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div class="r"><span class="l">One<div></div>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div class="r"><span class="l">One<br>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,8 @@
== ltr-basic.html left-ltr-ref.html
== rtl-basic.html right-rtl-ref.html
== rtl-span-only.html left-rtl-ref.html
== ltr-span-only.html right-ltr-ref.html
== ltr-ib.html left-ltr-ref.html
== rtl-ib.html right-rtl-ref.html
== rtl-span-only-ib.html left-rtl-ref.html
== ltr-span-only-ib.html right-ltr-ref.html

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<body>
<div style="direction: rtl">
<span style="border: 2px solid; border-right-style: none; padding-left: 5px; margin-left: 30px;">One</span>
<br>
<span style="border: 2px solid; border-left-style: none; padding-right: 10px; margin-right: 60px;">Two</span>
</div>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<body>
<div style="direction: rtl">
<span style="border: 2px solid; border-left-style: none; padding-right: 10px; margin-right: 60px;">One</span>
<br>
<span style="border: 2px solid; border-right-style: none; padding-left: 5px; margin-left: 30px;">Two</span>
</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div class="r"><span>One<br>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div class="r"><span>One<div></div>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div><span class="r">One<div></div>Two</span></div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
.r { direction: rtl; }
.l { direction: ltr; }
span { border: 2px solid; padding: 0 10px 0 5px; margin: 0 60px 0 30px; }
</style>
</head>
<body>
<div><span class="r">One<br>Two</span></div>
</body>
</html>

View File

@ -83,6 +83,9 @@ include image/reftest.list
# image-region/
include image-region/reftest.list
# inline borders and padding
include inline-borderpadding/reftest.list
# line-breaking/
include line-breaking/reftest.list