Bug 425981. Make first-letter frame wrapping build its own frame constructor state to ensure it's for the correct place in the frame tree. r+sr=bzbarsky

--HG--
extra : rebase_source : 7dd5de3f6b2a9e83994d7023d4cfafce205e9376
This commit is contained in:
Robert O'Callahan 2009-01-08 21:07:51 +13:00
parent a984a545e8
commit f708c8026e
4 changed files with 62 additions and 41 deletions

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
div:first-letter { float: left; }
</style>
<script>
function boom()
{
var v = document.getElementById("v");
var t = v.firstChild;
v.appendChild(document.createTextNode(" "));
v.removeChild(t);
}
</script>
</head>
<body onload="boom();"><div id="v" style="-moz-column-count: 2; width: 1px;">a b</div></body>
</html>

View File

@ -122,6 +122,7 @@ load 420213-1.html
load 420651-1.xhtml
load 421203-1.xul
load 423107-1.xhtml
load 425981-1.html
load 428448-1.html
load 429088-1.html
load 429088-2.html

View File

@ -8494,7 +8494,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
// Recover first-letter frames
if (haveFirstLetterStyle) {
RecoverLetterFrames(state, containingBlock);
RecoverLetterFrames(containingBlock);
}
#ifdef DEBUG
@ -8935,7 +8935,7 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
if (haveFirstLetterStyle) {
// Recover the letter frames for the containing block when
// it has first-letter style.
RecoverLetterFrames(state, state.mFloatedItems.containingBlock);
RecoverLetterFrames(state.mFloatedItems.containingBlock);
}
#ifdef DEBUG
@ -9379,7 +9379,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
GetAbsoluteContainingBlock(parentFrame),
containingBlock);
RecoverLetterFrames(state, containingBlock);
RecoverLetterFrames(containingBlock);
}
#ifdef DEBUG
@ -9678,7 +9678,7 @@ nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
GetAbsoluteContainingBlock(frame),
block, nsnull);
RecoverLetterFrames(state, block);
RecoverLetterFrames(block);
}
}
@ -11254,7 +11254,7 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
"can't be both block and box");
if (haveFirstLetterStyle) {
rv = WrapFramesInFirstLetterFrame(aState, aContent, aFrame, aFrameItems);
rv = WrapFramesInFirstLetterFrame(aContent, aFrame, aFrameItems);
}
if (haveFirstLineStyle) {
rv = WrapFramesInFirstLineFrame(aState, aContent, aFrame, aFrameItems);
@ -11314,6 +11314,13 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
// Special routine to handle placing a list of frames into a block
// frame that has first-line style. The routine ensures that the first
// collection of inline frames end up in a first-line frame.
// NOTE: aState may have containing block information related to a
// different part of the frame tree than where the first line occurs.
// In particular aState may be set up for where ContentInserted or
// ContentAppended is inserting content, which may be some
// non-first-in-flow continuation of the block to which the first-line
// belongs. So this function needs to be careful about how it uses
// aState.
nsresult
nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
nsFrameConstructorState& aState,
@ -11779,8 +11786,7 @@ nsCSSFrameConstructor::CreateFloatingLetterFrame(
* a child of aParentFrame.
*/
nsresult
nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsCSSFrameConstructor::CreateLetterFrame(nsIFrame* aBlockFrame,
nsIContent* aTextContent,
nsIFrame* aParentFrame,
nsFrameItems& aResult)
@ -11795,13 +11801,10 @@ nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
nsFrame::CorrectStyleParentFrame(aParentFrame,
nsCSSPseudoElements::firstLetter)->
GetStyleContext();
// Use content from containing block so that we can actually
// find a matching style rule.
nsIContent* blockContent =
aState.mFloatedItems.containingBlock->GetContent();
NS_ASSERTION(blockContent == aBlockFrame->GetContent(),
"Unexpected block content");
nsIContent* blockContent = aBlockFrame->GetContent();
// Create first-letter style rule
nsRefPtr<nsStyleContext> sc = GetFirstLetterStyle(blockContent,
@ -11814,11 +11817,17 @@ nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
// pass a temporary stylecontext, the correct one will be set later
nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
NS_ASSERTION(aBlockFrame == GetFloatContainingBlock(aParentFrame),
"Containing block is confused");
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
GetAbsoluteContainingBlock(aParentFrame),
aBlockFrame);
// Create the right type of first-letter frame
const nsStyleDisplay* display = sc->GetStyleDisplay();
if (display->IsFloating()) {
// Make a floating first-letter frame
CreateFloatingLetterFrame(aState, aBlockFrame, aTextContent, textFrame,
CreateFloatingLetterFrame(state, aBlockFrame, aTextContent, textFrame,
blockContent, aParentFrame,
sc, aResult);
}
@ -11833,7 +11842,7 @@ nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
nsIContent* letterContent = aTextContent->GetParent();
letterFrame->Init(letterContent, aParentFrame, nsnull);
InitAndRestoreFrame(aState, aTextContent, letterFrame, nsnull,
InitAndRestoreFrame(state, aTextContent, letterFrame, nsnull,
textFrame);
letterFrame->SetInitialChildList(nsnull, textFrame);
@ -11848,7 +11857,6 @@ nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
nsresult
nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsFrameConstructorState& aState,
nsIContent* aBlockContent,
nsIFrame* aBlockFrame,
nsFrameItems& aBlockFrames)
@ -11862,7 +11870,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsIFrame* prevFrame = nsnull;
nsFrameItems letterFrames;
PRBool stopLooking = PR_FALSE;
rv = WrapFramesInFirstLetterFrame(aState, aBlockFrame, aBlockFrame,
rv = WrapFramesInFirstLetterFrame(aBlockFrame, aBlockFrame,
aBlockFrames.childList,
&parentFrame, &textFrame, &prevFrame,
letterFrames, &stopLooking);
@ -11894,7 +11902,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
}
else {
// Take the old textFrame out of the inline parents child list
::DeletingFrameSubtree(aState.mFrameManager, textFrame);
::DeletingFrameSubtree(mPresShell->FrameManager(), textFrame);
parentFrame->RemoveFrame(nsnull, textFrame);
// Insert in the letter frame(s)
@ -11907,7 +11915,6 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsresult
nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsIFrame* aParentFrame,
nsIFrame* aParentFrameList,
@ -11931,7 +11938,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsIContent* textContent = frame->GetContent();
if (IsFirstLetterContent(textContent)) {
// Create letter frame to wrap up the text
rv = CreateLetterFrame(aState, aBlockFrame, textContent,
rv = CreateLetterFrame(aBlockFrame, textContent,
aParentFrame, aLetterFrames);
if (NS_FAILED(rv)) {
return rv;
@ -11947,7 +11954,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
}
else if (IsInlineFrame(frame) && frameType != nsGkAtoms::brFrame) {
nsIFrame* kids = frame->GetFirstChild(nsnull);
WrapFramesInFirstLetterFrame(aState, aBlockFrame, frame, kids,
WrapFramesInFirstLetterFrame(aBlockFrame, frame, kids,
aModifiedParent, aTextFrame,
aPrevFrame, aLetterFrames, aStopLooking);
if (*aStopLooking) {
@ -12177,8 +12184,7 @@ nsCSSFrameConstructor::RemoveLetterFrames(nsPresContext* aPresContext,
// Fixup the letter frame situation for the given block
nsresult
nsCSSFrameConstructor::RecoverLetterFrames(nsFrameConstructorState& aState,
nsIFrame* aBlockFrame)
nsCSSFrameConstructor::RecoverLetterFrames(nsIFrame* aBlockFrame)
{
aBlockFrame = aBlockFrame->GetFirstContinuation();
@ -12191,7 +12197,7 @@ nsCSSFrameConstructor::RecoverLetterFrames(nsFrameConstructorState& aState,
do {
// XXX shouldn't this bit be set already (bug 408493), assert instead?
aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
rv = WrapFramesInFirstLetterFrame(aState, aBlockFrame, aBlockFrame,
rv = WrapFramesInFirstLetterFrame(aBlockFrame, aBlockFrame,
aBlockFrame->GetFirstChild(nsnull),
&parentFrame, &textFrame, &prevFrame,
letterFrames, &stopLooking);
@ -12206,7 +12212,7 @@ nsCSSFrameConstructor::RecoverLetterFrames(nsFrameConstructorState& aState,
if (parentFrame) {
// Take the old textFrame out of the parents child list
::DeletingFrameSubtree(aState.mFrameManager, textFrame);
::DeletingFrameSubtree(mPresShell->FrameManager(), textFrame);
parentFrame->RemoveFrame(nsnull, textFrame);
// Insert in the letter frame(s)

View File

@ -1014,29 +1014,25 @@ private:
nsStyleContext* aStyleContext,
nsFrameItems& aResult);
nsresult CreateLetterFrame(nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsresult CreateLetterFrame(nsIFrame* aBlockFrame,
nsIContent* aTextContent,
nsIFrame* aParentFrame,
nsFrameItems& aResult);
nsresult WrapFramesInFirstLetterFrame(nsFrameConstructorState& aState,
nsIContent* aBlockContent,
nsIFrame* aBlockFrame,
nsFrameItems& aBlockFrames);
nsresult WrapFramesInFirstLetterFrame(nsIContent* aBlockContent,
nsIFrame* aBlockFrame,
nsFrameItems& aBlockFrames);
nsresult WrapFramesInFirstLetterFrame(nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsIFrame* aParentFrame,
nsIFrame* aParentFrameList,
nsIFrame** aModifiedParent,
nsIFrame** aTextFrame,
nsIFrame** aPrevFrame,
nsFrameItems& aLetterFrame,
PRBool* aStopLooking);
nsresult WrapFramesInFirstLetterFrame(nsIFrame* aBlockFrame,
nsIFrame* aParentFrame,
nsIFrame* aParentFrameList,
nsIFrame** aModifiedParent,
nsIFrame** aTextFrame,
nsIFrame** aPrevFrame,
nsFrameItems& aLetterFrame,
PRBool* aStopLooking);
nsresult RecoverLetterFrames(nsFrameConstructorState& aState,
nsIFrame* aBlockFrame);
nsresult RecoverLetterFrames(nsIFrame* aBlockFrame);
//
nsresult RemoveLetterFrames(nsPresContext* aPresContext,