Bug 526596. Make sure appends to an {ib} split coalesce blocks correctly if the appended frames start with a block and the trailing inline of the split is empty. r=roc

This commit is contained in:
Boris Zbarsky 2009-12-11 22:36:33 -08:00
parent 53aac44029
commit af198139a9
4 changed files with 83 additions and 8 deletions

View File

@ -1379,9 +1379,10 @@ PRBool IsBorderCollapse(nsIFrame* aFrame)
* Moves aFrameList from aOldParent to aNewParent. This updates the parent
* pointer of the frames in the list, reparents their views as needed, and sets
* the NS_FRAME_HAS_VIEW bit on aNewParent and its ancestors as needed. Then
* it sets the list as the initial child list on aNewParent. Note that this
* method differs from ReparentFrames in that it doesn't change the kids' style
* contexts.
* it sets the list as the initial child list on aNewParent, unless aNewParent
* either already has kids or has been reflowed; in that case it appends the
* new frames. Note that this method differs from ReparentFrames in that it
* doesn't change the kids' style contexts.
*/
// XXXbz Since this is only used for {ib} splits, could we just copy the view
// bits from aOldParent to aNewParent and then use the
@ -1397,10 +1398,6 @@ MoveChildrenTo(nsPresContext* aPresContext,
{
NS_PRECONDITION(aOldParent->GetParent() == aNewParent->GetParent(),
"Unexpected old and new parents");
NS_PRECONDITION(aNewParent->GetChildList(nsnull).IsEmpty(),
"New parent should have no kids");
NS_PRECONDITION(aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW,
"New parent shouldn't have been reflowed yet");
if (aNewParent->HasView() || aOldParent->HasView()) {
// Move the frames into the new view
@ -1424,7 +1421,12 @@ MoveChildrenTo(nsPresContext* aPresContext,
aNewParent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
}
aNewParent->SetInitialChildList(nsnull, aFrameList);
if (aNewParent->GetChildList(nsnull).IsEmpty() &&
(aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
aNewParent->SetInitialChildList(nsnull, aFrameList);
} else {
aNewParent->AppendFrames(nsnull, aFrameList);
}
}
// -----------------------------------------------------------
@ -5799,6 +5801,32 @@ nsCSSFrameConstructor::AppendFrames(nsFrameConstructorState& aState,
// of an {ib} split, we may need to create additional {ib} siblings to parent
// them.
if (!nextSibling && IsFrameSpecial(aParentFrame)) {
// When we get here, our frame list might start with a block. If it does
// so, and aParentFrame is an inline, and it and all its previous
// continuations have no siblings, then put the initial blocks from the
// frame list into the previous block of the {ib} split. Note that we
// didn't want to stop at the block part of the split when figuring out
// initial parent, because that could screw up float parenting; it's easier
// to do this little fixup here instead.
if (aFrameList.NotEmpty() && !IsInlineOutside(aFrameList.FirstChild())) {
// See whether out trailing inline is empty
nsIFrame* firstContinuation = aParentFrame->GetFirstContinuation();
if (firstContinuation->GetChildList(nsnull).IsEmpty()) {
// Our trailing inline is empty. Collect our starting blocks from
// aFrameList, get the right parent frame for them, and put them in.
nsFrameList::FrameLinkEnumerator firstNonBlockEnumerator =
FindFirstNonBlock(aFrameList);
nsFrameList blockKids = aFrameList.ExtractHead(firstNonBlockEnumerator);
NS_ASSERTION(blockKids.NotEmpty(), "No blocks?");
nsIFrame* prevBlock =
GetSpecialPrevSibling(firstContinuation)->GetLastContinuation();
NS_ASSERTION(prevBlock, "Should have previous block here");
MoveChildrenTo(aState.mPresContext, aParentFrame, prevBlock, blockKids);
}
}
// We want to put some of the frames into this inline frame.
nsFrameList::FrameLinkEnumerator firstBlockEnumerator(aFrameList);
FindFirstBlock(firstBlockEnumerator);

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css">
body > span { outline: 1px dotted black; }
body > span > span { display: block; width: 10em; }
</style>
</head>
<body>
<span><span>A</span><span>A</span></span>
</body>
</html>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css">
body > span { outline: 1px dotted black; }
body > span > span { display: block; width: 10em; }
</style>
<script>
function boom()
{
var n = document.getElementById("a");
n.parentNode.appendChild(n.cloneNode(true));
}
</script>
</head>
<body onload="boom();">
<span><span id="a">A</span></span>
</body>
</html>

View File

@ -80,3 +80,4 @@
== ignored-margins-2a.html ignored-margins-2-ref.html
== ignored-margins-2b.html ignored-margins-2-ref.html
== trailing-inline-with-continuations-1.html trailing-inline-with-continuations-1-ref.html
== append-to-empty-trailing-inline-1.html append-to-empty-trailing-inline-1-ref.html