Bug 363813. Ensure that floating first-letter frames get inserted in the right place in the list of new floated items. r+sr=dbaron

git-svn-id: svn://10.0.0.236/trunk@218543 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
roc+%cs.cmu.edu
2007-01-17 21:20:33 +00:00
parent 4ea952927c
commit ae08389d4d
2 changed files with 54 additions and 9 deletions

View File

@@ -706,6 +706,10 @@ struct nsFrameItems {
// Appends the frame to the end of the list
void AddChild(nsIFrame* aChild);
// Inserts the frame somewhere in the list
void InsertChildAfter(nsIFrame* aChild, nsIFrame* aAfter);
// Remove the frame from the list, return PR_FALSE if not found.
PRBool RemoveChild(nsIFrame* aChild);
};
@@ -740,6 +744,24 @@ nsFrameItems::AddChild(nsIFrame* aChild)
}
}
void
nsFrameItems::InsertChildAfter(nsIFrame* aChild, nsIFrame* aAfter)
{
if (!childList || (aAfter && !aAfter->GetNextSibling())) {
// Appending to the end of the list
AddChild(aChild);
return;
}
if (!aAfter) {
// Inserting at beginning of list
aChild->SetNextSibling(childList);
childList = aChild;
return;
}
aChild->SetNextSibling(aAfter->GetNextSibling());
aAfter->SetNextSibling(aChild);
}
PRBool
nsFrameItems::RemoveChild(nsIFrame* aFrame)
{
@@ -1152,7 +1174,9 @@ public:
nsIFrame* aParentFrame,
PRBool aCanBePositioned = PR_TRUE,
PRBool aCanBeFloated = PR_TRUE,
PRBool aIsOutOfFlowPopup = PR_FALSE);
PRBool aIsOutOfFlowPopup = PR_FALSE,
PRBool aInsertAfter = PR_FALSE,
nsIFrame* aInsertAfterFrame = nsnull);
protected:
friend class nsFrameConstructorSaveState;
@@ -1314,7 +1338,9 @@ nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
nsIFrame* aParentFrame,
PRBool aCanBePositioned,
PRBool aCanBeFloated,
PRBool aIsOutOfFlowPopup)
PRBool aIsOutOfFlowPopup,
PRBool aInsertAfter,
nsIFrame* aInsertAfterFrame)
{
// The comments in GetGeometricParent regarding root table frames
// all apply here, unfortunately.
@@ -1387,7 +1413,11 @@ nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
}
#endif
frameItems->AddChild(aNewFrame);
if (aInsertAfter) {
frameItems->InsertChildAfter(aNewFrame, aInsertAfterFrame);
} else {
frameItems->AddChild(aNewFrame);
}
// Now add the special siblings too.
nsIFrame* specialSibling = aNewFrame;
@@ -11641,6 +11671,7 @@ static PRBool IsFirstLetterContent(nsIContent* aContent)
void
nsCSSFrameConstructor::CreateFloatingLetterFrame(
nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsIContent* aTextContent,
nsIFrame* aTextFrame,
nsIContent* aBlockContent,
@@ -11696,10 +11727,19 @@ nsCSSFrameConstructor::CreateFloatingLetterFrame(
NS_ASSERTION(aResult.childList == nsnull,
"aResult should be an empty nsFrameItems!");
nsIFrame* insertAfter = nsnull;
nsIFrame* f;
// Put the new float before any of the floats in the block we're
// doing first-letter for, that is, before any floats whose parent is aBlockFrame
for (f = aState.mFloatedItems.childList; f; f = f->GetNextSibling()) {
if (f->GetParent() == aBlockFrame)
break;
insertAfter = f;
}
rv = aState.AddChild(letterFrame, aResult, letterFrame->GetStyleDisplay(),
aTextContent, aStyleContext, aParentFrame, PR_FALSE,
PR_TRUE);
PR_TRUE, PR_FALSE, PR_TRUE, insertAfter);
if (nextTextFrame) {
if (NS_FAILED(rv)) {
@@ -11716,6 +11756,7 @@ nsCSSFrameConstructor::CreateFloatingLetterFrame(
*/
nsresult
nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsIContent* aTextContent,
nsIFrame* aParentFrame,
nsFrameItems& aResult)
@@ -11745,7 +11786,7 @@ nsCSSFrameConstructor::CreateLetterFrame(nsFrameConstructorState& aState,
const nsStyleDisplay* display = sc->GetStyleDisplay();
if (display->IsFloating()) {
// Make a floating first-letter frame
CreateFloatingLetterFrame(aState, aTextContent, textFrame,
CreateFloatingLetterFrame(aState, aBlockFrame, aTextContent, textFrame,
blockContent, aParentFrame,
sc, aResult);
}
@@ -11783,7 +11824,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsIFrame* prevFrame = nsnull;
nsFrameItems letterFrames;
PRBool stopLooking = PR_FALSE;
rv = WrapFramesInFirstLetterFrame(aState, aBlockFrame,
rv = WrapFramesInFirstLetterFrame(aState, aBlockFrame, aBlockFrame,
aBlockFrames.childList,
&parentFrame, &textFrame, &prevFrame,
letterFrames, &stopLooking);
@@ -11829,6 +11870,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsresult
nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsFrameConstructorState& aState,
nsIFrame* aBlockFrame,
nsIFrame* aParentFrame,
nsIFrame* aParentFrameList,
nsIFrame** aModifiedParent,
@@ -11851,7 +11893,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
nsIContent* textContent = frame->GetContent();
if (IsFirstLetterContent(textContent)) {
// Create letter frame to wrap up the text
rv = CreateLetterFrame(aState, textContent,
rv = CreateLetterFrame(aState, aBlockFrame, textContent,
aParentFrame, aLetterFrames);
if (NS_FAILED(rv)) {
return rv;
@@ -11869,7 +11911,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
(nsGkAtoms::lineFrame == frameType) ||
(nsGkAtoms::positionedInlineFrame == frameType)) {
nsIFrame* kids = frame->GetFirstChild(nsnull);
WrapFramesInFirstLetterFrame(aState, frame, kids,
WrapFramesInFirstLetterFrame(aState, aBlockFrame, frame, kids,
aModifiedParent, aTextFrame,
aPrevFrame, aLetterFrames, aStopLooking);
if (*aStopLooking) {
@@ -12102,7 +12144,7 @@ nsCSSFrameConstructor::RecoverLetterFrames(nsFrameConstructorState& aState,
nsIFrame* prevFrame = nsnull;
nsFrameItems letterFrames;
PRBool stopLooking = PR_FALSE;
rv = WrapFramesInFirstLetterFrame(aState, aBlockFrame, blockKids,
rv = WrapFramesInFirstLetterFrame(aState, aBlockFrame, aBlockFrame, blockKids,
&parentFrame, &textFrame, &prevFrame,
letterFrames, &stopLooking);
if (NS_FAILED(rv)) {