diff --git a/content/shared/public/nsLayoutAtomList.h b/content/shared/public/nsLayoutAtomList.h index 6049f79de35..8bd8ffccd21 100644 --- a/content/shared/public/nsLayoutAtomList.h +++ b/content/shared/public/nsLayoutAtomList.h @@ -75,8 +75,10 @@ LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll") // Alphabetical list of frame types LAYOUT_ATOM(areaFrame, "AreaFrame") LAYOUT_ATOM(blockFrame, "BlockFrame") +LAYOUT_ATOM(hrFrame, "HRFrame") LAYOUT_ATOM(htmlFrameInnerFrame, "htmlFrameInnerFrame") LAYOUT_ATOM(htmlFrameOuterFrame, "htmlFrameOuterFrame") +LAYOUT_ATOM(imageFrame, "ImageFrame") LAYOUT_ATOM(inlineFrame, "InlineFrame") LAYOUT_ATOM(letterFrame, "LetterFrame") LAYOUT_ATOM(lineFrame, "LineFrame") diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index fdafb8f9776..34edd1edd2f 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -67,6 +67,9 @@ #include "nsIFrameManager.h" #include "nsIAttributeContent.h" +#include "nsInlineFrame.h" +#undef NOISY_FIRST_LETTER + #ifdef INCLUDE_XUL #include "nsXULAtoms.h" #include "nsTreeFrame.h" @@ -82,8 +85,6 @@ #include "nsDocument.h" #include "nsToolbarItemFrame.h" -#undef NOISY_FIRST_LETTER - #define IS_GFX nsresult @@ -169,26 +170,6 @@ static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); // ----------------------------------------------------------- -// Predicate to see if a given content (block element) has -// first-letter style applied to it. -static PRBool HaveFirstLetterStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aStyleContext) -{ - nsCOMPtr fls; - aPresContext->ProbePseudoStyleContextFor(aContent, - nsHTMLAtoms::firstLetterPseudo, - aStyleContext, PR_FALSE, - getter_AddRefs(fls)); - PRBool result = PR_FALSE; - if (fls) { - result = PR_TRUE; - } - return result; -} - -// ----------------------------------------------------------- - // Structure used when constructing formatting object trees. struct nsFrameItems { nsIFrame* childList; @@ -261,9 +242,11 @@ public: private: nsAbsoluteItems* mItems; // pointer to struct whose data we save/restore PRBool* mFirstLetterStyle; + PRBool* mFirstLineStyle; nsAbsoluteItems mSavedItems; // copy of original data PRBool mSavedFirstLetterStyle; + PRBool mSavedFirstLineStyle; friend class nsFrameConstructorState; }; @@ -280,6 +263,7 @@ public: nsAbsoluteItems mAbsoluteItems; nsAbsoluteItems mFloatedItems; PRBool mFirstLetterStyle; + PRBool mFirstLineStyle; // Constructor nsFrameConstructorState(nsIPresContext* aPresContext, @@ -296,7 +280,8 @@ public: // create a new scope void PushFloaterContainingBlock(nsIFrame* aNewFloaterContainingBlock, nsFrameConstructorSaveState& aSaveState, - PRBool aFirstLetterStyle); + PRBool aFirstLetterStyle, + PRBool aFirstLineStyle); }; nsFrameConstructorState::nsFrameConstructorState(nsIPresContext* aPresContext, @@ -324,18 +309,21 @@ nsFrameConstructorState::PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteConta void nsFrameConstructorState::PushFloaterContainingBlock(nsIFrame* aNewFloaterContainingBlock, nsFrameConstructorSaveState& aSaveState, - PRBool aFirstLetterStyle) + PRBool aFirstLetterStyle, + PRBool aFirstLineStyle) { aSaveState.mItems = &mFloatedItems; aSaveState.mFirstLetterStyle = &mFirstLetterStyle; aSaveState.mSavedItems = mFloatedItems; aSaveState.mSavedFirstLetterStyle = mFirstLetterStyle; + aSaveState.mSavedFirstLineStyle = mFirstLineStyle; mFloatedItems = nsAbsoluteItems(aNewFloaterContainingBlock); mFirstLetterStyle = aFirstLetterStyle; + mFirstLineStyle = aFirstLineStyle; } nsFrameConstructorSaveState::nsFrameConstructorSaveState() - : mItems(nsnull), mFirstLetterStyle(nsnull) + : mItems(nsnull), mFirstLetterStyle(nsnull), mFirstLineStyle(nsnull) { } @@ -348,6 +336,9 @@ nsFrameConstructorSaveState::~nsFrameConstructorSaveState() if (mFirstLetterStyle) { *mFirstLetterStyle = mSavedFirstLetterStyle; } + if (mFirstLineStyle) { + *mFirstLineStyle = mSavedFirstLineStyle; + } } // ----------------------------------------------------------- @@ -834,6 +825,7 @@ IsEmptyTextContent(nsIContent* aContent) return result; } +#if 0 #include "nsIDOMHTMLParagraphElement.h" static PRBool @@ -848,7 +840,7 @@ IsHTMLParagraph(nsIContent* aContent) } static PRBool -IsEmptyContent(nsIContent* aContainer) +IsEmptyContainer(nsIContent* aContainer) { // Check each kid and if each kid is empty text content (or there // are no kids) then return true. @@ -873,8 +865,9 @@ IsEmptyHTMLParagraph(nsIContent* aContent) // It's not an HTML paragraph so return false return PR_FALSE; } - return IsEmptyContent(aContent); + return IsEmptyContainer(aContent); } +#endif nsresult nsCSSFrameConstructor::CreateInputFrame(nsIPresContext *aPresContext, @@ -1261,10 +1254,13 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresContext* aPres } // The caption frame is a floater container - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); nsFrameConstructorSaveState floaterSaveState; aState.PushFloaterContainingBlock(aNewCaptionFrame, floaterSaveState, - haveFLS); + haveFirstLetterStyle, + haveFirstLineStyle); // Process the child content nsFrameItems childItems; @@ -1709,13 +1705,15 @@ nsCSSFrameConstructor::ConstructTableCellFrameOnly(nsIPresContext* aPre bodyPseudoStyle, nsnull); if (aProcessChildren) { - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, - aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); // The area frame is a floater container nsFrameConstructorSaveState floaterSaveState; aState.PushFloaterContainingBlock(aNewCellBodyFrame, floaterSaveState, - haveFLS); + haveFirstLetterStyle, + haveFirstLineStyle); // Process the child content nsFrameItems childItems; @@ -2085,10 +2083,13 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresContext* aPresCo nsFrameConstructorSaveState floaterSaveState; nsFrameItems childItems; - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aDocElement, - styleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aDocElement, styleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState); - aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aDocElement, areaFrame, PR_TRUE, childItems, isBlockFrame); @@ -2204,10 +2205,13 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresContext* aPresCo nsFrameItems childItems; // XXX these next lines are wrong for BoxFrame - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aDocElement, - styleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aDocElement, styleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState); - aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aDocElement, areaFrame, PR_TRUE, childItems, isBlockFrame); @@ -2986,14 +2990,13 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex const PRInt32 kNoSizeSpecified = -1; if (eWidgetRendering_Gfx == mode) { - // Construct a frame-based listbox or combobox - nsIDOMHTMLSelectElement* select = nsnull; + // Construct a frame-based listbox or combobox + nsCOMPtr sel(do_QueryInterface(aContent)); PRInt32 size = 1; - nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); - if (NS_SUCCEEDED(result)) { - select->GetSize(&size); + if (sel) { + sel->GetSize(&size); PRBool multipleSelect = PR_FALSE; - select->GetMultiple(&multipleSelect); + sel->GetMultiple(&multipleSelect); // Construct a combobox if size=1 or no size is specified and its multiple select if (((1 == size) || (kNoSizeSpecified == size)) && (PR_FALSE == multipleSelect)) { // Construct a frame-based combo box. @@ -3100,7 +3103,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); aFrameHasBeenInitialized = PR_TRUE; } - NS_RELEASE(select); } else { rv = NS_NewNativeSelectControlFrame(&aNewFrame); } @@ -4179,11 +4181,13 @@ nsCSSFrameConstructor::InitializeScrollFrame(nsIPresContext* aPresConte if (aProcessChildren) { // The area frame is a floater container - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, - aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); nsFrameConstructorSaveState floaterSaveState; aState.PushFloaterContainingBlock(scrolledFrame, floaterSaveState, - haveFLS); + haveFirstLetterStyle, + haveFirstLineStyle); // Process children nsFrameConstructorSaveState absoluteSaveState; @@ -4326,11 +4330,15 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPre nsFrameConstructorSaveState floaterSaveState; nsFrameItems childItems; - PRBool haveFLS = aDisplay->IsBlockLevel() - ? HaveFirstLetterStyle(aPresContext, aContent, aStyleContext) - : PR_FALSE; + PRBool haveFirstLetterStyle = PR_FALSE, haveFirstLineStyle = PR_FALSE; + if (aDisplay->IsBlockLevel()) { + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + } aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState); - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aContent, newFrame, PR_TRUE, childItems, PR_TRUE); @@ -4366,10 +4374,14 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPre nsFrameConstructorSaveState floaterSaveState; nsFrameItems childItems; - PRBool haveFLS = aDisplay->IsBlockLevel() - ? HaveFirstLetterStyle(aPresContext, aContent, aStyleContext) - : PR_FALSE; - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, haveFLS); + PRBool haveFirstLetterStyle = PR_FALSE, haveFirstLineStyle = PR_FALSE; + if (aDisplay->IsBlockLevel()) { + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + } + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aContent, newFrame, PR_TRUE, childItems, PR_TRUE); @@ -4414,9 +4426,12 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPre aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState); if (isBlockFrame) { - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, - aStyleContext); - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, haveFLS); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); } ProcessChildren(aPresContext, aState, aContent, newFrame, PR_TRUE, childItems, isBlockFrame); @@ -4600,12 +4615,16 @@ nsCSSFrameConstructor::ConstructBlock(nsIPresContext* aPresContext, aStyleContext, PR_FALSE); // See if the block has first-letter style applied to it... - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); // Process the child content nsFrameItems childItems; nsFrameConstructorSaveState floaterSaveState; - aState.PushFloaterContainingBlock(aNewFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(aNewFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); nsresult rv = ProcessChildren(aPresContext, aState, aContent, aNewFrame, PR_TRUE, childItems, PR_TRUE); @@ -5111,6 +5130,67 @@ ContentIsLogicalFirstChild(nsIContent* aContent, nsIContent* aContainingBlock) return PR_FALSE; } +nsresult +nsCSSFrameConstructor::MaybeCreateContainerFrame(nsIPresContext* aPresContext, + nsIContent* aContainer) +{ + nsresult rv = NS_OK; +#if 0 + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + + // See if aContainer's parent has a frame... + nsCOMPtr containerParent; + aContainer->GetParent(*getter_AddRefs(containerParent)); + if (containerParent) { + nsIFrame* parentFrame = GetFrameFor(shell, aPresContext, containerParent); + if (parentFrame) { + // aContainer's parent has a frame. Maybe aContainer needs a + // frame now? If it's display none, then it doesn't. + nsCOMPtr parentStyleContext; + parentFrame->GetStyleContext(getter_AddRefs(parentStyleContext)); + nsCOMPtr styleContext; + aPresContext->ResolveStyleContextFor(aContainer, parentStyleContext, + PR_FALSE, + getter_AddRefs(styleContext)); + const nsStyleDisplay* display = (const nsStyleDisplay*) + styleContext->GetStyleData(eStyleStruct_Display); + if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { + // aContainer's display is not none and it has a parent + // frame. Now we see if it needs a frame after new content + // was appended. + if (IsHTMLParagraph(aContainer)) { + if (!IsEmptyContainer(aContainer)) { + // It's an HTML paragraph (P) and it has some + // content. Because of the previous checks we now know + // that the P used to have nothing but empty content and + // therefore had no frame created. This condition is no + // longer true so we create a frame for aContainer (and + // its children) and insert them into the tree... + PRInt32 ix; + containerParent->IndexOf(aContainer, ix); + if (ix >= 0) { +#ifdef DEBUG_kipp + printf("Recreating frame for HTML:P\n"); +#endif + ContentInserted(aPresContext, containerParent, aContainer, ix); + } + } + } + } + } + else { + // If aContainer's parent has no frame then there is no need + // in trying to create a frame for aContainer. + } + } + else { + // aContainer has no parent. Odd. + } +#endif + return rv; +} + NS_IMETHODIMP nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -5178,14 +5258,19 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, containingBlock->GetStyleContext(getter_AddRefs(blockSC)); nsCOMPtr blockContent; containingBlock->GetContent(getter_AddRefs(blockContent)); - PRBool haveFLS = PR_FALSE; - if (HaveFirstLetterStyle(aPresContext, blockContent, blockSC)) { - haveFLS = PR_TRUE; - } + PRBool haveFirstLetterStyle = + HaveFirstLetterStyle(aPresContext, blockContent, blockSC); + PRBool haveFirstLineStyle = PR_FALSE; PRBool containerIsBlock = containingBlock == parentFrame; PRBool whitespaceDoesntMatter = PR_FALSE; PRBool okToSkip = PR_FALSE; if (containerIsBlock) { + // See if the container has :first-line style too + haveFirstLineStyle = + HaveFirstLineStyle(aPresContext, blockContent, blockSC); + + // Setup the whitespaceDoesntMatter flag so that we know whether + // or not we can skip over empty text frames. const nsStyleText* st; parentFrame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) st); whitespaceDoesntMatter = !st->WhiteSpaceIsSignificant(); @@ -5218,15 +5303,20 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, for (i = aNewIndexInContainer; i < count; i++) { nsCOMPtr childContent; aContainer->ChildAt(i, *getter_AddRefs(childContent)); - if (okToSkip && IsEmptyTextContent(childContent)) { - continue; - } + + // Block containers sometimes don't create frames for the kids + if (containerIsBlock) { + if (okToSkip && IsEmptyTextContent(childContent)) { + // Don't create a frame for useless compressible whitespace + continue; + } #if 0 - if (containerIsBlock && whitespaceDoesntMatter && - IsEmptyHTMLParagraph(childContent)) { - continue; - } + if (whitespaceDoesntMatter && IsEmptyHTMLParagraph(childContent)) { + // Don't create a frame for empty html paragraph's + continue; + } #endif + } // Construct a child frame okToSkip = PR_FALSE; @@ -5245,7 +5335,7 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } // See if we just created a frame in a :first-letter situation - if (haveFLS && + if (haveFirstLetterStyle && (0 == aNewIndexInContainer) && (frameItems.childList == frameItems.lastChild)) { MakeFirstLetterFrame(aPresContext, state, aContainer, childContent, @@ -5253,10 +5343,18 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } } - // Adjust parent frame for table inner/outer frame - // we need to do this here because we need both the parent frame and the constructed frame + if (haveFirstLineStyle) { + // It's possible that some of the new frames go into a + // first-line frame. Look at them and see... + AppendFirstLineFrames(aPresContext, state, aContainer, parentFrame, + frameItems); + } + + // Adjust parent frame for table inner/outer frame. We need to do + // this here because we need both the parent frame and the + // constructed frame nsresult result = NS_OK; - nsIFrame *adjustedParentFrame=parentFrame; + nsIFrame* adjustedParentFrame = parentFrame; firstAppendedFrame = frameItems.childList; if (nsnull != firstAppendedFrame) { const nsStyleDisplay* firstAppendedFrameDisplay; @@ -5268,7 +5366,7 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } // Notify the parent frame passing it the list of new frames - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result) && firstAppendedFrame) { // Append the flowed frames to the principal child list AppendFrames(aPresContext, shell, state.mFrameManager, aContainer, adjustedParentFrame, firstAppendedFrame); @@ -5304,94 +5402,30 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } } - // Here we have been notified that content has been insert - // so if the select now has a single item - // we need to go in and removed the dummy frame - nsCOMPtr selectElement; - nsresult res = aContainer->QueryInterface(nsCOMTypeInfo::GetIID(), - (void**)getter_AddRefs(selectElement)); - if (NS_SUCCEEDED(res) && selectElement) { + // Here we have been notified that content has been appended so if + // the select now has a single item we need to go in and removed + // the dummy frame. + nsCOMPtr sel(do_QueryInterface(aContainer)); + if (sel) { nsCOMPtr childContent; aContainer->ChildAt(aNewIndexInContainer, *getter_AddRefs(childContent)); if (childContent) { - RemoveDummyFrameFromSelect(aPresContext, shell, aContainer, childContent, selectElement); + RemoveDummyFrameFromSelect(aPresContext, shell, aContainer, + childContent, sel); } } } else { -#if 0 // Since the parentFrame wasn't found, aContainer didn't have a // frame created for it. Maybe now that it has a new child it // should get a frame... MaybeCreateContainerFrame(aPresContext, aContainer); -#endif } return NS_OK; } -#if 0 -nsresult -nsCSSFrameConstructor::MaybeCreateContainerFrame(nsIPresContext* aPresContext, - nsIContent* aContainer) -{ - nsresult rv = NS_OK; - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - - // See if aContainer's parent has a frame... - nsCOMPtr containerParent; - aContainer->GetParent(*getter_AddRefs(containerParent)); - if (containerParent) { - parentFrame = GetFrameFor(shell, aPresContext, containerParent); - if (parentFrame) { - // aContainer's parent has a frame. Maybe aContainer needs a - // frame now? If it's display none, then it doesn't. - nsCOMPtr parentStyleContext; - parentFrame->GetStyleContext(getter_AddRefs(parentStyleContext)); - nsCOMPtr styleContext; - aPresContext->ResolveStyleContextFor(aContainer, parentStyleContext, - PR_FALSE, - getter_AddRefs(styleContext)); - const nsStyleDisplay* display = (const nsStyleDisplay*) - styleContext->GetStyleData(eStyleStruct_Display); - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // aContainer's display is not none and it has a parent - // frame. Now we see if it needs a frame after new content - // was appended. - if (IsHTMLParagraph(aContainer)) { - if (!IsEmptyContent(aContainer)) { - // It's an HTML paragraph (P) and it has some - // content. Because of the previous checks we now know - // that the P used to have nothing but empty content and - // therefore had no frame created. This condition is no - // longer true so we create a frame for aContainer (and - // its children) and insert them into the tree... - PRInt32 ix; - containerParent->IndexOf(aContainer, ix); - if (ix >= 0) { -#ifdef DEBUG_kipp - printf("ContentAppended: recreating frame for HTML:P\n"); -#endif - ContentInserted(aPresContext, containerParent, aContainer, ix); - } - } - } - } - } - else { - // If aContainer's parent has no frame then there is no need - // in trying to create a frame for aContainer. - } - } - else { - // aContainer has no parent. Odd. - } - return rv; -} -#endif - nsresult nsCSSFrameConstructor::MakeFirstLetterFrame(nsIPresContext* aPresContext, nsFrameConstructorState& aState, @@ -5669,20 +5703,19 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, nextSibling = FindNextSibling(shell, aContainer, aIndexInContainer); } - // Get the geometric parent. + // Get the geometric parent. Use the prev sibling if we have it; + // otherwise use the next sibling nsIFrame* parentFrame; - if ((nsnull == prevSibling) && (nsnull == nextSibling)) { - + if (nsnull != prevSibling) { + prevSibling->GetParent(&parentFrame); + } + else if (nextSibling) { + nextSibling->GetParent(&parentFrame); + } + else { // No previous or next sibling so treat this like an appended frame. isAppend = PR_TRUE; shell->GetPrimaryFrameFor(aContainer, &parentFrame); - } else { - // Use the prev sibling if we have it; otherwise use the next sibling - if (nsnull != prevSibling) { - prevSibling->GetParent(&parentFrame); - } else { - nextSibling->GetParent(&parentFrame); - } } // Construct a new frame @@ -5692,60 +5725,49 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, GetAbsoluteContainingBlock(aPresContext, parentFrame), GetFloaterContainingBlock(aPresContext, parentFrame)); - // Examine the floater-container-block (which is the nearest - // block element up the tree) and see if :first-letter style - // applies. + PRBool needFixup = PR_FALSE; nsIFrame* containingBlock = state.mFloatedItems.containingBlock; nsCOMPtr blockSC; - containingBlock->GetStyleContext(getter_AddRefs(blockSC)); nsCOMPtr blockContent; - containingBlock->GetContent(getter_AddRefs(blockContent)); - PRBool haveFLS = - HaveFirstLetterStyle(aPresContext, blockContent, blockSC); - PRBool needFixup = PR_FALSE; - if (haveFLS) { - // Trap out to special routine that handles adjusting a blocks - // frame tree when first-letter style is present. -#ifdef NOISY_FIRST_LETTER - printf("ContentInserted: indexInContainer=%d containingBlock=", - aIndexInContainer); - nsFrame::ListTag(stdout, containingBlock); - printf("\n"); - printf(" parentFrame="); - nsFrame::ListTag(stdout, parentFrame); - if (prevSibling) { - printf(" prevSibling="); - nsFrame::ListTag(stdout, prevSibling); - } - printf("\n"); -#endif + PRBool haveFirstLetterStyle = PR_FALSE; + PRBool haveFirstLineStyle = PR_FALSE; + const nsStyleDisplay* parentDisplay; + parentFrame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)parentDisplay); - // Get the correct parentFrame and prevSibling - if a - // letter-frame is present, use its parent. - nsCOMPtr type; - parentFrame->GetFrameType(getter_AddRefs(type)); - if (type.get() == nsLayoutAtoms::letterFrame) { - if (prevSibling) { - prevSibling = parentFrame; + // Examine the parentFrame where the insertion is taking + // place. If its a certain kind of container then some special + // processing is done. + if ((NS_STYLE_DISPLAY_BLOCK == parentDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == parentDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE_BLOCK == parentDisplay->mDisplay)) { + // Dig up the special style flags + containingBlock->GetStyleContext(getter_AddRefs(blockSC)); + containingBlock->GetContent(getter_AddRefs(blockContent)); + HaveSpecialBlockStyle(aPresContext, blockContent, blockSC, + &haveFirstLetterStyle, + &haveFirstLineStyle); + + if (haveFirstLetterStyle) { + // Get the correct parentFrame and prevSibling - if a + // letter-frame is present, use its parent. + nsCOMPtr parentFrameType; + parentFrame->GetFrameType(getter_AddRefs(parentFrameType)); + if (parentFrameType == nsLayoutAtoms::letterFrame) { + if (prevSibling) { + prevSibling = parentFrame; + } + parentFrame->GetParent(&parentFrame); } - parentFrame->GetParent(&parentFrame); -#ifdef NOISY_FIRST_LETTER - printf(" ==> revised parentFrame="); - nsFrame::ListTag(stdout, parentFrame); - printf("\n"); -#endif - } - if (0 == aIndexInContainer) { - // See if after we construct the new first child if we will - // need to fixup the second child's frames. - state.mFirstLetterStyle = PR_TRUE; - if ((parentFrame == containingBlock) || - ContentIsLogicalFirstChild(aChild, blockContent)) { - needFixup = PR_TRUE; -#ifdef NOISY_FIRST_LETTER - printf(" ==> needFixup=yes\n"); -#endif + if (0 == aIndexInContainer) { + // See if after we construct the new first child if we will + // need to fixup the second child's frames. + state.mFirstLetterStyle = PR_TRUE; + if ((parentFrame == containingBlock) || + ContentIsLogicalFirstChild(aChild, blockContent)) { + needFixup = PR_TRUE; + } } } } @@ -5754,18 +5776,33 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, frameItems); // See if we just created a frame in a :first-letter situation - if (haveFLS && (0 == aIndexInContainer)) { + if (haveFirstLetterStyle && (0 == aIndexInContainer)) { MakeFirstLetterFrame(aPresContext, state, aContainer, aChild, blockContent, parentFrame, frameItems); } + + if (haveFirstLineStyle) { + // It's possible that the new frame goes into a first-line + // frame. Look at it and see... + if (isAppend) { + // Use append logic when appending + AppendFirstLineFrames(aPresContext, state, aContainer, parentFrame, + frameItems); + } + else { + // Use more complicated insert logic when inserting + InsertFirstLineFrames(aPresContext, state, aContainer, + containingBlock, &parentFrame, + prevSibling, frameItems); + } + } nsIFrame* newFrame = frameItems.childList; - if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) { // Notify the parent frame if (isAppend) { - rv = AppendFrames(aPresContext, shell, state.mFrameManager, aContainer, - parentFrame, newFrame); + rv = AppendFrames(aPresContext, shell, state.mFrameManager, + aContainer, parentFrame, newFrame); } else { if (!prevSibling) { // We're inserting the new frame as the first child. See if the @@ -5831,6 +5868,12 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, } } } + else { + // Since the parentFrame wasn't found, aContainer didn't have a + // frame created for it. Maybe now that it has a new child it + // should get a frame... + MaybeCreateContainerFrame(aPresContext, aContainer); + } // Here we have been notified that content has been insert // so if the select now has a single item @@ -6003,7 +6046,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, // we need to add a pseudo frame so select gets sized as the best it can // so here we see if it is a select and then we get the number of options nsresult result = NS_ERROR_FAILURE; - if (aContainer && nsnull != childFrame) { + if (aContainer && childFrame) { nsCOMPtr selectElement; result = aContainer->QueryInterface(nsCOMTypeInfo::GetIID(), (void**)getter_AddRefs(selectElement)); @@ -6085,6 +6128,23 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, } #endif // INCLUDE_XUL +#if 0 + // It's possible that we just made an HTML paragraph empty... + if (IsEmptyHTMLParagraph(aContainer)) { + nsCOMPtr containerParent; + aContainer->GetParent(*getter_AddRefs(containerParent)); + if (containerParent) { + PRInt32 ix; + containerParent->IndexOf(aContainer, ix); + if (ix >= 0) { + // No point in doing the fixup + needFixup = PR_FALSE; + rv = ContentRemoved(aPresContext, containerParent, aContainer, ix); + } + } + } +#endif + if (childFrame) { // Get the childFrame's parent frame nsIFrame* parentFrame; @@ -7598,6 +7658,67 @@ nsCSSFrameConstructor::GetFirstLetterStyle(nsIPresContext* aPresContext, return fls; } +nsIStyleContext* +nsCSSFrameConstructor::GetFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext) +{ + nsIStyleContext* fls = nsnull; + aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::firstLinePseudo, + aStyleContext, PR_FALSE, &fls); + return fls; +} + +// Predicate to see if a given content (block element) has +// first-letter style applied to it. +PRBool +nsCSSFrameConstructor::HaveFirstLetterStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext) +{ + nsCOMPtr fls; + aPresContext->ProbePseudoStyleContextFor(aContent, + nsHTMLAtoms::firstLetterPseudo, + aStyleContext, PR_FALSE, + getter_AddRefs(fls)); + PRBool result = PR_FALSE; + if (fls) { + result = PR_TRUE; + } + return result; +} + +PRBool +nsCSSFrameConstructor::HaveFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext) +{ + nsCOMPtr fls; + aPresContext->ProbePseudoStyleContextFor(aContent, + nsHTMLAtoms::firstLinePseudo, + aStyleContext, PR_FALSE, + getter_AddRefs(fls)); + PRBool result = PR_FALSE; + if (fls) { + result = PR_TRUE; + } + return result; +} + +void +nsCSSFrameConstructor::HaveSpecialBlockStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext, + PRBool* aHaveFirstLetterStyle, + PRBool* aHaveFirstLineStyle) +{ + *aHaveFirstLetterStyle = + HaveFirstLetterStyle(aPresContext, aContent, aStyleContext); + *aHaveFirstLineStyle = + HaveFirstLineStyle(aPresContext, aContent, aStyleContext); +} + PRBool nsCSSFrameConstructor::ShouldCreateFirstLetterFrame( nsIPresContext* aPresContext, @@ -7675,15 +7796,16 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresContext* aPresContext, for (PRInt32 i = 0; i < count; i++) { nsCOMPtr childContent; if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) { - if (okToSkip && IsEmptyTextContent(childContent)) { - continue; - } + if (aParentIsBlock) { + if (okToSkip && IsEmptyTextContent(childContent)) { + continue; + } #if 0 - if (aParentIsBlock && whitespaceDoesntMatter && - IsEmptyHTMLParagraph(childContent)) { - continue; - } + if (whitespaceDoesntMatter && IsEmptyHTMLParagraph(childContent)) { + continue; + } #endif + } // Construct a child frame okToSkip = PR_FALSE; @@ -7729,9 +7851,363 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresContext* aPresContext, } } + if (aParentIsBlock && aState.mFirstLineStyle) { + rv = WrapFramesInFirstLineFrame(aPresContext, aState, aContent, aFrame, + aFrameItems); + } + return rv; } +//---------------------------------------------------------------------- + +// Support for :first-line style + +// XXX this predicate and its cousins need to migrated to a single +// place in layout - something in nsStyleDisplay maybe? +static PRBool +IsInlineFrame(nsIFrame* aFrame) +{ + const nsStyleDisplay* display; + aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + switch (display->mDisplay) { + case NS_STYLE_DISPLAY_INLINE: + case NS_STYLE_DISPLAY_INLINE_BLOCK: + case NS_STYLE_DISPLAY_INLINE_TABLE: + return PR_TRUE; + default: + break; + } + return PR_FALSE; +} + +static void +ReparentFrame(nsIPresContext* aPresContext, + nsIFrame* aNewParentFrame, + nsIStyleContext* aParentStyleContext, + nsIFrame* aFrame) +{ + aFrame->ReResolveStyleContext(aPresContext, aParentStyleContext, + NS_STYLE_HINT_REFLOW, + nsnull, nsnull); + aFrame->SetParent(aNewParentFrame); +} + +// 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. +nsresult +nsCSSFrameConstructor::WrapFramesInFirstLineFrame( + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aFrame, + nsFrameItems& aFrameItems) +{ + nsresult rv = NS_OK; + + // Find the first and last inline frame in aFrameItems + nsIFrame* kid = aFrameItems.childList; + nsIFrame* firstInlineFrame = nsnull; + nsIFrame* lastInlineFrame = nsnull; + while (kid) { + if (IsInlineFrame(kid)) { + if (!firstInlineFrame) firstInlineFrame = kid; + lastInlineFrame = kid; + } + else { + break; + } + kid->GetNextSibling(&kid); + } + + // If we don't find any inline frames, then there is nothing to do + if (!firstInlineFrame) { + return rv; + } + + // Create line frame + nsCOMPtr parentStyle; + aFrame->GetStyleContext(getter_AddRefs(parentStyle)); + nsCOMPtr firstLineStyle( + getter_AddRefs(GetFirstLineStyle(aPresContext, aContent, parentStyle)) + ); + nsIFrame* lineFrame; + rv = NS_NewFirstLineFrame(&lineFrame); + if (NS_SUCCEEDED(rv)) { + // Initialize the line frame + rv = lineFrame->Init(*aPresContext, aContent, aFrame, + firstLineStyle, nsnull); + + // Mangle the list of frames we are giving to the block: first + // chop the list in two after lastInlineFrame + nsIFrame* secondBlockFrame; + lastInlineFrame->GetNextSibling(&secondBlockFrame); + lastInlineFrame->SetNextSibling(nsnull); + + // The lineFrame will be the block's first child; the rest of the + // frame list (after lastInlineFrame) will be the second and + // subsequent children; join the list together and reset + // aFrameItems appropriately. + if (secondBlockFrame) { + lineFrame->SetNextSibling(secondBlockFrame); + } + if (aFrameItems.childList == lastInlineFrame) { + // Just in case the block had exactly one inline child + aFrameItems.lastChild = lineFrame; + } + aFrameItems.childList = lineFrame; + + // Give the inline frames to the lineFrame after reparenting them + kid = firstInlineFrame; + while (kid) { + ReparentFrame(aPresContext, lineFrame, firstLineStyle, kid); + kid->GetNextSibling(&kid); + } + lineFrame->SetInitialChildList(*aPresContext, nsnull, firstInlineFrame); + } + + return rv; +} + +// Special routine to handle appending a new frame to a block frame's +// child list. Takes care of placing the new frame into the right +// place when first-line style is present. +nsresult +nsCSSFrameConstructor::AppendFirstLineFrames( + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsFrameItems& aFrameItems) +{ + // It's possible that aBlockFrame needs to have a first-line frame + // created because it doesn't currently have any children. + nsIFrame* blockKid; + aBlockFrame->FirstChild(nsnull, &blockKid); + if (!blockKid) { + return WrapFramesInFirstLineFrame(aPresContext, aState, aContent, + aBlockFrame, aFrameItems); + } + + // Examine the last block child - if it's a first-line frame then + // appended frames need special treatment. + nsresult rv = NS_OK; + nsFrameList blockFrames(blockKid); + nsIFrame* lastBlockKid = blockFrames.LastChild(); + nsCOMPtr frameType; + lastBlockKid->GetFrameType(getter_AddRefs(frameType)); + if (frameType != nsLayoutAtoms::lineFrame) { + // No first-line frame at the end of the list, therefore there is + // an interveening block between any first-line frame the frames + // we are appending. Therefore, we don't need any special + // treatment of the appended frames. + return rv; + } + nsIFrame* lineFrame = lastBlockKid; + nsCOMPtr firstLineStyle; + lineFrame->GetStyleContext(getter_AddRefs(firstLineStyle)); + + // Find the first and last inline frame in aFrameItems + nsIFrame* kid = aFrameItems.childList; + nsIFrame* firstInlineFrame = nsnull; + nsIFrame* lastInlineFrame = nsnull; + while (kid) { + if (IsInlineFrame(kid)) { + if (!firstInlineFrame) firstInlineFrame = kid; + lastInlineFrame = kid; + } + else { + break; + } + kid->GetNextSibling(&kid); + } + + // If we don't find any inline frames, then there is nothing to do + if (!firstInlineFrame) { + return rv; + } + + // The inline frames get appended to the lineFrame. Make sure they + // are reparented properly. + nsIFrame* remainingFrames; + lastInlineFrame->GetNextSibling(&remainingFrames); + lastInlineFrame->SetNextSibling(nsnull); + kid = firstInlineFrame; + while (kid) { + ReparentFrame(aPresContext, lineFrame, firstLineStyle, kid); + kid->GetNextSibling(&kid); + } + aState.mFrameManager->AppendFrames(*aPresContext, *aState.mPresShell, + lineFrame, nsnull, firstInlineFrame); + + // The remaining frames get appended to the block frame + if (remainingFrames) { + aFrameItems.childList = remainingFrames; + } + else { + aFrameItems.childList = nsnull; + aFrameItems.lastChild = nsnull; + } + + return rv; +} + +// Special routine to handle inserting a new frame into a block +// frame's child list. Takes care of placing the new frame into the +// right place when first-line style is present. +nsresult +nsCSSFrameConstructor::InsertFirstLineFrames( + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsIFrame** aParentFrame, + nsIFrame* aPrevSibling, + nsFrameItems& aFrameItems) +{ + nsresult rv = NS_OK; +#if 0 + nsIFrame* parentFrame = *aParentFrame; + nsIFrame* newFrame = aFrameItems.childList; + PRBool isInline = IsInlineFrame(newFrame); + + if (!aPrevSibling) { + // Insertion will become the first frame. Two cases: we either + // already have a first-line frame or we don't. + nsIFrame* firstBlockKid; + aBlockFrame->FirstChild(nsnull, &firstBlockKid); + nsCOMPtr frameType; + firstBlockKid->GetFrameType(getter_AddRefs(frameType)); + if (frameType == nsLayoutAtoms::lineFrame) { + // We already have a first-line frame + nsIFrame* lineFrame = firstBlockKid; + nsCOMPtr firstLineStyle; + lineFrame->GetStyleContext(getter_AddRefs(firstLineStyle)); + + if (isInline) { + // Easy case: the new inline frame will go into the lineFrame. + ReparentFrame(aPresContext, lineFrame, firstLineStyle, newFrame); + aState.mFrameManager->InsertFrames(*aPresContext, *aState.mPresShell, + lineFrame, nsnull, nsnull, + newFrame); + + // Since the frame is going into the lineFrame, don't let it + // go into the block too. + aFrameItems.childList = nsnull; + aFrameItems.lastChild = nsnull; + } + else { + // Harder case: We are about to insert a block level element + // before the first-line frame. + // XXX need a method to steal away frames from the line-frame + } + } + else { + // We do not have a first-line frame + if (isInline) { + // We now need a first-line frame to contain the inline frame. + nsIFrame* lineFrame; + rv = NS_NewFirstLineFrame(&lineFrame); + if (NS_SUCCEEDED(rv)) { + // Lookup first-line style context + nsCOMPtr parentStyle; + aBlockFrame->GetStyleContext(getter_AddRefs(parentStyle)); + nsCOMPtr firstLineStyle( + getter_AddRefs(GetFirstLineStyle(aPresContext, aContent, + parentStyle)) + ); + + // Initialize the line frame + rv = lineFrame->Init(*aPresContext, aContent, aBlockFrame, + firstLineStyle, nsnull); + + // Make sure the caller inserts the lineFrame into the + // blocks list of children. + aFrameItems.childList = lineFrame; + aFrameItems.lastChild = lineFrame; + + // Give the inline frames to the lineFrame after + // reparenting them + ReparentFrame(aPresContext, lineFrame, firstLineStyle, newFrame); + lineFrame->SetInitialChildList(*aPresContext, nsnull, newFrame); + } + } + else { + // Easy case: the regular insertion logic can insert the new + // frame because its a block frame. + } + } + } + else { + // Insertion will not be the first frame. + nsIFrame* prevSiblingParent; + aPrevSibling->GetParent(&prevSiblingParent); + if (prevSiblingParent == aBlockFrame) { + // Easy case: The prev-siblings parent is the block + // frame. Therefore the prev-sibling is not currently in a + // line-frame. Therefore the new frame which is going after it, + // regardless of type, is not going into a line-frame. + } + else { + // If the prevSiblingParent is not the block-frame then it must + // be a line-frame (if it were a letter-frame, that logic would + // already have adjusted the prev-sibling to be the + // letter-frame). + if (isInline) { + // Easy case: the insertion can go where the caller thinks it + // should go (which is into prevSiblingParent). + } + else { + // Block elements don't end up in line-frames, therefore + // change the insertion point to aBlockFrame. However, there + // might be more inline elements following aPrevSibling that + // need to be pulled out of the line-frame and become children + // of the block. + nsIFrame* nextSibling; + aPrevSibling->GetNextSibling(&nextSibling); + nsIFrame* nextLineFrame; + prevSiblingParent->GetNextInFlow(&nextLineFrame); + if (nextSibling || nextLineFrame) { + // Oy. We have work to do. Create a list of the new frames + // that are going into the block by stripping them away from + // the line-frame(s). + nsFrameList list(nextSibling); + if (nextSibling) { + nsLineFrame* lineFrame = (nsLineFrame*) prevSiblingParent; + lineFrame->StealFramesFrom(nextSibling); + } + + nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame; + for (;;) { + nextLineFrame->GetNextInFlow(&nextLineFrame); + if (!nextLineFrame) { + break; + } + nsIFrame* kids; + nextLineFrame->FirstChild(nsnull, &kids); + } + } + else { + // We got lucky: aPrevSibling was the last inline frame in + // the line-frame. + ReparentFrame(aPresContext, aBlockFrame, firstLineStyle, newFrame); + aState.mFrameManager->InsertFrames(*aPresContext, *aState.mPresShell, + aBlockFrame, nsnull, + prevSiblingParent, newFrame); + aFrameItems.childList = nsnull; + aFrameItems.lastChild = nsnull; + } + } + } + } + +#endif + return rv; +} + +//---------------------------------------------------------------------- + // Determine how many characters in the text fragment apply to the // first letter static PRInt32 @@ -7783,15 +8259,15 @@ TotalLength(nsTextFragment* aFragments, PRInt32 aNumFragments) return sum; } -static PRBool NeedFirstLetterContinuation(nsIContent* aContent) +static PRBool +NeedFirstLetterContinuation(nsIContent* aContent) { NS_PRECONDITION(aContent, "null ptr"); PRBool result = PR_FALSE; if (aContent) { - nsITextContent* tc = nsnull; - nsresult rv = aContent->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_SUCCEEDED(rv)) { + nsCOMPtr tc(do_QueryInterface(aContent)); + if (tc) { nsTextFragment* frags = nsnull; PRInt32 numFrags = 0; tc->GetText((const nsTextFragment*&)frags, numFrags); diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index a6ff6d4c0d1..31ded2af593 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -627,9 +627,27 @@ InitializeScrollFrame(nsIPresContext* aPresContext, // Methods support creating block frames and their children - nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aStyleContext); + static nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static nsIStyleContext* GetFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static PRBool HaveFirstLetterStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static PRBool HaveFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static void HaveSpecialBlockStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext, + PRBool* aHaveFirstLetterStyle, + PRBool* aHaveFirstLineStyle); PRBool ShouldCreateFirstLetterFrame(nsIPresContext* aPresContext, nsIContent* aContent, @@ -679,6 +697,29 @@ InitializeScrollFrame(nsIPresContext* aPresContext, nsFrameItems& aFloatingItems, nsIStyleContext* aStyleContext); + nsresult WrapFramesInFirstLineFrame(nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aFrame, + nsFrameItems& aFrameItems); + + nsresult AppendFirstLineFrames(nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsFrameItems& aFrameItems); + + nsresult InsertFirstLineFrames(nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsIFrame** aParentFrame, + nsIFrame* aPrevSibling, + nsFrameItems& aFrameItems); + + nsresult MaybeCreateContainerFrame(nsIPresContext* aPresContext, + nsIContent* aContainer); + protected: nsIDocument* mDocument; diff --git a/layout/base/nsLayoutAtomList.h b/layout/base/nsLayoutAtomList.h index 6049f79de35..8bd8ffccd21 100644 --- a/layout/base/nsLayoutAtomList.h +++ b/layout/base/nsLayoutAtomList.h @@ -75,8 +75,10 @@ LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll") // Alphabetical list of frame types LAYOUT_ATOM(areaFrame, "AreaFrame") LAYOUT_ATOM(blockFrame, "BlockFrame") +LAYOUT_ATOM(hrFrame, "HRFrame") LAYOUT_ATOM(htmlFrameInnerFrame, "htmlFrameInnerFrame") LAYOUT_ATOM(htmlFrameOuterFrame, "htmlFrameOuterFrame") +LAYOUT_ATOM(imageFrame, "ImageFrame") LAYOUT_ATOM(inlineFrame, "InlineFrame") LAYOUT_ATOM(letterFrame, "LetterFrame") LAYOUT_ATOM(lineFrame, "LineFrame") diff --git a/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index 60fbc3530e6..b7fad5c525c 100644 --- a/layout/base/public/nsIFrame.h +++ b/layout/base/public/nsIFrame.h @@ -31,6 +31,7 @@ class nsIFrame; class nsIPresContext; class nsIPresShell; class nsIRenderingContext; +class nsISizeOfHandler; class nsISpaceManager; class nsIStyleContext; class nsIView; @@ -588,7 +589,7 @@ public: * called when the frame has been scrolled to a new * position. only called for frames with views. */ - NS_IMETHOD Scrolled(nsIView *aView) = 0; + NS_IMETHOD Scrolled(nsIView *aView) = 0; // Debugging NS_IMETHOD List(FILE* out, PRInt32 aIndent) const = 0; @@ -608,6 +609,23 @@ public: */ NS_IMETHOD DumpRegressionData(FILE* out, PRInt32 aIndent) = 0; + /** + * Get the size of the frame object. The size value should include + * all subordinate data referenced by the frame that is not + * accounted for by child frames. However, this value should not + * include the content objects, style contexts, views or other data + * that lies logically outside the frame system. + * + * If the implementation so chooses, instead of returning the total + * subordinate data it may instead use the sizeof handler to store + * away subordinate data under its own key so that the subordinate + * data may be tabulated independently of the frame itself. + * + * The caller is responsible for recursing over all child-lists that + * the frame supports. + */ + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const = 0; + NS_IMETHOD VerifyTree() const = 0; /** Selection related calls diff --git a/layout/base/public/nsLayoutAtomList.h b/layout/base/public/nsLayoutAtomList.h index 6049f79de35..8bd8ffccd21 100644 --- a/layout/base/public/nsLayoutAtomList.h +++ b/layout/base/public/nsLayoutAtomList.h @@ -75,8 +75,10 @@ LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll") // Alphabetical list of frame types LAYOUT_ATOM(areaFrame, "AreaFrame") LAYOUT_ATOM(blockFrame, "BlockFrame") +LAYOUT_ATOM(hrFrame, "HRFrame") LAYOUT_ATOM(htmlFrameInnerFrame, "htmlFrameInnerFrame") LAYOUT_ATOM(htmlFrameOuterFrame, "htmlFrameOuterFrame") +LAYOUT_ATOM(imageFrame, "ImageFrame") LAYOUT_ATOM(inlineFrame, "InlineFrame") LAYOUT_ATOM(letterFrame, "LetterFrame") LAYOUT_ATOM(lineFrame, "LineFrame") diff --git a/layout/generic/nsAreaFrame.cpp b/layout/generic/nsAreaFrame.cpp index 7dbd2510de7..b893078295a 100644 --- a/layout/generic/nsAreaFrame.cpp +++ b/layout/generic/nsAreaFrame.cpp @@ -451,3 +451,14 @@ nsAreaFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Area", aResult); } + +NS_IMETHODIMP +nsAreaFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + nsBlockFrame::SizeOf(aHandler, aResult); + *aResult += sizeof(*this) - sizeof(nsBlockFrame); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/generic/nsAreaFrame.h b/layout/generic/nsAreaFrame.h index e7de9b6b787..b54ca0eca3f 100644 --- a/layout/generic/nsAreaFrame.h +++ b/layout/generic/nsAreaFrame.h @@ -104,6 +104,8 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; + // nsIAreaFrame NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const; diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index d44af8f27d6..2d24571254d 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -45,8 +45,6 @@ #include "nsITextContent.h" #include "nsStyleChangeList.h" -// XXX for IsEmptyLine -#include "nsTextFragment.h" #include "nsIFocusTracker.h" #include "nsIFrameSelection.h" @@ -985,6 +983,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // It is possible that we just acquired first-line style. See if // this is the case, and if so, fix things up. if (0 == (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState)) { @@ -1005,6 +1004,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } } +#endif return rv; } @@ -2185,7 +2185,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState, // Setup the line-layout for the new line aState.mCurrentLine = aLine; aLine->ClearDirty(); - aLine->SetNeedDidReflow(); // Now that we know what kind of line we have, reflow it nsRect oldCombinedArea = aLine->mCombinedArea; @@ -2643,38 +2642,6 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState, return PR_FALSE; } -#if 0 - const nsStyleText* styleText; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText); - if ((NS_STYLE_WHITESPACE_PRE == styleText->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == styleText->mWhiteSpace)) { - // Since whitespace is significant, we know that the paragraph - // is not empty (even if it has no text in it because it has - return PR_FALSE; - -static PRBool -IsEmptyHTMLParagraph(nsIFrame* aFrame) -{ - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf)) && - nsBlockReflowContext::IsHTMLParagraph(aFrame)) { - if (!bf->mLines) { - // It's an html paragraph and it's empty - return PR_TRUE; - } - - nsLineBox* line = bf->mLines; - while (line) { - if (!IsEmptyLine(line)) { - return PR_FALSE; - } - line = line->mNext; - } - } - return PR_FALSE; -} -#endif - nsIFrame* nsBlockFrame::GetTopBlockChild() { @@ -3071,6 +3038,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, availWidth, availHeight, impactedByFloaters, PR_FALSE /*XXX isTopOfPage*/); + + // XXX Unfortunately we need to know this before reflowing the first + // inline frame in the line. FIX ME. if ((0 == aLineLayout.GetLineNumber()) && (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) { aLineLayout.SetFirstLetterStyleOK(PR_TRUE); @@ -3287,10 +3257,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, // line and don't stop the line reflow... PRBool splitLine = !reflowingFirstLetter; if (reflowingFirstLetter) { +#ifdef BLOCK_DOES_FIRST_LINE if (aLine->IsFirstLine()) { splitLine = PR_TRUE; } - else { + else +#endif + { nsIAtom* frameType; if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) { if (frameType == nsLayoutAtoms::inlineFrame) { @@ -3391,7 +3364,9 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, aLine->mNext = to; } to->SetIsBlock(aLine->IsBlock()); +#ifdef BLOCK_DOES_FIRST_LINE to->SetIsFirstLine(aLine->IsFirstLine()); +#endif aLine->mChildCount -= pushCount; // Let line layout know that some frames are no longer part of its @@ -3656,20 +3631,6 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, aLine->mMaxElementWidth = aMaxElementSize.width; } -#if XXX_need_line_outside_children - // Compute LINE_OUTSIDE_CHILDREN state for this line. The bit is set - // if any child frame has outside children. - if ((aLine->mCombinedArea.x < aLine->mBounds.x) || - (aLine->mCombinedArea.XMost() > aLine->mBounds.XMost()) || - (aLine->mCombinedArea.y < aLine->mBounds.y) || - (aLine->mCombinedArea.YMost() > aLine->mBounds.YMost())) { - aLine->SetOutsideChildren(); - } - else { - aLine->ClearOutsideChildren(); - } -#endif - // Update xmost nscoord xmost = aLine->mBounds.XMost(); if (xmost > aState.mKidXMost) { @@ -3847,6 +3808,7 @@ nsBlockFrame::LastChild() return nsnull; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) { @@ -3938,6 +3900,7 @@ nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) return rv; } +#endif NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, @@ -3963,12 +3926,14 @@ nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, nsLineBox* lastLine = nsLineBox::LastLine(mLines); if (lastLine) { lastKid = lastLine->LastChild(); +#ifdef BLOCK_DOES_FIRST_LINE if (lastLine->IsFirstLine()) { // Get last frame in the nsFirstLineFrame lastKid->FirstChild(nsnull, &lastKid); nsFrameList frames(lastKid); lastKid = frames.LastChild(); } +#endif } // Add frames after the last child @@ -4058,6 +4023,7 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, nsLineBox* prevSibLine = nsnull; PRInt32 prevSiblingIndex = -1; if (aPrevSibling) { +#ifdef BLOCK_DOES_FIRST_LINE // Its possible we have an nsFirstLineFrame managing some of our // child frames. If we do and the AddFrames is targetted at it, // use AddFirstLineFrames to get the frames properly placed. @@ -4079,7 +4045,9 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, (nsFirstLineFrame*)prevSiblingParent, aFrameList, aPrevSibling); } - else { + else +#endif + { // Find the line that contains the previous sibling prevSibLine = nsLineBox::FindLineContaining(mLines, aPrevSibling, &prevSiblingIndex); @@ -4091,12 +4059,14 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, } } } +#ifdef BLOCK_DOES_FIRST_LINE else if (mLines && mLines->IsFirstLine()) { mLines->MarkDirty(); return AddFirstLineFrames(aPresContext, (nsFirstLineFrame*)mLines->mFirstChild, aFrameList, nsnull); } +#endif // Find the frame following aPrevSibling so that we can join up the // two lists of frames. @@ -4168,20 +4138,22 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, aPrevSibling->SetNextSibling(prevSiblingNextFrame); } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { // We just added one or more frame(s) to the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4310,6 +4282,7 @@ nsBlockFrame::TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, return kids.FirstChild(); } +#endif void nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) @@ -4404,12 +4377,14 @@ nsresult nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, nsIFrame* aDeletedFrame) { +#ifdef BLOCK_DOES_FIRST_LINE nsIFrame* parent; aDeletedFrame->GetParent(&parent); if (parent != this) { return RemoveFirstLineFrame(aPresContext, (nsFirstLineFrame*)parent, aDeletedFrame); } +#endif // Find the line and the previous sibling that contains // deletedFrame; we also find the pointer to the line. @@ -4446,6 +4421,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, while (nsnull != aDeletedFrame) { while ((nsnull != line) && (nsnull != aDeletedFrame)) { #ifdef NS_DEBUG +#ifndef BLOCK_DOES_FIRST_LINE + nsIFrame* parent; +#endif aDeletedFrame->GetParent(&parent); NS_ASSERTION(flow == parent, "messed up delete code"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); @@ -4547,6 +4525,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { @@ -4554,14 +4533,15 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, // removed a block that preceeded the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4596,106 +4576,7 @@ nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, } return NS_OK; } - -static PRBool -IsEmptyLine(nsIPresContext* aPresContext, nsLineBox* aLine) -{ - PRInt32 i, n = aLine->ChildCount(); - nsIFrame* frame = aLine->mFirstChild; - for (i = 0; i < n; i++) { - nsIContent* content; - nsresult rv = frame->GetContent(&content); - if (NS_FAILED(rv) || (nsnull == content)) { - // If it doesn't have any content then this can't be an empty line - return PR_FALSE; - } - nsITextContent* tc; - rv = content->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_FAILED(rv) || (nsnull == tc)) { - // If it's not text content then this can't be an empty line - NS_RELEASE(content); - return PR_FALSE; - } - - const nsTextFragment* frag; - PRInt32 numFrags; - rv = tc->GetText(frag, numFrags); - if (NS_FAILED(rv)) { - NS_RELEASE(content); - NS_RELEASE(tc); - return PR_FALSE; - } - - // If the text has any non-whitespace characters in it then the - // line is not an empty line. - while (--numFrags >= 0) { - PRInt32 len = frag->GetLength(); - if (frag->Is2b()) { - const PRUnichar* cp = frag->Get2b(); - const PRUnichar* end = cp + len; - while (cp < end) { - PRUnichar ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - else { - const char* cp = frag->Get1b(); - const char* end = cp + len; - while (cp < end) { - char ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - frag++; - } - - NS_RELEASE(tc); - NS_RELEASE(content); - frame->GetNextSibling(&frame); - } - return PR_TRUE; -} - -void -nsBlockFrame::MarkEmptyLines(nsIPresContext* aPresContext) -{ - // PRE-formatted content considers whitespace significant - const nsStyleText* text; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) text); - if ((NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == text->mWhiteSpace)) { - return; - } - - PRBool afterBlock = PR_TRUE; - nsLineBox* line = mLines; - while (nsnull != line) { - if (line->IsBlock()) { - afterBlock = PR_TRUE; - } - else if (afterBlock) { - afterBlock = PR_FALSE; - - // This is an inline line and it is immediately after a block - // (or its our first line). See if it contains nothing but - // collapsible text. - PRBool isEmpty = IsEmptyLine(aPresContext, line); - line->SetIsEmptyLine(isEmpty); - } - else { - line->SetIsEmptyLine(PR_FALSE); - } - line = line->mNext; - } -} +#endif void nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, @@ -5609,6 +5490,40 @@ nsBlockFrame::VerifyTree() const return NS_OK; } +NS_IMETHODIMP +nsBlockFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + PRUint32 sum = sizeof(*this); + + // Add in size of each line object + nsLineBox* line = mLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + line = mOverflowLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + + // Add in text-run data + nsTextRun* runs = mTextRuns; + while (runs) { + PRUint32 runSize; + runs->SizeOf(aHandler, &runSize); + sum += runSize; + runs = runs->GetNext(); + } + + *aResult = sum; + return NS_OK; +} + //---------------------------------------------------------------------- NS_IMETHODIMP @@ -5643,6 +5558,7 @@ nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext) return fls; } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) { @@ -5652,6 +5568,7 @@ nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) mStyleContext, PR_FALSE, &fls); return fls; } +#endif NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, @@ -5677,6 +5594,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(firstLetterStyle); } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext); if (nsnull != firstLineStyle) { mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE; @@ -5686,6 +5604,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif NS_RELEASE(firstLineStyle); } +#endif } rv = AddFrames(&aPresContext, aChildList, nsnull); @@ -6238,9 +6157,15 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) if (line->IsBlock()) { seenBlock = PR_TRUE; } - if (line->IsFirstLine() || line->IsBlock()) { +#ifdef BLOCK_DOES_FIRST_LINE + if (line->IsFirstLine()) { NS_ASSERTION(1 == line->mChildCount, "bad first line"); } +#endif + if (line->IsBlock()) { + NS_ASSERTION(1 == line->mChildCount, "bad first line"); + } +#ifdef BLOCK_DOES_FIRST_LINE if (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) { if (seenBlock) { NS_ASSERTION(!line->IsFirstLine(), "bad first line"); @@ -6249,6 +6174,7 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) NS_ASSERTION(line->IsFirstLine(), "bad first line"); } } +#endif } NS_ASSERTION(line->mChildCount < MAX_LINE_COUNT, "bad line child count"); count += line->mChildCount; diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 0f7537724c3..fb85992e2d1 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -40,7 +40,9 @@ class nsFirstLineFrame; */ #define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x80000000 #define NS_BLOCK_IS_HTML_PARAGRAPH 0x40000000 +#ifdef BLOCK_DOES_FIRST_LINE #define NS_BLOCK_HAS_FIRST_LINE_STYLE 0x20000000 +#endif #define NS_BLOCK_HAS_FIRST_LETTER_STYLE 0x10000000 #define nsBlockFrameSuper nsHTMLContainerFrame @@ -99,6 +101,7 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; NS_IMETHOD VerifyTree() const; NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame); NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, @@ -145,7 +148,9 @@ protected: nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext); +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* GetFirstLineStyle(nsIPresContext* aPresContext); +#endif void SetFlags(PRUint32 aFlags) { mFlags = aFlags; @@ -171,12 +176,11 @@ protected: nsBlockReflowState& aState, nsHTMLReflowMetrics& aMetrics); - void MarkEmptyLines(nsIPresContext* aPresContext); - nsresult AddFrames(nsIPresContext* aPresContext, nsIFrame* aFrameList, nsIFrame* aPrevSibling); +#ifdef BLOCK_DOES_FIRST_LINE nsresult AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, nsIFrame* aFrameList, @@ -185,16 +189,18 @@ protected: nsIFrame* TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, nsIFrame* aFromKid); - void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame); - - nsresult DoRemoveFrame(nsIPresContext* aPresContext, - nsIFrame* aDeletedFrame); - nsresult RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, nsIFrame* aDeletedFrame); nsresult WrapFramesInFirstLineFrame(nsIPresContext* aPresContext); +#endif + + void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame); + + nsresult DoRemoveFrame(nsIPresContext* aPresContext, + nsIFrame* aDeletedFrame); + nsresult PrepareInitialReflow(nsBlockReflowState& aState); diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index d44af8f27d6..2d24571254d 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -45,8 +45,6 @@ #include "nsITextContent.h" #include "nsStyleChangeList.h" -// XXX for IsEmptyLine -#include "nsTextFragment.h" #include "nsIFocusTracker.h" #include "nsIFrameSelection.h" @@ -985,6 +983,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // It is possible that we just acquired first-line style. See if // this is the case, and if so, fix things up. if (0 == (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState)) { @@ -1005,6 +1004,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } } +#endif return rv; } @@ -2185,7 +2185,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState, // Setup the line-layout for the new line aState.mCurrentLine = aLine; aLine->ClearDirty(); - aLine->SetNeedDidReflow(); // Now that we know what kind of line we have, reflow it nsRect oldCombinedArea = aLine->mCombinedArea; @@ -2643,38 +2642,6 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState, return PR_FALSE; } -#if 0 - const nsStyleText* styleText; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText); - if ((NS_STYLE_WHITESPACE_PRE == styleText->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == styleText->mWhiteSpace)) { - // Since whitespace is significant, we know that the paragraph - // is not empty (even if it has no text in it because it has - return PR_FALSE; - -static PRBool -IsEmptyHTMLParagraph(nsIFrame* aFrame) -{ - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf)) && - nsBlockReflowContext::IsHTMLParagraph(aFrame)) { - if (!bf->mLines) { - // It's an html paragraph and it's empty - return PR_TRUE; - } - - nsLineBox* line = bf->mLines; - while (line) { - if (!IsEmptyLine(line)) { - return PR_FALSE; - } - line = line->mNext; - } - } - return PR_FALSE; -} -#endif - nsIFrame* nsBlockFrame::GetTopBlockChild() { @@ -3071,6 +3038,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, availWidth, availHeight, impactedByFloaters, PR_FALSE /*XXX isTopOfPage*/); + + // XXX Unfortunately we need to know this before reflowing the first + // inline frame in the line. FIX ME. if ((0 == aLineLayout.GetLineNumber()) && (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) { aLineLayout.SetFirstLetterStyleOK(PR_TRUE); @@ -3287,10 +3257,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, // line and don't stop the line reflow... PRBool splitLine = !reflowingFirstLetter; if (reflowingFirstLetter) { +#ifdef BLOCK_DOES_FIRST_LINE if (aLine->IsFirstLine()) { splitLine = PR_TRUE; } - else { + else +#endif + { nsIAtom* frameType; if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) { if (frameType == nsLayoutAtoms::inlineFrame) { @@ -3391,7 +3364,9 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, aLine->mNext = to; } to->SetIsBlock(aLine->IsBlock()); +#ifdef BLOCK_DOES_FIRST_LINE to->SetIsFirstLine(aLine->IsFirstLine()); +#endif aLine->mChildCount -= pushCount; // Let line layout know that some frames are no longer part of its @@ -3656,20 +3631,6 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, aLine->mMaxElementWidth = aMaxElementSize.width; } -#if XXX_need_line_outside_children - // Compute LINE_OUTSIDE_CHILDREN state for this line. The bit is set - // if any child frame has outside children. - if ((aLine->mCombinedArea.x < aLine->mBounds.x) || - (aLine->mCombinedArea.XMost() > aLine->mBounds.XMost()) || - (aLine->mCombinedArea.y < aLine->mBounds.y) || - (aLine->mCombinedArea.YMost() > aLine->mBounds.YMost())) { - aLine->SetOutsideChildren(); - } - else { - aLine->ClearOutsideChildren(); - } -#endif - // Update xmost nscoord xmost = aLine->mBounds.XMost(); if (xmost > aState.mKidXMost) { @@ -3847,6 +3808,7 @@ nsBlockFrame::LastChild() return nsnull; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) { @@ -3938,6 +3900,7 @@ nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) return rv; } +#endif NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, @@ -3963,12 +3926,14 @@ nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, nsLineBox* lastLine = nsLineBox::LastLine(mLines); if (lastLine) { lastKid = lastLine->LastChild(); +#ifdef BLOCK_DOES_FIRST_LINE if (lastLine->IsFirstLine()) { // Get last frame in the nsFirstLineFrame lastKid->FirstChild(nsnull, &lastKid); nsFrameList frames(lastKid); lastKid = frames.LastChild(); } +#endif } // Add frames after the last child @@ -4058,6 +4023,7 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, nsLineBox* prevSibLine = nsnull; PRInt32 prevSiblingIndex = -1; if (aPrevSibling) { +#ifdef BLOCK_DOES_FIRST_LINE // Its possible we have an nsFirstLineFrame managing some of our // child frames. If we do and the AddFrames is targetted at it, // use AddFirstLineFrames to get the frames properly placed. @@ -4079,7 +4045,9 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, (nsFirstLineFrame*)prevSiblingParent, aFrameList, aPrevSibling); } - else { + else +#endif + { // Find the line that contains the previous sibling prevSibLine = nsLineBox::FindLineContaining(mLines, aPrevSibling, &prevSiblingIndex); @@ -4091,12 +4059,14 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, } } } +#ifdef BLOCK_DOES_FIRST_LINE else if (mLines && mLines->IsFirstLine()) { mLines->MarkDirty(); return AddFirstLineFrames(aPresContext, (nsFirstLineFrame*)mLines->mFirstChild, aFrameList, nsnull); } +#endif // Find the frame following aPrevSibling so that we can join up the // two lists of frames. @@ -4168,20 +4138,22 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, aPrevSibling->SetNextSibling(prevSiblingNextFrame); } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { // We just added one or more frame(s) to the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4310,6 +4282,7 @@ nsBlockFrame::TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, return kids.FirstChild(); } +#endif void nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) @@ -4404,12 +4377,14 @@ nsresult nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, nsIFrame* aDeletedFrame) { +#ifdef BLOCK_DOES_FIRST_LINE nsIFrame* parent; aDeletedFrame->GetParent(&parent); if (parent != this) { return RemoveFirstLineFrame(aPresContext, (nsFirstLineFrame*)parent, aDeletedFrame); } +#endif // Find the line and the previous sibling that contains // deletedFrame; we also find the pointer to the line. @@ -4446,6 +4421,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, while (nsnull != aDeletedFrame) { while ((nsnull != line) && (nsnull != aDeletedFrame)) { #ifdef NS_DEBUG +#ifndef BLOCK_DOES_FIRST_LINE + nsIFrame* parent; +#endif aDeletedFrame->GetParent(&parent); NS_ASSERTION(flow == parent, "messed up delete code"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); @@ -4547,6 +4525,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { @@ -4554,14 +4533,15 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, // removed a block that preceeded the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4596,106 +4576,7 @@ nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, } return NS_OK; } - -static PRBool -IsEmptyLine(nsIPresContext* aPresContext, nsLineBox* aLine) -{ - PRInt32 i, n = aLine->ChildCount(); - nsIFrame* frame = aLine->mFirstChild; - for (i = 0; i < n; i++) { - nsIContent* content; - nsresult rv = frame->GetContent(&content); - if (NS_FAILED(rv) || (nsnull == content)) { - // If it doesn't have any content then this can't be an empty line - return PR_FALSE; - } - nsITextContent* tc; - rv = content->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_FAILED(rv) || (nsnull == tc)) { - // If it's not text content then this can't be an empty line - NS_RELEASE(content); - return PR_FALSE; - } - - const nsTextFragment* frag; - PRInt32 numFrags; - rv = tc->GetText(frag, numFrags); - if (NS_FAILED(rv)) { - NS_RELEASE(content); - NS_RELEASE(tc); - return PR_FALSE; - } - - // If the text has any non-whitespace characters in it then the - // line is not an empty line. - while (--numFrags >= 0) { - PRInt32 len = frag->GetLength(); - if (frag->Is2b()) { - const PRUnichar* cp = frag->Get2b(); - const PRUnichar* end = cp + len; - while (cp < end) { - PRUnichar ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - else { - const char* cp = frag->Get1b(); - const char* end = cp + len; - while (cp < end) { - char ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - frag++; - } - - NS_RELEASE(tc); - NS_RELEASE(content); - frame->GetNextSibling(&frame); - } - return PR_TRUE; -} - -void -nsBlockFrame::MarkEmptyLines(nsIPresContext* aPresContext) -{ - // PRE-formatted content considers whitespace significant - const nsStyleText* text; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) text); - if ((NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == text->mWhiteSpace)) { - return; - } - - PRBool afterBlock = PR_TRUE; - nsLineBox* line = mLines; - while (nsnull != line) { - if (line->IsBlock()) { - afterBlock = PR_TRUE; - } - else if (afterBlock) { - afterBlock = PR_FALSE; - - // This is an inline line and it is immediately after a block - // (or its our first line). See if it contains nothing but - // collapsible text. - PRBool isEmpty = IsEmptyLine(aPresContext, line); - line->SetIsEmptyLine(isEmpty); - } - else { - line->SetIsEmptyLine(PR_FALSE); - } - line = line->mNext; - } -} +#endif void nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, @@ -5609,6 +5490,40 @@ nsBlockFrame::VerifyTree() const return NS_OK; } +NS_IMETHODIMP +nsBlockFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + PRUint32 sum = sizeof(*this); + + // Add in size of each line object + nsLineBox* line = mLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + line = mOverflowLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + + // Add in text-run data + nsTextRun* runs = mTextRuns; + while (runs) { + PRUint32 runSize; + runs->SizeOf(aHandler, &runSize); + sum += runSize; + runs = runs->GetNext(); + } + + *aResult = sum; + return NS_OK; +} + //---------------------------------------------------------------------- NS_IMETHODIMP @@ -5643,6 +5558,7 @@ nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext) return fls; } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) { @@ -5652,6 +5568,7 @@ nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) mStyleContext, PR_FALSE, &fls); return fls; } +#endif NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, @@ -5677,6 +5594,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(firstLetterStyle); } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext); if (nsnull != firstLineStyle) { mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE; @@ -5686,6 +5604,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif NS_RELEASE(firstLineStyle); } +#endif } rv = AddFrames(&aPresContext, aChildList, nsnull); @@ -6238,9 +6157,15 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) if (line->IsBlock()) { seenBlock = PR_TRUE; } - if (line->IsFirstLine() || line->IsBlock()) { +#ifdef BLOCK_DOES_FIRST_LINE + if (line->IsFirstLine()) { NS_ASSERTION(1 == line->mChildCount, "bad first line"); } +#endif + if (line->IsBlock()) { + NS_ASSERTION(1 == line->mChildCount, "bad first line"); + } +#ifdef BLOCK_DOES_FIRST_LINE if (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) { if (seenBlock) { NS_ASSERTION(!line->IsFirstLine(), "bad first line"); @@ -6249,6 +6174,7 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) NS_ASSERTION(line->IsFirstLine(), "bad first line"); } } +#endif } NS_ASSERTION(line->mChildCount < MAX_LINE_COUNT, "bad line child count"); count += line->mChildCount; diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index d44af8f27d6..2d24571254d 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -45,8 +45,6 @@ #include "nsITextContent.h" #include "nsStyleChangeList.h" -// XXX for IsEmptyLine -#include "nsTextFragment.h" #include "nsIFocusTracker.h" #include "nsIFrameSelection.h" @@ -985,6 +983,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // It is possible that we just acquired first-line style. See if // this is the case, and if so, fix things up. if (0 == (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState)) { @@ -1005,6 +1004,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } } +#endif return rv; } @@ -2185,7 +2185,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState, // Setup the line-layout for the new line aState.mCurrentLine = aLine; aLine->ClearDirty(); - aLine->SetNeedDidReflow(); // Now that we know what kind of line we have, reflow it nsRect oldCombinedArea = aLine->mCombinedArea; @@ -2643,38 +2642,6 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState, return PR_FALSE; } -#if 0 - const nsStyleText* styleText; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText); - if ((NS_STYLE_WHITESPACE_PRE == styleText->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == styleText->mWhiteSpace)) { - // Since whitespace is significant, we know that the paragraph - // is not empty (even if it has no text in it because it has - return PR_FALSE; - -static PRBool -IsEmptyHTMLParagraph(nsIFrame* aFrame) -{ - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf)) && - nsBlockReflowContext::IsHTMLParagraph(aFrame)) { - if (!bf->mLines) { - // It's an html paragraph and it's empty - return PR_TRUE; - } - - nsLineBox* line = bf->mLines; - while (line) { - if (!IsEmptyLine(line)) { - return PR_FALSE; - } - line = line->mNext; - } - } - return PR_FALSE; -} -#endif - nsIFrame* nsBlockFrame::GetTopBlockChild() { @@ -3071,6 +3038,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, availWidth, availHeight, impactedByFloaters, PR_FALSE /*XXX isTopOfPage*/); + + // XXX Unfortunately we need to know this before reflowing the first + // inline frame in the line. FIX ME. if ((0 == aLineLayout.GetLineNumber()) && (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) { aLineLayout.SetFirstLetterStyleOK(PR_TRUE); @@ -3287,10 +3257,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, // line and don't stop the line reflow... PRBool splitLine = !reflowingFirstLetter; if (reflowingFirstLetter) { +#ifdef BLOCK_DOES_FIRST_LINE if (aLine->IsFirstLine()) { splitLine = PR_TRUE; } - else { + else +#endif + { nsIAtom* frameType; if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) { if (frameType == nsLayoutAtoms::inlineFrame) { @@ -3391,7 +3364,9 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, aLine->mNext = to; } to->SetIsBlock(aLine->IsBlock()); +#ifdef BLOCK_DOES_FIRST_LINE to->SetIsFirstLine(aLine->IsFirstLine()); +#endif aLine->mChildCount -= pushCount; // Let line layout know that some frames are no longer part of its @@ -3656,20 +3631,6 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, aLine->mMaxElementWidth = aMaxElementSize.width; } -#if XXX_need_line_outside_children - // Compute LINE_OUTSIDE_CHILDREN state for this line. The bit is set - // if any child frame has outside children. - if ((aLine->mCombinedArea.x < aLine->mBounds.x) || - (aLine->mCombinedArea.XMost() > aLine->mBounds.XMost()) || - (aLine->mCombinedArea.y < aLine->mBounds.y) || - (aLine->mCombinedArea.YMost() > aLine->mBounds.YMost())) { - aLine->SetOutsideChildren(); - } - else { - aLine->ClearOutsideChildren(); - } -#endif - // Update xmost nscoord xmost = aLine->mBounds.XMost(); if (xmost > aState.mKidXMost) { @@ -3847,6 +3808,7 @@ nsBlockFrame::LastChild() return nsnull; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) { @@ -3938,6 +3900,7 @@ nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) return rv; } +#endif NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, @@ -3963,12 +3926,14 @@ nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, nsLineBox* lastLine = nsLineBox::LastLine(mLines); if (lastLine) { lastKid = lastLine->LastChild(); +#ifdef BLOCK_DOES_FIRST_LINE if (lastLine->IsFirstLine()) { // Get last frame in the nsFirstLineFrame lastKid->FirstChild(nsnull, &lastKid); nsFrameList frames(lastKid); lastKid = frames.LastChild(); } +#endif } // Add frames after the last child @@ -4058,6 +4023,7 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, nsLineBox* prevSibLine = nsnull; PRInt32 prevSiblingIndex = -1; if (aPrevSibling) { +#ifdef BLOCK_DOES_FIRST_LINE // Its possible we have an nsFirstLineFrame managing some of our // child frames. If we do and the AddFrames is targetted at it, // use AddFirstLineFrames to get the frames properly placed. @@ -4079,7 +4045,9 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, (nsFirstLineFrame*)prevSiblingParent, aFrameList, aPrevSibling); } - else { + else +#endif + { // Find the line that contains the previous sibling prevSibLine = nsLineBox::FindLineContaining(mLines, aPrevSibling, &prevSiblingIndex); @@ -4091,12 +4059,14 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, } } } +#ifdef BLOCK_DOES_FIRST_LINE else if (mLines && mLines->IsFirstLine()) { mLines->MarkDirty(); return AddFirstLineFrames(aPresContext, (nsFirstLineFrame*)mLines->mFirstChild, aFrameList, nsnull); } +#endif // Find the frame following aPrevSibling so that we can join up the // two lists of frames. @@ -4168,20 +4138,22 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, aPrevSibling->SetNextSibling(prevSiblingNextFrame); } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { // We just added one or more frame(s) to the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4310,6 +4282,7 @@ nsBlockFrame::TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, return kids.FirstChild(); } +#endif void nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) @@ -4404,12 +4377,14 @@ nsresult nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, nsIFrame* aDeletedFrame) { +#ifdef BLOCK_DOES_FIRST_LINE nsIFrame* parent; aDeletedFrame->GetParent(&parent); if (parent != this) { return RemoveFirstLineFrame(aPresContext, (nsFirstLineFrame*)parent, aDeletedFrame); } +#endif // Find the line and the previous sibling that contains // deletedFrame; we also find the pointer to the line. @@ -4446,6 +4421,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, while (nsnull != aDeletedFrame) { while ((nsnull != line) && (nsnull != aDeletedFrame)) { #ifdef NS_DEBUG +#ifndef BLOCK_DOES_FIRST_LINE + nsIFrame* parent; +#endif aDeletedFrame->GetParent(&parent); NS_ASSERTION(flow == parent, "messed up delete code"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); @@ -4547,6 +4525,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { @@ -4554,14 +4533,15 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, // removed a block that preceeded the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4596,106 +4576,7 @@ nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, } return NS_OK; } - -static PRBool -IsEmptyLine(nsIPresContext* aPresContext, nsLineBox* aLine) -{ - PRInt32 i, n = aLine->ChildCount(); - nsIFrame* frame = aLine->mFirstChild; - for (i = 0; i < n; i++) { - nsIContent* content; - nsresult rv = frame->GetContent(&content); - if (NS_FAILED(rv) || (nsnull == content)) { - // If it doesn't have any content then this can't be an empty line - return PR_FALSE; - } - nsITextContent* tc; - rv = content->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_FAILED(rv) || (nsnull == tc)) { - // If it's not text content then this can't be an empty line - NS_RELEASE(content); - return PR_FALSE; - } - - const nsTextFragment* frag; - PRInt32 numFrags; - rv = tc->GetText(frag, numFrags); - if (NS_FAILED(rv)) { - NS_RELEASE(content); - NS_RELEASE(tc); - return PR_FALSE; - } - - // If the text has any non-whitespace characters in it then the - // line is not an empty line. - while (--numFrags >= 0) { - PRInt32 len = frag->GetLength(); - if (frag->Is2b()) { - const PRUnichar* cp = frag->Get2b(); - const PRUnichar* end = cp + len; - while (cp < end) { - PRUnichar ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - else { - const char* cp = frag->Get1b(); - const char* end = cp + len; - while (cp < end) { - char ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - frag++; - } - - NS_RELEASE(tc); - NS_RELEASE(content); - frame->GetNextSibling(&frame); - } - return PR_TRUE; -} - -void -nsBlockFrame::MarkEmptyLines(nsIPresContext* aPresContext) -{ - // PRE-formatted content considers whitespace significant - const nsStyleText* text; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) text); - if ((NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == text->mWhiteSpace)) { - return; - } - - PRBool afterBlock = PR_TRUE; - nsLineBox* line = mLines; - while (nsnull != line) { - if (line->IsBlock()) { - afterBlock = PR_TRUE; - } - else if (afterBlock) { - afterBlock = PR_FALSE; - - // This is an inline line and it is immediately after a block - // (or its our first line). See if it contains nothing but - // collapsible text. - PRBool isEmpty = IsEmptyLine(aPresContext, line); - line->SetIsEmptyLine(isEmpty); - } - else { - line->SetIsEmptyLine(PR_FALSE); - } - line = line->mNext; - } -} +#endif void nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, @@ -5609,6 +5490,40 @@ nsBlockFrame::VerifyTree() const return NS_OK; } +NS_IMETHODIMP +nsBlockFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + PRUint32 sum = sizeof(*this); + + // Add in size of each line object + nsLineBox* line = mLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + line = mOverflowLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + + // Add in text-run data + nsTextRun* runs = mTextRuns; + while (runs) { + PRUint32 runSize; + runs->SizeOf(aHandler, &runSize); + sum += runSize; + runs = runs->GetNext(); + } + + *aResult = sum; + return NS_OK; +} + //---------------------------------------------------------------------- NS_IMETHODIMP @@ -5643,6 +5558,7 @@ nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext) return fls; } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) { @@ -5652,6 +5568,7 @@ nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) mStyleContext, PR_FALSE, &fls); return fls; } +#endif NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, @@ -5677,6 +5594,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(firstLetterStyle); } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext); if (nsnull != firstLineStyle) { mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE; @@ -5686,6 +5604,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif NS_RELEASE(firstLineStyle); } +#endif } rv = AddFrames(&aPresContext, aChildList, nsnull); @@ -6238,9 +6157,15 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) if (line->IsBlock()) { seenBlock = PR_TRUE; } - if (line->IsFirstLine() || line->IsBlock()) { +#ifdef BLOCK_DOES_FIRST_LINE + if (line->IsFirstLine()) { NS_ASSERTION(1 == line->mChildCount, "bad first line"); } +#endif + if (line->IsBlock()) { + NS_ASSERTION(1 == line->mChildCount, "bad first line"); + } +#ifdef BLOCK_DOES_FIRST_LINE if (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) { if (seenBlock) { NS_ASSERTION(!line->IsFirstLine(), "bad first line"); @@ -6249,6 +6174,7 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) NS_ASSERTION(line->IsFirstLine(), "bad first line"); } } +#endif } NS_ASSERTION(line->mChildCount < MAX_LINE_COUNT, "bad line child count"); count += line->mChildCount; diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 5e84d5bcc41..1c908b57fd5 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -667,3 +667,13 @@ nsContainerFrame::List(FILE* out, PRInt32 aIndent) const return NS_OK; } + +NS_IMETHODIMP +nsContainerFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index c4b75ba0374..405e6d7c5ce 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -50,6 +50,7 @@ public: nsIFrame* aOldFrame, nsIFrame* aNewFrame); NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; // nsIHTMLReflow overrides NS_IMETHOD DidReflow(nsIPresContext& aPresContext, diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 4c23ab15e0c..603d9b1a016 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -205,6 +205,15 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, ll.EndLineReflow(); } else { +// XXX currently the block code sets this up; see comment in +// ReflowInlineFrames +#if XXX + // Only the first-in-flow frame of a first-letter frame gets the + // special first-letter reflow treatment. + if (!mPrevInFlow) { + rs.mLineLayout->SetFirstLetterStyleOK(PR_TRUE); + } +#endif htmlReflow->Reflow(aPresContext, aMetrics, rs, aReflowStatus); } diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 30ef95ff9ac..0a3ed98f576 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1586,6 +1586,16 @@ nsFrame::DumpBaseRegressionData(FILE* out, PRInt32 aIndent) } while (nsnull != list); } +NS_IMETHODIMP +nsFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} + NS_IMETHODIMP nsFrame::VerifyTree() const { diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 312b2fcc371..b6e54383358 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -223,6 +223,7 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD DumpRegressionData(FILE* out, PRInt32 aIndent); + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; NS_IMETHOD VerifyTree() const; NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, nsSpread aSpread); NS_IMETHOD GetSelected(PRBool *aSelected) const; diff --git a/layout/generic/nsHTMLFrame.cpp b/layout/generic/nsHTMLFrame.cpp index 7319ef12a4d..a728d62066e 100644 --- a/layout/generic/nsHTMLFrame.cpp +++ b/layout/generic/nsHTMLFrame.cpp @@ -89,6 +89,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; // XXX Temporary hack... NS_IMETHOD SetRect(const nsRect& aRect); @@ -450,3 +451,13 @@ RootFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Root", aResult); } + +NS_IMETHODIMP +RootFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 60fbc3530e6..b7fad5c525c 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -31,6 +31,7 @@ class nsIFrame; class nsIPresContext; class nsIPresShell; class nsIRenderingContext; +class nsISizeOfHandler; class nsISpaceManager; class nsIStyleContext; class nsIView; @@ -588,7 +589,7 @@ public: * called when the frame has been scrolled to a new * position. only called for frames with views. */ - NS_IMETHOD Scrolled(nsIView *aView) = 0; + NS_IMETHOD Scrolled(nsIView *aView) = 0; // Debugging NS_IMETHOD List(FILE* out, PRInt32 aIndent) const = 0; @@ -608,6 +609,23 @@ public: */ NS_IMETHOD DumpRegressionData(FILE* out, PRInt32 aIndent) = 0; + /** + * Get the size of the frame object. The size value should include + * all subordinate data referenced by the frame that is not + * accounted for by child frames. However, this value should not + * include the content objects, style contexts, views or other data + * that lies logically outside the frame system. + * + * If the implementation so chooses, instead of returning the total + * subordinate data it may instead use the sizeof handler to store + * away subordinate data under its own key so that the subordinate + * data may be tabulated independently of the frame itself. + * + * The caller is responsible for recursing over all child-lists that + * the frame supports. + */ + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const = 0; + NS_IMETHOD VerifyTree() const = 0; /** Selection related calls diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 62230561b52..cb6136deb7f 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -55,6 +55,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsTextFragment.h" #include "nsIDOMHTMLMapElement.h" #include "nsIStyleSet.h" +#include "nsLayoutAtoms.h" #ifdef DEBUG #undef NOISY_IMAGE_LOADING @@ -859,3 +860,26 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext, return NS_OK; } + +NS_IMETHODIMP +nsImageFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = nsLayoutAtoms::imageFrame; + NS_ADDREF(*aType); + return NS_OK; +} + +// Note: this doesn't factor in: +// -- the mImageMap (it might be shared) +NS_IMETHODIMP +nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + PRUint32 sum = sizeof(*this) - sizeof(mImageLoader) + + mImageLoader.GetDataSize(); + *aResult = sum; + return NS_OK; +} diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 104187f5e72..ccd6cd67bbf 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -59,6 +59,8 @@ public: nsIContent* aChild, nsIAtom* aAttribute, PRInt32 aHint); + NS_IMETHOD GetFrameType(nsIAtom** aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: virtual ~nsImageFrame(); diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index a6255be67cc..04fc9b75ccb 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -78,7 +78,7 @@ public: const nsString& GetAltText() const { return mAltText; } PRBool GetSuppress() const { return mSuppressFeedback; } - virtual void SizeOf(nsISizeOfHandler* aHandler) const; + virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; nsString mBase; nsString mHREF; @@ -106,15 +106,18 @@ Area::~Area() } void -Area::SizeOf(nsISizeOfHandler* aHandler) const +Area::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const { - aHandler->Add(sizeof(*this)); - aHandler->Add((size_t) (- ((PRInt32)sizeof(nsString) * 4) ) ); - mBase.SizeOf(aHandler); - mHREF.SizeOf(aHandler); - mTarget.SizeOf(aHandler); - mAltText.SizeOf(aHandler); - aHandler->Add(mNumCoords * sizeof(nscoord)); + if (aResult) { + PRUint32 sum = sizeof(*this); + PRUint32 s; + mBase.SizeOf(aHandler, &s); sum += s; + mHREF.SizeOf(aHandler, &s); sum += s; + mTarget.SizeOf(aHandler, &s); sum += s; + mAltText.SizeOf(aHandler, &s); sum += s; + sum += mNumCoords * sizeof(nscoord); + *aResult = sum; + } } #include @@ -1132,3 +1135,19 @@ nsImageMap::DocumentWillBeDestroyed(nsIDocument *aDocument) { return NS_OK; } + +void +nsImageMap::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + PRInt32 i, n = mAreas.Count(); + for (i = 0; i < n; i++) { + Area* area = (Area*) mAreas.ElementAt(i); + PRUint32 areaSize; + area->SizeOf(aHandler, &areaSize); + sum += areaSize; + } + *aResult = sum; + } +} diff --git a/layout/generic/nsImageMap.h b/layout/generic/nsImageMap.h index ccf2f690a1a..e0a5f7067ff 100644 --- a/layout/generic/nsImageMap.h +++ b/layout/generic/nsImageMap.h @@ -62,6 +62,8 @@ public: void Draw(nsIPresContext& aCX, nsIRenderingContext& aRC); + void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; + // nsISupports NS_DECL_ISUPPORTS diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 62fc70926e5..1c2b643647e 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -1240,6 +1240,20 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext, } DrainOverflow(&aPresContext); + if (IsFrameTreeTooDeep(aReflowState, aMetrics)) { +#ifdef DEBUG_kipp + { + extern char* nsPresShell_ReflowStackPointerTop; + char marker; + char* newsp = (char*) ▮ + printf("XXX: frame tree is too deep; approx stack size = %d\n", + nsPresShell_ReflowStackPointerTop - newsp); + } +#endif + aStatus = NS_FRAME_COMPLETE; + return NS_OK; + } + // Set our own reflow state (additional state above and beyond // aReflowState) InlineReflowState irs; @@ -1472,6 +1486,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, aMetrics.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; +#ifdef DEBUG_kipp // Note: we use the actual font height for sizing our selves // instead of the computed font height. On systems where they // disagree the actual font height is more appropriate. This @@ -1484,6 +1499,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, if (getenv("GECKO_USE_COMPUTED_HEIGHT")) { useComputedHeight = PR_TRUE; } + firstTime = 0; } #endif if (useComputedHeight) { @@ -1505,6 +1521,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, aMetrics.height = computedHeight; } } +#endif /* DEBUG_kipp */ NS_RELEASE(fm); } @@ -1892,8 +1909,16 @@ nsFirstLineFrame::AppendFrames(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { +#ifdef BLOCK_DOES_FIRST_LINE return mParent->AppendFrames(aPresContext, aPresShell, aListName, aFrameList); +#else + nsresult rv = nsInlineFrame::AppendFrames(aPresContext, aPresShell, + aListName, aFrameList); +// nsFrameList frames(aFrameList); +// ReResolveChildList(&aPresContext, mStyleContext, frames); + return rv; +#endif } NS_IMETHODIMP @@ -1903,8 +1928,16 @@ nsFirstLineFrame::InsertFrames(nsIPresContext& aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { +#ifdef BLOCK_DOES_FIRST_LINE return mParent->InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); +#else + nsresult rv = nsInlineFrame::InsertFrames(aPresContext, aPresShell, + aListName, aPrevFrame, aFrameList); +// nsFrameList frames(aFrameList); +// ReResolveChildList(&aPresContext, mStyleContext, frames); + return rv; +#endif } NS_IMETHODIMP @@ -1913,10 +1946,17 @@ nsFirstLineFrame::RemoveFrame(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { +#ifdef BLOCK_DOES_FIRST_LINE return mParent->RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); +#else + nsresult rv = nsInlineFrame::RemoveFrame(aPresContext, aPresShell, + aListName, aOldFrame); + return rv; +#endif } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsFirstLineFrame::AppendFrames2(nsIPresContext* aPresContext, nsIFrame* aFrameList) @@ -1952,9 +1992,10 @@ nsFirstLineFrame::RemoveFrame2(nsIPresContext* aPresContext, mFrames.RemoveFrame(aOldFrame); return NS_OK; } +#endif void -nsFirstLineFrame::RemoveFramesFrom(nsIFrame* aFrame) +nsFirstLineFrame::StealFramesFrom(nsIFrame* aFrame) { nsIFrame* prevFrame = mFrames.GetPrevSiblingFor(aFrame); if (prevFrame) { @@ -2138,3 +2179,14 @@ nsFirstLineFrame::Reflow(nsIPresContext& aPresContext, return rv; } + +NS_IMETHODIMP +nsPositionedInlineFrame::SizeOf(nsISizeOfHandler* aHandler, + PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/generic/nsInlineFrame.h b/layout/generic/nsInlineFrame.h index 77606af3e85..5a0fc328628 100644 --- a/layout/generic/nsInlineFrame.h +++ b/layout/generic/nsInlineFrame.h @@ -192,8 +192,10 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); +#ifdef BLOCK_DOES_FIRST_LINE // AppendFrames/InsertFrames/RemoveFrame are implemented to forward // the method call to the parent frame. +#endif NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -208,6 +210,7 @@ public: nsIAtom* aListName, nsIFrame* aOldFrame); +#ifdef BLOCK_DOES_FIRST_LINE // These methods are used by the parent frame to actually modify the // child frames of the line frame. These methods do not generate // reflow commands. @@ -221,9 +224,14 @@ public: nsresult RemoveFrame2(nsIPresContext* aPresContext, nsIFrame* aOldFrame); - void RemoveFramesFrom(nsIFrame* aFrame); +#endif + // Take frames starting at aFrame until the end of the frame-list + // away from this frame. The caller is presumed to keep them alive. + void StealFramesFrom(nsIFrame* aFrame); - void RemoveAllFrames() { + // Take all of the frames away from this frame. The caller is + // presumed to keep them alive. + void StealAllFrames() { mFrames.SetFrames(nsnull); } @@ -250,6 +258,7 @@ class nsPositionedInlineFrame : public nsInlineFrame { public: NS_IMETHOD Destroy(nsIPresContext& aPresContext); + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, diff --git a/layout/generic/nsLeafFrame.cpp b/layout/generic/nsLeafFrame.cpp index 7687aa5b95c..3f6475c2ad3 100644 --- a/layout/generic/nsLeafFrame.cpp +++ b/layout/generic/nsLeafFrame.cpp @@ -126,3 +126,13 @@ nsLeafFrame::ContentChanged(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsLeafFrame::SizeOf(nsISizeOfHandler* aHandler, + PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/generic/nsLeafFrame.h b/layout/generic/nsLeafFrame.h index 4a85a84e1c0..4c8ddc599bf 100644 --- a/layout/generic/nsLeafFrame.h +++ b/layout/generic/nsLeafFrame.h @@ -41,6 +41,7 @@ public: NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent); + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: virtual ~nsLeafFrame(); diff --git a/layout/generic/nsLineBox.cpp b/layout/generic/nsLineBox.cpp index fad3604abfb..1604722d6cb 100644 --- a/layout/generic/nsLineBox.cpp +++ b/layout/generic/nsLineBox.cpp @@ -26,7 +26,7 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags) { mFirstChild = aFrame; mChildCount = aCount; - mState = LINE_IS_DIRTY | LINE_NEED_DID_REFLOW | flags; + mState = LINE_IS_DIRTY | flags; mFloaters = nsnull; mNext = nsnull; mBounds.SetRect(0,0,0,0); diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index fe54792565b..9961bd6fae8 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -23,16 +23,13 @@ #include "nsPlaceholderFrame.h" #include "nsILineIterator.h" -// bits in nsLineBox.mFlags +// bits in nsLineBox.mState #define LINE_IS_DIRTY 0x1 #define LINE_IS_BLOCK 0x2 -#define LINE_WAS_DIRTY 0x4 -#define LINE_NEED_DID_REFLOW 0x8 -#define LINE_TOP_MARGIN_IS_AUTO 0x10 -#define LINE_BOTTOM_MARGIN_IS_AUTO 0x20 -#define LINE_OUTSIDE_CHILDREN 0x40 -#define LINE_ISA_EMPTY_LINE 0x80 -#define LINE_IS_FIRST_LINE 0x100 +#ifdef BLOCK_DOES_FIRST_LINE +#define LINE_IS_FIRST_LINE 0x4 +#endif +#define LINE_WAS_DIRTY 0x8 class nsISpaceManager; class nsLineBox; @@ -51,17 +48,6 @@ public: nscoord GetHeight() const { return mBounds.height; } - PRBool IsEmptyLine() const { - return 0 != (mState & LINE_ISA_EMPTY_LINE); - } - - void SetIsEmptyLine(PRBool aSetting) { - if (aSetting) - mState |= aSetting; - else - mState &= ~aSetting; - } - //---------------------------------------------------------------------- // XXX old junk nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags); @@ -106,6 +92,7 @@ public: } } +#ifdef BLOCK_DOES_FIRST_LINE PRBool IsFirstLine() const { return 0 != (LINE_IS_FIRST_LINE & mState); } @@ -118,6 +105,7 @@ public: mState &= ~LINE_IS_FIRST_LINE; } } +#endif void MarkDirty() { mState |= LINE_IS_DIRTY; @@ -143,34 +131,6 @@ public: return 0 != (LINE_WAS_DIRTY & mState); } - void SetNeedDidReflow() { - mState |= LINE_NEED_DID_REFLOW; - } - - void ClearNeedDidReflow() { - mState &= ~LINE_NEED_DID_REFLOW; - } - - PRBool NeedsDidReflow() { - return 0 != (LINE_NEED_DID_REFLOW & mState); - } - -#ifdef XXX_need_line_outside_children - void SetOutsideChildren() { - mState |= LINE_OUTSIDE_CHILDREN; - } - - void ClearOutsideChildren() { - mState &= ~LINE_OUTSIDE_CHILDREN; - } - - PRBool OutsideChildren() const { - return 0 != (LINE_OUTSIDE_CHILDREN & mState); - } -#endif - - PRUint16 GetState() const { return mState; } - char* StateToString(char* aBuf, PRInt32 aBufSize) const; PRInt32 IndexOf(nsIFrame* aFrame) const; @@ -185,7 +145,7 @@ public: nsIFrame* mFirstChild; PRUint16 mChildCount; - PRUint16 mState; + PRUint8 mState; PRUint8 mBreakType; nsRect mBounds; nsRect mCombinedArea; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index 4c6825d2bd1..78746b215d5 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -806,7 +806,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // the state out. We need to know how to treat the current frame // when breaking. PRBool notSafeToBreak = CanPlaceFloaterNow() || InWord(); -//XXX PRBool firstLetterOK = mFirstLetterStyleOK; // Apply left margins (as appropriate) to the frame computing the // new starting x,y coordinates for the frame. @@ -979,8 +978,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, parent->DeleteChildsNextInFlow(mPresContext, aFrame); } } -//XXX if (firstLetterOK && !mFirstLetterStyleOK) { -//XXX } // See if we can place the frame. If we can't fit it, then we // return now. diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index 2d21c6a4775..f9caa7007ce 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -113,3 +113,13 @@ nsPlaceholderFrame::List(FILE* out, PRInt32 aIndent) const fputs("\n", out); return NS_OK; } + +NS_IMETHODIMP +nsPlaceholderFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/generic/nsPlaceholderFrame.h b/layout/generic/nsPlaceholderFrame.h index 51dbc522786..55cb6684f1e 100644 --- a/layout/generic/nsPlaceholderFrame.h +++ b/layout/generic/nsPlaceholderFrame.h @@ -56,6 +56,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: nsIFrame* mOutOfFlowFrame; diff --git a/layout/generic/nsSplittableFrame.cpp b/layout/generic/nsSplittableFrame.cpp index 3009b46007e..1f8214b7b6f 100644 --- a/layout/generic/nsSplittableFrame.cpp +++ b/layout/generic/nsSplittableFrame.cpp @@ -193,4 +193,15 @@ nsSplittableFrame::DumpBaseRegressionData(FILE* out, PRInt32 aIndent) IndentBy(out, aIndent); fprintf(out, "\n", PRUptrdiff(mPrevInFlow)); } + +} + +NS_IMETHODIMP +nsSplittableFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; } diff --git a/layout/generic/nsSplittableFrame.h b/layout/generic/nsSplittableFrame.h index 5d7d3d59215..1d0b890af38 100644 --- a/layout/generic/nsSplittableFrame.h +++ b/layout/generic/nsSplittableFrame.h @@ -31,6 +31,7 @@ public: nsIFrame* aPrevInFlow); NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; // Flow member functions. NS_IMETHOD GetPrevInFlow(nsIFrame** aPrevInFlow) const; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 4072151bb73..f79d9b3495c 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -227,6 +227,8 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; + NS_IMETHOD GetPosition(nsIPresContext& aCX, nscoord aXCoord, nsIContent ** aNewContent, @@ -3072,6 +3074,16 @@ nsTextFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } +NS_IMETHODIMP +nsTextFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} + NS_IMETHODIMP nsTextFrame::GetFrameName(nsString& aResult) const { diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index 5ad0c71f099..2eeefbf7788 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -83,6 +83,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: nsresult IncrementalReflow(nsIPresContext& aPresContext, @@ -571,3 +572,13 @@ ViewportFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Viewport", aResult); } + +NS_IMETHODIMP +ViewportFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/html/base/src/nsAreaFrame.cpp b/layout/html/base/src/nsAreaFrame.cpp index 7dbd2510de7..b893078295a 100644 --- a/layout/html/base/src/nsAreaFrame.cpp +++ b/layout/html/base/src/nsAreaFrame.cpp @@ -451,3 +451,14 @@ nsAreaFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Area", aResult); } + +NS_IMETHODIMP +nsAreaFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + nsBlockFrame::SizeOf(aHandler, aResult); + *aResult += sizeof(*this) - sizeof(nsBlockFrame); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/base/src/nsAreaFrame.h b/layout/html/base/src/nsAreaFrame.h index e7de9b6b787..b54ca0eca3f 100644 --- a/layout/html/base/src/nsAreaFrame.h +++ b/layout/html/base/src/nsAreaFrame.h @@ -104,6 +104,8 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; + // nsIAreaFrame NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const; diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index d44af8f27d6..2d24571254d 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -45,8 +45,6 @@ #include "nsITextContent.h" #include "nsStyleChangeList.h" -// XXX for IsEmptyLine -#include "nsTextFragment.h" #include "nsIFocusTracker.h" #include "nsIFrameSelection.h" @@ -985,6 +983,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // It is possible that we just acquired first-line style. See if // this is the case, and if so, fix things up. if (0 == (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState)) { @@ -1005,6 +1004,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } } +#endif return rv; } @@ -2185,7 +2185,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState, // Setup the line-layout for the new line aState.mCurrentLine = aLine; aLine->ClearDirty(); - aLine->SetNeedDidReflow(); // Now that we know what kind of line we have, reflow it nsRect oldCombinedArea = aLine->mCombinedArea; @@ -2643,38 +2642,6 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState, return PR_FALSE; } -#if 0 - const nsStyleText* styleText; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText); - if ((NS_STYLE_WHITESPACE_PRE == styleText->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == styleText->mWhiteSpace)) { - // Since whitespace is significant, we know that the paragraph - // is not empty (even if it has no text in it because it has - return PR_FALSE; - -static PRBool -IsEmptyHTMLParagraph(nsIFrame* aFrame) -{ - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf)) && - nsBlockReflowContext::IsHTMLParagraph(aFrame)) { - if (!bf->mLines) { - // It's an html paragraph and it's empty - return PR_TRUE; - } - - nsLineBox* line = bf->mLines; - while (line) { - if (!IsEmptyLine(line)) { - return PR_FALSE; - } - line = line->mNext; - } - } - return PR_FALSE; -} -#endif - nsIFrame* nsBlockFrame::GetTopBlockChild() { @@ -3071,6 +3038,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, availWidth, availHeight, impactedByFloaters, PR_FALSE /*XXX isTopOfPage*/); + + // XXX Unfortunately we need to know this before reflowing the first + // inline frame in the line. FIX ME. if ((0 == aLineLayout.GetLineNumber()) && (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) { aLineLayout.SetFirstLetterStyleOK(PR_TRUE); @@ -3287,10 +3257,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, // line and don't stop the line reflow... PRBool splitLine = !reflowingFirstLetter; if (reflowingFirstLetter) { +#ifdef BLOCK_DOES_FIRST_LINE if (aLine->IsFirstLine()) { splitLine = PR_TRUE; } - else { + else +#endif + { nsIAtom* frameType; if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) { if (frameType == nsLayoutAtoms::inlineFrame) { @@ -3391,7 +3364,9 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, aLine->mNext = to; } to->SetIsBlock(aLine->IsBlock()); +#ifdef BLOCK_DOES_FIRST_LINE to->SetIsFirstLine(aLine->IsFirstLine()); +#endif aLine->mChildCount -= pushCount; // Let line layout know that some frames are no longer part of its @@ -3656,20 +3631,6 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, aLine->mMaxElementWidth = aMaxElementSize.width; } -#if XXX_need_line_outside_children - // Compute LINE_OUTSIDE_CHILDREN state for this line. The bit is set - // if any child frame has outside children. - if ((aLine->mCombinedArea.x < aLine->mBounds.x) || - (aLine->mCombinedArea.XMost() > aLine->mBounds.XMost()) || - (aLine->mCombinedArea.y < aLine->mBounds.y) || - (aLine->mCombinedArea.YMost() > aLine->mBounds.YMost())) { - aLine->SetOutsideChildren(); - } - else { - aLine->ClearOutsideChildren(); - } -#endif - // Update xmost nscoord xmost = aLine->mBounds.XMost(); if (xmost > aState.mKidXMost) { @@ -3847,6 +3808,7 @@ nsBlockFrame::LastChild() return nsnull; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) { @@ -3938,6 +3900,7 @@ nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) return rv; } +#endif NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, @@ -3963,12 +3926,14 @@ nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, nsLineBox* lastLine = nsLineBox::LastLine(mLines); if (lastLine) { lastKid = lastLine->LastChild(); +#ifdef BLOCK_DOES_FIRST_LINE if (lastLine->IsFirstLine()) { // Get last frame in the nsFirstLineFrame lastKid->FirstChild(nsnull, &lastKid); nsFrameList frames(lastKid); lastKid = frames.LastChild(); } +#endif } // Add frames after the last child @@ -4058,6 +4023,7 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, nsLineBox* prevSibLine = nsnull; PRInt32 prevSiblingIndex = -1; if (aPrevSibling) { +#ifdef BLOCK_DOES_FIRST_LINE // Its possible we have an nsFirstLineFrame managing some of our // child frames. If we do and the AddFrames is targetted at it, // use AddFirstLineFrames to get the frames properly placed. @@ -4079,7 +4045,9 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, (nsFirstLineFrame*)prevSiblingParent, aFrameList, aPrevSibling); } - else { + else +#endif + { // Find the line that contains the previous sibling prevSibLine = nsLineBox::FindLineContaining(mLines, aPrevSibling, &prevSiblingIndex); @@ -4091,12 +4059,14 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, } } } +#ifdef BLOCK_DOES_FIRST_LINE else if (mLines && mLines->IsFirstLine()) { mLines->MarkDirty(); return AddFirstLineFrames(aPresContext, (nsFirstLineFrame*)mLines->mFirstChild, aFrameList, nsnull); } +#endif // Find the frame following aPrevSibling so that we can join up the // two lists of frames. @@ -4168,20 +4138,22 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, aPrevSibling->SetNextSibling(prevSiblingNextFrame); } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { // We just added one or more frame(s) to the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4310,6 +4282,7 @@ nsBlockFrame::TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, return kids.FirstChild(); } +#endif void nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) @@ -4404,12 +4377,14 @@ nsresult nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, nsIFrame* aDeletedFrame) { +#ifdef BLOCK_DOES_FIRST_LINE nsIFrame* parent; aDeletedFrame->GetParent(&parent); if (parent != this) { return RemoveFirstLineFrame(aPresContext, (nsFirstLineFrame*)parent, aDeletedFrame); } +#endif // Find the line and the previous sibling that contains // deletedFrame; we also find the pointer to the line. @@ -4446,6 +4421,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, while (nsnull != aDeletedFrame) { while ((nsnull != line) && (nsnull != aDeletedFrame)) { #ifdef NS_DEBUG +#ifndef BLOCK_DOES_FIRST_LINE + nsIFrame* parent; +#endif aDeletedFrame->GetParent(&parent); NS_ASSERTION(flow == parent, "messed up delete code"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); @@ -4547,6 +4525,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { @@ -4554,14 +4533,15 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, // removed a block that preceeded the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4596,106 +4576,7 @@ nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, } return NS_OK; } - -static PRBool -IsEmptyLine(nsIPresContext* aPresContext, nsLineBox* aLine) -{ - PRInt32 i, n = aLine->ChildCount(); - nsIFrame* frame = aLine->mFirstChild; - for (i = 0; i < n; i++) { - nsIContent* content; - nsresult rv = frame->GetContent(&content); - if (NS_FAILED(rv) || (nsnull == content)) { - // If it doesn't have any content then this can't be an empty line - return PR_FALSE; - } - nsITextContent* tc; - rv = content->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_FAILED(rv) || (nsnull == tc)) { - // If it's not text content then this can't be an empty line - NS_RELEASE(content); - return PR_FALSE; - } - - const nsTextFragment* frag; - PRInt32 numFrags; - rv = tc->GetText(frag, numFrags); - if (NS_FAILED(rv)) { - NS_RELEASE(content); - NS_RELEASE(tc); - return PR_FALSE; - } - - // If the text has any non-whitespace characters in it then the - // line is not an empty line. - while (--numFrags >= 0) { - PRInt32 len = frag->GetLength(); - if (frag->Is2b()) { - const PRUnichar* cp = frag->Get2b(); - const PRUnichar* end = cp + len; - while (cp < end) { - PRUnichar ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - else { - const char* cp = frag->Get1b(); - const char* end = cp + len; - while (cp < end) { - char ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - frag++; - } - - NS_RELEASE(tc); - NS_RELEASE(content); - frame->GetNextSibling(&frame); - } - return PR_TRUE; -} - -void -nsBlockFrame::MarkEmptyLines(nsIPresContext* aPresContext) -{ - // PRE-formatted content considers whitespace significant - const nsStyleText* text; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) text); - if ((NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == text->mWhiteSpace)) { - return; - } - - PRBool afterBlock = PR_TRUE; - nsLineBox* line = mLines; - while (nsnull != line) { - if (line->IsBlock()) { - afterBlock = PR_TRUE; - } - else if (afterBlock) { - afterBlock = PR_FALSE; - - // This is an inline line and it is immediately after a block - // (or its our first line). See if it contains nothing but - // collapsible text. - PRBool isEmpty = IsEmptyLine(aPresContext, line); - line->SetIsEmptyLine(isEmpty); - } - else { - line->SetIsEmptyLine(PR_FALSE); - } - line = line->mNext; - } -} +#endif void nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, @@ -5609,6 +5490,40 @@ nsBlockFrame::VerifyTree() const return NS_OK; } +NS_IMETHODIMP +nsBlockFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + PRUint32 sum = sizeof(*this); + + // Add in size of each line object + nsLineBox* line = mLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + line = mOverflowLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + + // Add in text-run data + nsTextRun* runs = mTextRuns; + while (runs) { + PRUint32 runSize; + runs->SizeOf(aHandler, &runSize); + sum += runSize; + runs = runs->GetNext(); + } + + *aResult = sum; + return NS_OK; +} + //---------------------------------------------------------------------- NS_IMETHODIMP @@ -5643,6 +5558,7 @@ nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext) return fls; } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) { @@ -5652,6 +5568,7 @@ nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) mStyleContext, PR_FALSE, &fls); return fls; } +#endif NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, @@ -5677,6 +5594,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(firstLetterStyle); } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext); if (nsnull != firstLineStyle) { mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE; @@ -5686,6 +5604,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif NS_RELEASE(firstLineStyle); } +#endif } rv = AddFrames(&aPresContext, aChildList, nsnull); @@ -6238,9 +6157,15 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) if (line->IsBlock()) { seenBlock = PR_TRUE; } - if (line->IsFirstLine() || line->IsBlock()) { +#ifdef BLOCK_DOES_FIRST_LINE + if (line->IsFirstLine()) { NS_ASSERTION(1 == line->mChildCount, "bad first line"); } +#endif + if (line->IsBlock()) { + NS_ASSERTION(1 == line->mChildCount, "bad first line"); + } +#ifdef BLOCK_DOES_FIRST_LINE if (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) { if (seenBlock) { NS_ASSERTION(!line->IsFirstLine(), "bad first line"); @@ -6249,6 +6174,7 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) NS_ASSERTION(line->IsFirstLine(), "bad first line"); } } +#endif } NS_ASSERTION(line->mChildCount < MAX_LINE_COUNT, "bad line child count"); count += line->mChildCount; diff --git a/layout/html/base/src/nsBlockFrame.h b/layout/html/base/src/nsBlockFrame.h index 0f7537724c3..fb85992e2d1 100644 --- a/layout/html/base/src/nsBlockFrame.h +++ b/layout/html/base/src/nsBlockFrame.h @@ -40,7 +40,9 @@ class nsFirstLineFrame; */ #define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x80000000 #define NS_BLOCK_IS_HTML_PARAGRAPH 0x40000000 +#ifdef BLOCK_DOES_FIRST_LINE #define NS_BLOCK_HAS_FIRST_LINE_STYLE 0x20000000 +#endif #define NS_BLOCK_HAS_FIRST_LETTER_STYLE 0x10000000 #define nsBlockFrameSuper nsHTMLContainerFrame @@ -99,6 +101,7 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; NS_IMETHOD VerifyTree() const; NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame); NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, @@ -145,7 +148,9 @@ protected: nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext); +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* GetFirstLineStyle(nsIPresContext* aPresContext); +#endif void SetFlags(PRUint32 aFlags) { mFlags = aFlags; @@ -171,12 +176,11 @@ protected: nsBlockReflowState& aState, nsHTMLReflowMetrics& aMetrics); - void MarkEmptyLines(nsIPresContext* aPresContext); - nsresult AddFrames(nsIPresContext* aPresContext, nsIFrame* aFrameList, nsIFrame* aPrevSibling); +#ifdef BLOCK_DOES_FIRST_LINE nsresult AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, nsIFrame* aFrameList, @@ -185,16 +189,18 @@ protected: nsIFrame* TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, nsIFrame* aFromKid); - void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame); - - nsresult DoRemoveFrame(nsIPresContext* aPresContext, - nsIFrame* aDeletedFrame); - nsresult RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, nsIFrame* aDeletedFrame); nsresult WrapFramesInFirstLineFrame(nsIPresContext* aPresContext); +#endif + + void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame); + + nsresult DoRemoveFrame(nsIPresContext* aPresContext, + nsIFrame* aDeletedFrame); + nsresult PrepareInitialReflow(nsBlockReflowState& aState); diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index d44af8f27d6..2d24571254d 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -45,8 +45,6 @@ #include "nsITextContent.h" #include "nsStyleChangeList.h" -// XXX for IsEmptyLine -#include "nsTextFragment.h" #include "nsIFocusTracker.h" #include "nsIFrameSelection.h" @@ -985,6 +983,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // It is possible that we just acquired first-line style. See if // this is the case, and if so, fix things up. if (0 == (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState)) { @@ -1005,6 +1004,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } } +#endif return rv; } @@ -2185,7 +2185,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState, // Setup the line-layout for the new line aState.mCurrentLine = aLine; aLine->ClearDirty(); - aLine->SetNeedDidReflow(); // Now that we know what kind of line we have, reflow it nsRect oldCombinedArea = aLine->mCombinedArea; @@ -2643,38 +2642,6 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState, return PR_FALSE; } -#if 0 - const nsStyleText* styleText; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText); - if ((NS_STYLE_WHITESPACE_PRE == styleText->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == styleText->mWhiteSpace)) { - // Since whitespace is significant, we know that the paragraph - // is not empty (even if it has no text in it because it has - return PR_FALSE; - -static PRBool -IsEmptyHTMLParagraph(nsIFrame* aFrame) -{ - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf)) && - nsBlockReflowContext::IsHTMLParagraph(aFrame)) { - if (!bf->mLines) { - // It's an html paragraph and it's empty - return PR_TRUE; - } - - nsLineBox* line = bf->mLines; - while (line) { - if (!IsEmptyLine(line)) { - return PR_FALSE; - } - line = line->mNext; - } - } - return PR_FALSE; -} -#endif - nsIFrame* nsBlockFrame::GetTopBlockChild() { @@ -3071,6 +3038,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, availWidth, availHeight, impactedByFloaters, PR_FALSE /*XXX isTopOfPage*/); + + // XXX Unfortunately we need to know this before reflowing the first + // inline frame in the line. FIX ME. if ((0 == aLineLayout.GetLineNumber()) && (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) { aLineLayout.SetFirstLetterStyleOK(PR_TRUE); @@ -3287,10 +3257,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, // line and don't stop the line reflow... PRBool splitLine = !reflowingFirstLetter; if (reflowingFirstLetter) { +#ifdef BLOCK_DOES_FIRST_LINE if (aLine->IsFirstLine()) { splitLine = PR_TRUE; } - else { + else +#endif + { nsIAtom* frameType; if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) { if (frameType == nsLayoutAtoms::inlineFrame) { @@ -3391,7 +3364,9 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, aLine->mNext = to; } to->SetIsBlock(aLine->IsBlock()); +#ifdef BLOCK_DOES_FIRST_LINE to->SetIsFirstLine(aLine->IsFirstLine()); +#endif aLine->mChildCount -= pushCount; // Let line layout know that some frames are no longer part of its @@ -3656,20 +3631,6 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, aLine->mMaxElementWidth = aMaxElementSize.width; } -#if XXX_need_line_outside_children - // Compute LINE_OUTSIDE_CHILDREN state for this line. The bit is set - // if any child frame has outside children. - if ((aLine->mCombinedArea.x < aLine->mBounds.x) || - (aLine->mCombinedArea.XMost() > aLine->mBounds.XMost()) || - (aLine->mCombinedArea.y < aLine->mBounds.y) || - (aLine->mCombinedArea.YMost() > aLine->mBounds.YMost())) { - aLine->SetOutsideChildren(); - } - else { - aLine->ClearOutsideChildren(); - } -#endif - // Update xmost nscoord xmost = aLine->mBounds.XMost(); if (xmost > aState.mKidXMost) { @@ -3847,6 +3808,7 @@ nsBlockFrame::LastChild() return nsnull; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) { @@ -3938,6 +3900,7 @@ nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) return rv; } +#endif NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, @@ -3963,12 +3926,14 @@ nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, nsLineBox* lastLine = nsLineBox::LastLine(mLines); if (lastLine) { lastKid = lastLine->LastChild(); +#ifdef BLOCK_DOES_FIRST_LINE if (lastLine->IsFirstLine()) { // Get last frame in the nsFirstLineFrame lastKid->FirstChild(nsnull, &lastKid); nsFrameList frames(lastKid); lastKid = frames.LastChild(); } +#endif } // Add frames after the last child @@ -4058,6 +4023,7 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, nsLineBox* prevSibLine = nsnull; PRInt32 prevSiblingIndex = -1; if (aPrevSibling) { +#ifdef BLOCK_DOES_FIRST_LINE // Its possible we have an nsFirstLineFrame managing some of our // child frames. If we do and the AddFrames is targetted at it, // use AddFirstLineFrames to get the frames properly placed. @@ -4079,7 +4045,9 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, (nsFirstLineFrame*)prevSiblingParent, aFrameList, aPrevSibling); } - else { + else +#endif + { // Find the line that contains the previous sibling prevSibLine = nsLineBox::FindLineContaining(mLines, aPrevSibling, &prevSiblingIndex); @@ -4091,12 +4059,14 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, } } } +#ifdef BLOCK_DOES_FIRST_LINE else if (mLines && mLines->IsFirstLine()) { mLines->MarkDirty(); return AddFirstLineFrames(aPresContext, (nsFirstLineFrame*)mLines->mFirstChild, aFrameList, nsnull); } +#endif // Find the frame following aPrevSibling so that we can join up the // two lists of frames. @@ -4168,20 +4138,22 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, aPrevSibling->SetNextSibling(prevSiblingNextFrame); } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { // We just added one or more frame(s) to the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4310,6 +4282,7 @@ nsBlockFrame::TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, return kids.FirstChild(); } +#endif void nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) @@ -4404,12 +4377,14 @@ nsresult nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, nsIFrame* aDeletedFrame) { +#ifdef BLOCK_DOES_FIRST_LINE nsIFrame* parent; aDeletedFrame->GetParent(&parent); if (parent != this) { return RemoveFirstLineFrame(aPresContext, (nsFirstLineFrame*)parent, aDeletedFrame); } +#endif // Find the line and the previous sibling that contains // deletedFrame; we also find the pointer to the line. @@ -4446,6 +4421,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, while (nsnull != aDeletedFrame) { while ((nsnull != line) && (nsnull != aDeletedFrame)) { #ifdef NS_DEBUG +#ifndef BLOCK_DOES_FIRST_LINE + nsIFrame* parent; +#endif aDeletedFrame->GetParent(&parent); NS_ASSERTION(flow == parent, "messed up delete code"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); @@ -4547,6 +4525,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { @@ -4554,14 +4533,15 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, // removed a block that preceeded the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4596,106 +4576,7 @@ nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, } return NS_OK; } - -static PRBool -IsEmptyLine(nsIPresContext* aPresContext, nsLineBox* aLine) -{ - PRInt32 i, n = aLine->ChildCount(); - nsIFrame* frame = aLine->mFirstChild; - for (i = 0; i < n; i++) { - nsIContent* content; - nsresult rv = frame->GetContent(&content); - if (NS_FAILED(rv) || (nsnull == content)) { - // If it doesn't have any content then this can't be an empty line - return PR_FALSE; - } - nsITextContent* tc; - rv = content->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_FAILED(rv) || (nsnull == tc)) { - // If it's not text content then this can't be an empty line - NS_RELEASE(content); - return PR_FALSE; - } - - const nsTextFragment* frag; - PRInt32 numFrags; - rv = tc->GetText(frag, numFrags); - if (NS_FAILED(rv)) { - NS_RELEASE(content); - NS_RELEASE(tc); - return PR_FALSE; - } - - // If the text has any non-whitespace characters in it then the - // line is not an empty line. - while (--numFrags >= 0) { - PRInt32 len = frag->GetLength(); - if (frag->Is2b()) { - const PRUnichar* cp = frag->Get2b(); - const PRUnichar* end = cp + len; - while (cp < end) { - PRUnichar ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - else { - const char* cp = frag->Get1b(); - const char* end = cp + len; - while (cp < end) { - char ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - frag++; - } - - NS_RELEASE(tc); - NS_RELEASE(content); - frame->GetNextSibling(&frame); - } - return PR_TRUE; -} - -void -nsBlockFrame::MarkEmptyLines(nsIPresContext* aPresContext) -{ - // PRE-formatted content considers whitespace significant - const nsStyleText* text; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) text); - if ((NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == text->mWhiteSpace)) { - return; - } - - PRBool afterBlock = PR_TRUE; - nsLineBox* line = mLines; - while (nsnull != line) { - if (line->IsBlock()) { - afterBlock = PR_TRUE; - } - else if (afterBlock) { - afterBlock = PR_FALSE; - - // This is an inline line and it is immediately after a block - // (or its our first line). See if it contains nothing but - // collapsible text. - PRBool isEmpty = IsEmptyLine(aPresContext, line); - line->SetIsEmptyLine(isEmpty); - } - else { - line->SetIsEmptyLine(PR_FALSE); - } - line = line->mNext; - } -} +#endif void nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, @@ -5609,6 +5490,40 @@ nsBlockFrame::VerifyTree() const return NS_OK; } +NS_IMETHODIMP +nsBlockFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + PRUint32 sum = sizeof(*this); + + // Add in size of each line object + nsLineBox* line = mLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + line = mOverflowLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + + // Add in text-run data + nsTextRun* runs = mTextRuns; + while (runs) { + PRUint32 runSize; + runs->SizeOf(aHandler, &runSize); + sum += runSize; + runs = runs->GetNext(); + } + + *aResult = sum; + return NS_OK; +} + //---------------------------------------------------------------------- NS_IMETHODIMP @@ -5643,6 +5558,7 @@ nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext) return fls; } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) { @@ -5652,6 +5568,7 @@ nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) mStyleContext, PR_FALSE, &fls); return fls; } +#endif NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, @@ -5677,6 +5594,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(firstLetterStyle); } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext); if (nsnull != firstLineStyle) { mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE; @@ -5686,6 +5604,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif NS_RELEASE(firstLineStyle); } +#endif } rv = AddFrames(&aPresContext, aChildList, nsnull); @@ -6238,9 +6157,15 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) if (line->IsBlock()) { seenBlock = PR_TRUE; } - if (line->IsFirstLine() || line->IsBlock()) { +#ifdef BLOCK_DOES_FIRST_LINE + if (line->IsFirstLine()) { NS_ASSERTION(1 == line->mChildCount, "bad first line"); } +#endif + if (line->IsBlock()) { + NS_ASSERTION(1 == line->mChildCount, "bad first line"); + } +#ifdef BLOCK_DOES_FIRST_LINE if (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) { if (seenBlock) { NS_ASSERTION(!line->IsFirstLine(), "bad first line"); @@ -6249,6 +6174,7 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) NS_ASSERTION(line->IsFirstLine(), "bad first line"); } } +#endif } NS_ASSERTION(line->mChildCount < MAX_LINE_COUNT, "bad line child count"); count += line->mChildCount; diff --git a/layout/html/base/src/nsBlockReflowState.h b/layout/html/base/src/nsBlockReflowState.h index d44af8f27d6..2d24571254d 100644 --- a/layout/html/base/src/nsBlockReflowState.h +++ b/layout/html/base/src/nsBlockReflowState.h @@ -45,8 +45,6 @@ #include "nsITextContent.h" #include "nsStyleChangeList.h" -// XXX for IsEmptyLine -#include "nsTextFragment.h" #include "nsIFocusTracker.h" #include "nsIFrameSelection.h" @@ -985,6 +983,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // It is possible that we just acquired first-line style. See if // this is the case, and if so, fix things up. if (0 == (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState)) { @@ -1005,6 +1004,7 @@ nsBlockFrame::ReResolveStyleContext(nsIPresContext* aPresContext, } } } +#endif return rv; } @@ -2185,7 +2185,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState, // Setup the line-layout for the new line aState.mCurrentLine = aLine; aLine->ClearDirty(); - aLine->SetNeedDidReflow(); // Now that we know what kind of line we have, reflow it nsRect oldCombinedArea = aLine->mCombinedArea; @@ -2643,38 +2642,6 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState, return PR_FALSE; } -#if 0 - const nsStyleText* styleText; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText); - if ((NS_STYLE_WHITESPACE_PRE == styleText->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == styleText->mWhiteSpace)) { - // Since whitespace is significant, we know that the paragraph - // is not empty (even if it has no text in it because it has - return PR_FALSE; - -static PRBool -IsEmptyHTMLParagraph(nsIFrame* aFrame) -{ - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf)) && - nsBlockReflowContext::IsHTMLParagraph(aFrame)) { - if (!bf->mLines) { - // It's an html paragraph and it's empty - return PR_TRUE; - } - - nsLineBox* line = bf->mLines; - while (line) { - if (!IsEmptyLine(line)) { - return PR_FALSE; - } - line = line->mNext; - } - } - return PR_FALSE; -} -#endif - nsIFrame* nsBlockFrame::GetTopBlockChild() { @@ -3071,6 +3038,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, availWidth, availHeight, impactedByFloaters, PR_FALSE /*XXX isTopOfPage*/); + + // XXX Unfortunately we need to know this before reflowing the first + // inline frame in the line. FIX ME. if ((0 == aLineLayout.GetLineNumber()) && (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) { aLineLayout.SetFirstLetterStyleOK(PR_TRUE); @@ -3287,10 +3257,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, // line and don't stop the line reflow... PRBool splitLine = !reflowingFirstLetter; if (reflowingFirstLetter) { +#ifdef BLOCK_DOES_FIRST_LINE if (aLine->IsFirstLine()) { splitLine = PR_TRUE; } - else { + else +#endif + { nsIAtom* frameType; if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) { if (frameType == nsLayoutAtoms::inlineFrame) { @@ -3391,7 +3364,9 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, aLine->mNext = to; } to->SetIsBlock(aLine->IsBlock()); +#ifdef BLOCK_DOES_FIRST_LINE to->SetIsFirstLine(aLine->IsFirstLine()); +#endif aLine->mChildCount -= pushCount; // Let line layout know that some frames are no longer part of its @@ -3656,20 +3631,6 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, aLine->mMaxElementWidth = aMaxElementSize.width; } -#if XXX_need_line_outside_children - // Compute LINE_OUTSIDE_CHILDREN state for this line. The bit is set - // if any child frame has outside children. - if ((aLine->mCombinedArea.x < aLine->mBounds.x) || - (aLine->mCombinedArea.XMost() > aLine->mBounds.XMost()) || - (aLine->mCombinedArea.y < aLine->mBounds.y) || - (aLine->mCombinedArea.YMost() > aLine->mBounds.YMost())) { - aLine->SetOutsideChildren(); - } - else { - aLine->ClearOutsideChildren(); - } -#endif - // Update xmost nscoord xmost = aLine->mBounds.XMost(); if (xmost > aState.mKidXMost) { @@ -3847,6 +3808,7 @@ nsBlockFrame::LastChild() return nsnull; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) { @@ -3938,6 +3900,7 @@ nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext) return rv; } +#endif NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, @@ -3963,12 +3926,14 @@ nsBlockFrame::AppendFrames(nsIPresContext& aPresContext, nsLineBox* lastLine = nsLineBox::LastLine(mLines); if (lastLine) { lastKid = lastLine->LastChild(); +#ifdef BLOCK_DOES_FIRST_LINE if (lastLine->IsFirstLine()) { // Get last frame in the nsFirstLineFrame lastKid->FirstChild(nsnull, &lastKid); nsFrameList frames(lastKid); lastKid = frames.LastChild(); } +#endif } // Add frames after the last child @@ -4058,6 +4023,7 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, nsLineBox* prevSibLine = nsnull; PRInt32 prevSiblingIndex = -1; if (aPrevSibling) { +#ifdef BLOCK_DOES_FIRST_LINE // Its possible we have an nsFirstLineFrame managing some of our // child frames. If we do and the AddFrames is targetted at it, // use AddFirstLineFrames to get the frames properly placed. @@ -4079,7 +4045,9 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, (nsFirstLineFrame*)prevSiblingParent, aFrameList, aPrevSibling); } - else { + else +#endif + { // Find the line that contains the previous sibling prevSibLine = nsLineBox::FindLineContaining(mLines, aPrevSibling, &prevSiblingIndex); @@ -4091,12 +4059,14 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, } } } +#ifdef BLOCK_DOES_FIRST_LINE else if (mLines && mLines->IsFirstLine()) { mLines->MarkDirty(); return AddFirstLineFrames(aPresContext, (nsFirstLineFrame*)mLines->mFirstChild, aFrameList, nsnull); } +#endif // Find the frame following aPrevSibling so that we can join up the // two lists of frames. @@ -4168,20 +4138,22 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext, aPrevSibling->SetNextSibling(prevSiblingNextFrame); } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { // We just added one or more frame(s) to the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::AddFirstLineFrames(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4310,6 +4282,7 @@ nsBlockFrame::TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame, return kids.FirstChild(); } +#endif void nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) @@ -4404,12 +4377,14 @@ nsresult nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, nsIFrame* aDeletedFrame) { +#ifdef BLOCK_DOES_FIRST_LINE nsIFrame* parent; aDeletedFrame->GetParent(&parent); if (parent != this) { return RemoveFirstLineFrame(aPresContext, (nsFirstLineFrame*)parent, aDeletedFrame); } +#endif // Find the line and the previous sibling that contains // deletedFrame; we also find the pointer to the line. @@ -4446,6 +4421,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, while (nsnull != aDeletedFrame) { while ((nsnull != line) && (nsnull != aDeletedFrame)) { #ifdef NS_DEBUG +#ifndef BLOCK_DOES_FIRST_LINE + nsIFrame* parent; +#endif aDeletedFrame->GetParent(&parent); NS_ASSERTION(flow == parent, "messed up delete code"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); @@ -4547,6 +4525,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, } } +#ifdef BLOCK_DOES_FIRST_LINE // Fixup any frames that should be in a first-line frame but aren't if ((NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) && (nsnull != mLines) && !mLines->IsBlock()) { @@ -4554,14 +4533,15 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext, // removed a block that preceeded the first line. WrapFramesInFirstLineFrame(aPresContext); } +#endif #ifdef DEBUG VerifyLines(PR_TRUE); #endif - MarkEmptyLines(aPresContext); return NS_OK; } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, nsFirstLineFrame* aLineFrame, @@ -4596,106 +4576,7 @@ nsBlockFrame::RemoveFirstLineFrame(nsIPresContext* aPresContext, } return NS_OK; } - -static PRBool -IsEmptyLine(nsIPresContext* aPresContext, nsLineBox* aLine) -{ - PRInt32 i, n = aLine->ChildCount(); - nsIFrame* frame = aLine->mFirstChild; - for (i = 0; i < n; i++) { - nsIContent* content; - nsresult rv = frame->GetContent(&content); - if (NS_FAILED(rv) || (nsnull == content)) { - // If it doesn't have any content then this can't be an empty line - return PR_FALSE; - } - nsITextContent* tc; - rv = content->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_FAILED(rv) || (nsnull == tc)) { - // If it's not text content then this can't be an empty line - NS_RELEASE(content); - return PR_FALSE; - } - - const nsTextFragment* frag; - PRInt32 numFrags; - rv = tc->GetText(frag, numFrags); - if (NS_FAILED(rv)) { - NS_RELEASE(content); - NS_RELEASE(tc); - return PR_FALSE; - } - - // If the text has any non-whitespace characters in it then the - // line is not an empty line. - while (--numFrags >= 0) { - PRInt32 len = frag->GetLength(); - if (frag->Is2b()) { - const PRUnichar* cp = frag->Get2b(); - const PRUnichar* end = cp + len; - while (cp < end) { - PRUnichar ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - else { - const char* cp = frag->Get1b(); - const char* end = cp + len; - while (cp < end) { - char ch = *cp++; - if (!XP_IS_SPACE(ch)) { - NS_RELEASE(tc); - NS_RELEASE(content); - return PR_FALSE; - } - } - } - frag++; - } - - NS_RELEASE(tc); - NS_RELEASE(content); - frame->GetNextSibling(&frame); - } - return PR_TRUE; -} - -void -nsBlockFrame::MarkEmptyLines(nsIPresContext* aPresContext) -{ - // PRE-formatted content considers whitespace significant - const nsStyleText* text; - GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) text); - if ((NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) || - (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == text->mWhiteSpace)) { - return; - } - - PRBool afterBlock = PR_TRUE; - nsLineBox* line = mLines; - while (nsnull != line) { - if (line->IsBlock()) { - afterBlock = PR_TRUE; - } - else if (afterBlock) { - afterBlock = PR_FALSE; - - // This is an inline line and it is immediately after a block - // (or its our first line). See if it contains nothing but - // collapsible text. - PRBool isEmpty = IsEmptyLine(aPresContext, line); - line->SetIsEmptyLine(isEmpty); - } - else { - line->SetIsEmptyLine(PR_FALSE); - } - line = line->mNext; - } -} +#endif void nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, @@ -5609,6 +5490,40 @@ nsBlockFrame::VerifyTree() const return NS_OK; } +NS_IMETHODIMP +nsBlockFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + PRUint32 sum = sizeof(*this); + + // Add in size of each line object + nsLineBox* line = mLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + line = mOverflowLines; + while (line) { + sum += sizeof(nsLineBox); + line = line->mNext; + } + + // Add in text-run data + nsTextRun* runs = mTextRuns; + while (runs) { + PRUint32 runSize; + runs->SizeOf(aHandler, &runSize); + sum += runSize; + runs = runs->GetNext(); + } + + *aResult = sum; + return NS_OK; +} + //---------------------------------------------------------------------- NS_IMETHODIMP @@ -5643,6 +5558,7 @@ nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext) return fls; } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) { @@ -5652,6 +5568,7 @@ nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext) mStyleContext, PR_FALSE, &fls); return fls; } +#endif NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, @@ -5677,6 +5594,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(firstLetterStyle); } +#ifdef BLOCK_DOES_FIRST_LINE nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext); if (nsnull != firstLineStyle) { mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE; @@ -5686,6 +5604,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif NS_RELEASE(firstLineStyle); } +#endif } rv = AddFrames(&aPresContext, aChildList, nsnull); @@ -6238,9 +6157,15 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) if (line->IsBlock()) { seenBlock = PR_TRUE; } - if (line->IsFirstLine() || line->IsBlock()) { +#ifdef BLOCK_DOES_FIRST_LINE + if (line->IsFirstLine()) { NS_ASSERTION(1 == line->mChildCount, "bad first line"); } +#endif + if (line->IsBlock()) { + NS_ASSERTION(1 == line->mChildCount, "bad first line"); + } +#ifdef BLOCK_DOES_FIRST_LINE if (NS_BLOCK_HAS_FIRST_LINE_STYLE & mState) { if (seenBlock) { NS_ASSERTION(!line->IsFirstLine(), "bad first line"); @@ -6249,6 +6174,7 @@ nsBlockFrame::VerifyLines(PRBool aFinalCheckOK) NS_ASSERTION(line->IsFirstLine(), "bad first line"); } } +#endif } NS_ASSERTION(line->mChildCount < MAX_LINE_COUNT, "bad line child count"); count += line->mChildCount; diff --git a/layout/html/base/src/nsContainerFrame.cpp b/layout/html/base/src/nsContainerFrame.cpp index 5e84d5bcc41..1c908b57fd5 100644 --- a/layout/html/base/src/nsContainerFrame.cpp +++ b/layout/html/base/src/nsContainerFrame.cpp @@ -667,3 +667,13 @@ nsContainerFrame::List(FILE* out, PRInt32 aIndent) const return NS_OK; } + +NS_IMETHODIMP +nsContainerFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/base/src/nsContainerFrame.h b/layout/html/base/src/nsContainerFrame.h index c4b75ba0374..405e6d7c5ce 100644 --- a/layout/html/base/src/nsContainerFrame.h +++ b/layout/html/base/src/nsContainerFrame.h @@ -50,6 +50,7 @@ public: nsIFrame* aOldFrame, nsIFrame* aNewFrame); NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; // nsIHTMLReflow overrides NS_IMETHOD DidReflow(nsIPresContext& aPresContext, diff --git a/layout/html/base/src/nsFirstLetterFrame.cpp b/layout/html/base/src/nsFirstLetterFrame.cpp index 4c23ab15e0c..603d9b1a016 100644 --- a/layout/html/base/src/nsFirstLetterFrame.cpp +++ b/layout/html/base/src/nsFirstLetterFrame.cpp @@ -205,6 +205,15 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, ll.EndLineReflow(); } else { +// XXX currently the block code sets this up; see comment in +// ReflowInlineFrames +#if XXX + // Only the first-in-flow frame of a first-letter frame gets the + // special first-letter reflow treatment. + if (!mPrevInFlow) { + rs.mLineLayout->SetFirstLetterStyleOK(PR_TRUE); + } +#endif htmlReflow->Reflow(aPresContext, aMetrics, rs, aReflowStatus); } diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index 30ef95ff9ac..0a3ed98f576 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -1586,6 +1586,16 @@ nsFrame::DumpBaseRegressionData(FILE* out, PRInt32 aIndent) } while (nsnull != list); } +NS_IMETHODIMP +nsFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} + NS_IMETHODIMP nsFrame::VerifyTree() const { diff --git a/layout/html/base/src/nsFrame.h b/layout/html/base/src/nsFrame.h index 312b2fcc371..b6e54383358 100644 --- a/layout/html/base/src/nsFrame.h +++ b/layout/html/base/src/nsFrame.h @@ -223,6 +223,7 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD DumpRegressionData(FILE* out, PRInt32 aIndent); + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; NS_IMETHOD VerifyTree() const; NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, nsSpread aSpread); NS_IMETHOD GetSelected(PRBool *aSelected) const; diff --git a/layout/html/base/src/nsHRFrame.cpp b/layout/html/base/src/nsHRFrame.cpp index 40359424638..dcf693d83f7 100644 --- a/layout/html/base/src/nsHRFrame.cpp +++ b/layout/html/base/src/nsHRFrame.cpp @@ -33,6 +33,7 @@ #include "nsIDOMHTMLHRElement.h" #include "nsIDeviceContext.h" #include "nsStyleUtil.h" +#include "nsLayoutAtoms.h" static NS_DEFINE_IID(kIDOMHTMLHRElementIID, NS_IDOMHTMLHRELEMENT_IID); @@ -51,6 +52,8 @@ public: nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); + NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: PRBool GetNoShade(); @@ -253,3 +256,22 @@ HRuleFrame::GetNoShade() } return result; } + +NS_IMETHODIMP +HRuleFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = nsLayoutAtoms::hrFrame; + NS_ADDREF(*aType); + return NS_OK; +} + +NS_IMETHODIMP +HRuleFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/html/base/src/nsHTMLFrame.cpp b/layout/html/base/src/nsHTMLFrame.cpp index 7319ef12a4d..a728d62066e 100644 --- a/layout/html/base/src/nsHTMLFrame.cpp +++ b/layout/html/base/src/nsHTMLFrame.cpp @@ -89,6 +89,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; // XXX Temporary hack... NS_IMETHOD SetRect(const nsRect& aRect); @@ -450,3 +451,13 @@ RootFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Root", aResult); } + +NS_IMETHODIMP +RootFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/html/base/src/nsHTMLImageLoader.cpp b/layout/html/base/src/nsHTMLImageLoader.cpp index 92e37351faf..24ea30cf336 100644 --- a/layout/html/base/src/nsHTMLImageLoader.cpp +++ b/layout/html/base/src/nsHTMLImageLoader.cpp @@ -372,3 +372,17 @@ nsHTMLImageLoader::GetLoadStatus() const } return loadStatus; } + +// Note: this doesn't factor in: +// -- the mBaseURL (it might be shared) +// -- the mFrame (that will be counted elsewhere most likely) +// -- the mClosure (we don't know what type it is) +// -- the mImageLoader (it might be shared) +PRUint32 +nsHTMLImageLoader::GetDataSize() const +{ + PRUint32 sum = sizeof(*this); + sum += sizeof(PRUnichar) * mURLSpec.Length() + + sizeof(PRUnichar) * mURL.Length(); + return sum; +} diff --git a/layout/html/base/src/nsHTMLImageLoader.h b/layout/html/base/src/nsHTMLImageLoader.h index 109e831c1eb..3bfffbe212e 100644 --- a/layout/html/base/src/nsHTMLImageLoader.h +++ b/layout/html/base/src/nsHTMLImageLoader.h @@ -82,6 +82,8 @@ public: return mFlags.mHaveComputedSize; } + PRUint32 GetDataSize() const; + protected: static nsresult ImageLoadCB(nsIPresContext* aPresContext, nsIFrameImageLoader* aLoader, diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index 62230561b52..cb6136deb7f 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -55,6 +55,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsTextFragment.h" #include "nsIDOMHTMLMapElement.h" #include "nsIStyleSet.h" +#include "nsLayoutAtoms.h" #ifdef DEBUG #undef NOISY_IMAGE_LOADING @@ -859,3 +860,26 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext, return NS_OK; } + +NS_IMETHODIMP +nsImageFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = nsLayoutAtoms::imageFrame; + NS_ADDREF(*aType); + return NS_OK; +} + +// Note: this doesn't factor in: +// -- the mImageMap (it might be shared) +NS_IMETHODIMP +nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + PRUint32 sum = sizeof(*this) - sizeof(mImageLoader) + + mImageLoader.GetDataSize(); + *aResult = sum; + return NS_OK; +} diff --git a/layout/html/base/src/nsImageFrame.h b/layout/html/base/src/nsImageFrame.h index 104187f5e72..ccd6cd67bbf 100644 --- a/layout/html/base/src/nsImageFrame.h +++ b/layout/html/base/src/nsImageFrame.h @@ -59,6 +59,8 @@ public: nsIContent* aChild, nsIAtom* aAttribute, PRInt32 aHint); + NS_IMETHOD GetFrameType(nsIAtom** aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: virtual ~nsImageFrame(); diff --git a/layout/html/base/src/nsImageMap.cpp b/layout/html/base/src/nsImageMap.cpp index a6255be67cc..04fc9b75ccb 100644 --- a/layout/html/base/src/nsImageMap.cpp +++ b/layout/html/base/src/nsImageMap.cpp @@ -78,7 +78,7 @@ public: const nsString& GetAltText() const { return mAltText; } PRBool GetSuppress() const { return mSuppressFeedback; } - virtual void SizeOf(nsISizeOfHandler* aHandler) const; + virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; nsString mBase; nsString mHREF; @@ -106,15 +106,18 @@ Area::~Area() } void -Area::SizeOf(nsISizeOfHandler* aHandler) const +Area::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const { - aHandler->Add(sizeof(*this)); - aHandler->Add((size_t) (- ((PRInt32)sizeof(nsString) * 4) ) ); - mBase.SizeOf(aHandler); - mHREF.SizeOf(aHandler); - mTarget.SizeOf(aHandler); - mAltText.SizeOf(aHandler); - aHandler->Add(mNumCoords * sizeof(nscoord)); + if (aResult) { + PRUint32 sum = sizeof(*this); + PRUint32 s; + mBase.SizeOf(aHandler, &s); sum += s; + mHREF.SizeOf(aHandler, &s); sum += s; + mTarget.SizeOf(aHandler, &s); sum += s; + mAltText.SizeOf(aHandler, &s); sum += s; + sum += mNumCoords * sizeof(nscoord); + *aResult = sum; + } } #include @@ -1132,3 +1135,19 @@ nsImageMap::DocumentWillBeDestroyed(nsIDocument *aDocument) { return NS_OK; } + +void +nsImageMap::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + PRInt32 i, n = mAreas.Count(); + for (i = 0; i < n; i++) { + Area* area = (Area*) mAreas.ElementAt(i); + PRUint32 areaSize; + area->SizeOf(aHandler, &areaSize); + sum += areaSize; + } + *aResult = sum; + } +} diff --git a/layout/html/base/src/nsImageMap.h b/layout/html/base/src/nsImageMap.h index ccf2f690a1a..e0a5f7067ff 100644 --- a/layout/html/base/src/nsImageMap.h +++ b/layout/html/base/src/nsImageMap.h @@ -62,6 +62,8 @@ public: void Draw(nsIPresContext& aCX, nsIRenderingContext& aRC); + void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; + // nsISupports NS_DECL_ISUPPORTS diff --git a/layout/html/base/src/nsInlineFrame.cpp b/layout/html/base/src/nsInlineFrame.cpp index 62fc70926e5..1c2b643647e 100644 --- a/layout/html/base/src/nsInlineFrame.cpp +++ b/layout/html/base/src/nsInlineFrame.cpp @@ -1240,6 +1240,20 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext, } DrainOverflow(&aPresContext); + if (IsFrameTreeTooDeep(aReflowState, aMetrics)) { +#ifdef DEBUG_kipp + { + extern char* nsPresShell_ReflowStackPointerTop; + char marker; + char* newsp = (char*) ▮ + printf("XXX: frame tree is too deep; approx stack size = %d\n", + nsPresShell_ReflowStackPointerTop - newsp); + } +#endif + aStatus = NS_FRAME_COMPLETE; + return NS_OK; + } + // Set our own reflow state (additional state above and beyond // aReflowState) InlineReflowState irs; @@ -1472,6 +1486,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, aMetrics.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; +#ifdef DEBUG_kipp // Note: we use the actual font height for sizing our selves // instead of the computed font height. On systems where they // disagree the actual font height is more appropriate. This @@ -1484,6 +1499,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, if (getenv("GECKO_USE_COMPUTED_HEIGHT")) { useComputedHeight = PR_TRUE; } + firstTime = 0; } #endif if (useComputedHeight) { @@ -1505,6 +1521,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, aMetrics.height = computedHeight; } } +#endif /* DEBUG_kipp */ NS_RELEASE(fm); } @@ -1892,8 +1909,16 @@ nsFirstLineFrame::AppendFrames(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { +#ifdef BLOCK_DOES_FIRST_LINE return mParent->AppendFrames(aPresContext, aPresShell, aListName, aFrameList); +#else + nsresult rv = nsInlineFrame::AppendFrames(aPresContext, aPresShell, + aListName, aFrameList); +// nsFrameList frames(aFrameList); +// ReResolveChildList(&aPresContext, mStyleContext, frames); + return rv; +#endif } NS_IMETHODIMP @@ -1903,8 +1928,16 @@ nsFirstLineFrame::InsertFrames(nsIPresContext& aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { +#ifdef BLOCK_DOES_FIRST_LINE return mParent->InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); +#else + nsresult rv = nsInlineFrame::InsertFrames(aPresContext, aPresShell, + aListName, aPrevFrame, aFrameList); +// nsFrameList frames(aFrameList); +// ReResolveChildList(&aPresContext, mStyleContext, frames); + return rv; +#endif } NS_IMETHODIMP @@ -1913,10 +1946,17 @@ nsFirstLineFrame::RemoveFrame(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { +#ifdef BLOCK_DOES_FIRST_LINE return mParent->RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); +#else + nsresult rv = nsInlineFrame::RemoveFrame(aPresContext, aPresShell, + aListName, aOldFrame); + return rv; +#endif } +#ifdef BLOCK_DOES_FIRST_LINE nsresult nsFirstLineFrame::AppendFrames2(nsIPresContext* aPresContext, nsIFrame* aFrameList) @@ -1952,9 +1992,10 @@ nsFirstLineFrame::RemoveFrame2(nsIPresContext* aPresContext, mFrames.RemoveFrame(aOldFrame); return NS_OK; } +#endif void -nsFirstLineFrame::RemoveFramesFrom(nsIFrame* aFrame) +nsFirstLineFrame::StealFramesFrom(nsIFrame* aFrame) { nsIFrame* prevFrame = mFrames.GetPrevSiblingFor(aFrame); if (prevFrame) { @@ -2138,3 +2179,14 @@ nsFirstLineFrame::Reflow(nsIPresContext& aPresContext, return rv; } + +NS_IMETHODIMP +nsPositionedInlineFrame::SizeOf(nsISizeOfHandler* aHandler, + PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/base/src/nsInlineFrame.h b/layout/html/base/src/nsInlineFrame.h index 77606af3e85..5a0fc328628 100644 --- a/layout/html/base/src/nsInlineFrame.h +++ b/layout/html/base/src/nsInlineFrame.h @@ -192,8 +192,10 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); +#ifdef BLOCK_DOES_FIRST_LINE // AppendFrames/InsertFrames/RemoveFrame are implemented to forward // the method call to the parent frame. +#endif NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -208,6 +210,7 @@ public: nsIAtom* aListName, nsIFrame* aOldFrame); +#ifdef BLOCK_DOES_FIRST_LINE // These methods are used by the parent frame to actually modify the // child frames of the line frame. These methods do not generate // reflow commands. @@ -221,9 +224,14 @@ public: nsresult RemoveFrame2(nsIPresContext* aPresContext, nsIFrame* aOldFrame); - void RemoveFramesFrom(nsIFrame* aFrame); +#endif + // Take frames starting at aFrame until the end of the frame-list + // away from this frame. The caller is presumed to keep them alive. + void StealFramesFrom(nsIFrame* aFrame); - void RemoveAllFrames() { + // Take all of the frames away from this frame. The caller is + // presumed to keep them alive. + void StealAllFrames() { mFrames.SetFrames(nsnull); } @@ -250,6 +258,7 @@ class nsPositionedInlineFrame : public nsInlineFrame { public: NS_IMETHOD Destroy(nsIPresContext& aPresContext); + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, diff --git a/layout/html/base/src/nsLeafFrame.cpp b/layout/html/base/src/nsLeafFrame.cpp index 7687aa5b95c..3f6475c2ad3 100644 --- a/layout/html/base/src/nsLeafFrame.cpp +++ b/layout/html/base/src/nsLeafFrame.cpp @@ -126,3 +126,13 @@ nsLeafFrame::ContentChanged(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsLeafFrame::SizeOf(nsISizeOfHandler* aHandler, + PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/base/src/nsLeafFrame.h b/layout/html/base/src/nsLeafFrame.h index 4a85a84e1c0..4c8ddc599bf 100644 --- a/layout/html/base/src/nsLeafFrame.h +++ b/layout/html/base/src/nsLeafFrame.h @@ -41,6 +41,7 @@ public: NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent); + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: virtual ~nsLeafFrame(); diff --git a/layout/html/base/src/nsLineBox.cpp b/layout/html/base/src/nsLineBox.cpp index fad3604abfb..1604722d6cb 100644 --- a/layout/html/base/src/nsLineBox.cpp +++ b/layout/html/base/src/nsLineBox.cpp @@ -26,7 +26,7 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags) { mFirstChild = aFrame; mChildCount = aCount; - mState = LINE_IS_DIRTY | LINE_NEED_DID_REFLOW | flags; + mState = LINE_IS_DIRTY | flags; mFloaters = nsnull; mNext = nsnull; mBounds.SetRect(0,0,0,0); diff --git a/layout/html/base/src/nsLineBox.h b/layout/html/base/src/nsLineBox.h index fe54792565b..9961bd6fae8 100644 --- a/layout/html/base/src/nsLineBox.h +++ b/layout/html/base/src/nsLineBox.h @@ -23,16 +23,13 @@ #include "nsPlaceholderFrame.h" #include "nsILineIterator.h" -// bits in nsLineBox.mFlags +// bits in nsLineBox.mState #define LINE_IS_DIRTY 0x1 #define LINE_IS_BLOCK 0x2 -#define LINE_WAS_DIRTY 0x4 -#define LINE_NEED_DID_REFLOW 0x8 -#define LINE_TOP_MARGIN_IS_AUTO 0x10 -#define LINE_BOTTOM_MARGIN_IS_AUTO 0x20 -#define LINE_OUTSIDE_CHILDREN 0x40 -#define LINE_ISA_EMPTY_LINE 0x80 -#define LINE_IS_FIRST_LINE 0x100 +#ifdef BLOCK_DOES_FIRST_LINE +#define LINE_IS_FIRST_LINE 0x4 +#endif +#define LINE_WAS_DIRTY 0x8 class nsISpaceManager; class nsLineBox; @@ -51,17 +48,6 @@ public: nscoord GetHeight() const { return mBounds.height; } - PRBool IsEmptyLine() const { - return 0 != (mState & LINE_ISA_EMPTY_LINE); - } - - void SetIsEmptyLine(PRBool aSetting) { - if (aSetting) - mState |= aSetting; - else - mState &= ~aSetting; - } - //---------------------------------------------------------------------- // XXX old junk nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags); @@ -106,6 +92,7 @@ public: } } +#ifdef BLOCK_DOES_FIRST_LINE PRBool IsFirstLine() const { return 0 != (LINE_IS_FIRST_LINE & mState); } @@ -118,6 +105,7 @@ public: mState &= ~LINE_IS_FIRST_LINE; } } +#endif void MarkDirty() { mState |= LINE_IS_DIRTY; @@ -143,34 +131,6 @@ public: return 0 != (LINE_WAS_DIRTY & mState); } - void SetNeedDidReflow() { - mState |= LINE_NEED_DID_REFLOW; - } - - void ClearNeedDidReflow() { - mState &= ~LINE_NEED_DID_REFLOW; - } - - PRBool NeedsDidReflow() { - return 0 != (LINE_NEED_DID_REFLOW & mState); - } - -#ifdef XXX_need_line_outside_children - void SetOutsideChildren() { - mState |= LINE_OUTSIDE_CHILDREN; - } - - void ClearOutsideChildren() { - mState &= ~LINE_OUTSIDE_CHILDREN; - } - - PRBool OutsideChildren() const { - return 0 != (LINE_OUTSIDE_CHILDREN & mState); - } -#endif - - PRUint16 GetState() const { return mState; } - char* StateToString(char* aBuf, PRInt32 aBufSize) const; PRInt32 IndexOf(nsIFrame* aFrame) const; @@ -185,7 +145,7 @@ public: nsIFrame* mFirstChild; PRUint16 mChildCount; - PRUint16 mState; + PRUint8 mState; PRUint8 mBreakType; nsRect mBounds; nsRect mCombinedArea; diff --git a/layout/html/base/src/nsLineLayout.cpp b/layout/html/base/src/nsLineLayout.cpp index 4c6825d2bd1..78746b215d5 100644 --- a/layout/html/base/src/nsLineLayout.cpp +++ b/layout/html/base/src/nsLineLayout.cpp @@ -806,7 +806,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // the state out. We need to know how to treat the current frame // when breaking. PRBool notSafeToBreak = CanPlaceFloaterNow() || InWord(); -//XXX PRBool firstLetterOK = mFirstLetterStyleOK; // Apply left margins (as appropriate) to the frame computing the // new starting x,y coordinates for the frame. @@ -979,8 +978,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, parent->DeleteChildsNextInFlow(mPresContext, aFrame); } } -//XXX if (firstLetterOK && !mFirstLetterStyleOK) { -//XXX } // See if we can place the frame. If we can't fit it, then we // return now. diff --git a/layout/html/base/src/nsPlaceholderFrame.cpp b/layout/html/base/src/nsPlaceholderFrame.cpp index 2d21c6a4775..f9caa7007ce 100644 --- a/layout/html/base/src/nsPlaceholderFrame.cpp +++ b/layout/html/base/src/nsPlaceholderFrame.cpp @@ -113,3 +113,13 @@ nsPlaceholderFrame::List(FILE* out, PRInt32 aIndent) const fputs("\n", out); return NS_OK; } + +NS_IMETHODIMP +nsPlaceholderFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/html/base/src/nsPlaceholderFrame.h b/layout/html/base/src/nsPlaceholderFrame.h index 51dbc522786..55cb6684f1e 100644 --- a/layout/html/base/src/nsPlaceholderFrame.h +++ b/layout/html/base/src/nsPlaceholderFrame.h @@ -56,6 +56,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: nsIFrame* mOutOfFlowFrame; diff --git a/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index 16ce7a0c509..6aa1917a77c 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/layout/html/base/src/nsScrollFrame.cpp @@ -761,3 +761,13 @@ nsScrollFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Scroll", aResult); } + +NS_IMETHODIMP +nsScrollFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/html/base/src/nsScrollFrame.h b/layout/html/base/src/nsScrollFrame.h index efe1fb80ed7..06862a1bee1 100644 --- a/layout/html/base/src/nsScrollFrame.h +++ b/layout/html/base/src/nsScrollFrame.h @@ -86,6 +86,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: nsScrollFrame(); diff --git a/layout/html/base/src/nsSplittableFrame.cpp b/layout/html/base/src/nsSplittableFrame.cpp index 3009b46007e..1f8214b7b6f 100644 --- a/layout/html/base/src/nsSplittableFrame.cpp +++ b/layout/html/base/src/nsSplittableFrame.cpp @@ -193,4 +193,15 @@ nsSplittableFrame::DumpBaseRegressionData(FILE* out, PRInt32 aIndent) IndentBy(out, aIndent); fprintf(out, "\n", PRUptrdiff(mPrevInFlow)); } + +} + +NS_IMETHODIMP +nsSplittableFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + *aResult = sizeof(*this); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; } diff --git a/layout/html/base/src/nsSplittableFrame.h b/layout/html/base/src/nsSplittableFrame.h index 5d7d3d59215..1d0b890af38 100644 --- a/layout/html/base/src/nsSplittableFrame.h +++ b/layout/html/base/src/nsSplittableFrame.h @@ -31,6 +31,7 @@ public: nsIFrame* aPrevInFlow); NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; // Flow member functions. NS_IMETHOD GetPrevInFlow(nsIFrame** aPrevInFlow) const; diff --git a/layout/html/base/src/nsTextFrame.cpp b/layout/html/base/src/nsTextFrame.cpp index 4072151bb73..f79d9b3495c 100644 --- a/layout/html/base/src/nsTextFrame.cpp +++ b/layout/html/base/src/nsTextFrame.cpp @@ -227,6 +227,8 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; + NS_IMETHOD GetPosition(nsIPresContext& aCX, nscoord aXCoord, nsIContent ** aNewContent, @@ -3072,6 +3074,16 @@ nsTextFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } +NS_IMETHODIMP +nsTextFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} + NS_IMETHODIMP nsTextFrame::GetFrameName(nsString& aResult) const { diff --git a/layout/html/base/src/nsTextRun.h b/layout/html/base/src/nsTextRun.h index b8791fa1048..ec07073ed2f 100644 --- a/layout/html/base/src/nsTextRun.h +++ b/layout/html/base/src/nsTextRun.h @@ -50,6 +50,13 @@ public: return mArray.Count(); } + void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const { + if (aResult) { + mArray.SizeOf(aHandler, aResult); + *aResult += sizeof(this) - sizeof(mArray); + } + } + nsIFrame* operator[](PRInt32 aIndex) const { return (nsIFrame*) mArray[aIndex]; } diff --git a/layout/html/base/src/nsViewportFrame.cpp b/layout/html/base/src/nsViewportFrame.cpp index 5ad0c71f099..2eeefbf7788 100644 --- a/layout/html/base/src/nsViewportFrame.cpp +++ b/layout/html/base/src/nsViewportFrame.cpp @@ -83,6 +83,7 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; protected: nsresult IncrementalReflow(nsIPresContext& aPresContext, @@ -571,3 +572,13 @@ ViewportFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("Viewport", aResult); } + +NS_IMETHODIMP +ViewportFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index fdafb8f9776..34edd1edd2f 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -67,6 +67,9 @@ #include "nsIFrameManager.h" #include "nsIAttributeContent.h" +#include "nsInlineFrame.h" +#undef NOISY_FIRST_LETTER + #ifdef INCLUDE_XUL #include "nsXULAtoms.h" #include "nsTreeFrame.h" @@ -82,8 +85,6 @@ #include "nsDocument.h" #include "nsToolbarItemFrame.h" -#undef NOISY_FIRST_LETTER - #define IS_GFX nsresult @@ -169,26 +170,6 @@ static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); // ----------------------------------------------------------- -// Predicate to see if a given content (block element) has -// first-letter style applied to it. -static PRBool HaveFirstLetterStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aStyleContext) -{ - nsCOMPtr fls; - aPresContext->ProbePseudoStyleContextFor(aContent, - nsHTMLAtoms::firstLetterPseudo, - aStyleContext, PR_FALSE, - getter_AddRefs(fls)); - PRBool result = PR_FALSE; - if (fls) { - result = PR_TRUE; - } - return result; -} - -// ----------------------------------------------------------- - // Structure used when constructing formatting object trees. struct nsFrameItems { nsIFrame* childList; @@ -261,9 +242,11 @@ public: private: nsAbsoluteItems* mItems; // pointer to struct whose data we save/restore PRBool* mFirstLetterStyle; + PRBool* mFirstLineStyle; nsAbsoluteItems mSavedItems; // copy of original data PRBool mSavedFirstLetterStyle; + PRBool mSavedFirstLineStyle; friend class nsFrameConstructorState; }; @@ -280,6 +263,7 @@ public: nsAbsoluteItems mAbsoluteItems; nsAbsoluteItems mFloatedItems; PRBool mFirstLetterStyle; + PRBool mFirstLineStyle; // Constructor nsFrameConstructorState(nsIPresContext* aPresContext, @@ -296,7 +280,8 @@ public: // create a new scope void PushFloaterContainingBlock(nsIFrame* aNewFloaterContainingBlock, nsFrameConstructorSaveState& aSaveState, - PRBool aFirstLetterStyle); + PRBool aFirstLetterStyle, + PRBool aFirstLineStyle); }; nsFrameConstructorState::nsFrameConstructorState(nsIPresContext* aPresContext, @@ -324,18 +309,21 @@ nsFrameConstructorState::PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteConta void nsFrameConstructorState::PushFloaterContainingBlock(nsIFrame* aNewFloaterContainingBlock, nsFrameConstructorSaveState& aSaveState, - PRBool aFirstLetterStyle) + PRBool aFirstLetterStyle, + PRBool aFirstLineStyle) { aSaveState.mItems = &mFloatedItems; aSaveState.mFirstLetterStyle = &mFirstLetterStyle; aSaveState.mSavedItems = mFloatedItems; aSaveState.mSavedFirstLetterStyle = mFirstLetterStyle; + aSaveState.mSavedFirstLineStyle = mFirstLineStyle; mFloatedItems = nsAbsoluteItems(aNewFloaterContainingBlock); mFirstLetterStyle = aFirstLetterStyle; + mFirstLineStyle = aFirstLineStyle; } nsFrameConstructorSaveState::nsFrameConstructorSaveState() - : mItems(nsnull), mFirstLetterStyle(nsnull) + : mItems(nsnull), mFirstLetterStyle(nsnull), mFirstLineStyle(nsnull) { } @@ -348,6 +336,9 @@ nsFrameConstructorSaveState::~nsFrameConstructorSaveState() if (mFirstLetterStyle) { *mFirstLetterStyle = mSavedFirstLetterStyle; } + if (mFirstLineStyle) { + *mFirstLineStyle = mSavedFirstLineStyle; + } } // ----------------------------------------------------------- @@ -834,6 +825,7 @@ IsEmptyTextContent(nsIContent* aContent) return result; } +#if 0 #include "nsIDOMHTMLParagraphElement.h" static PRBool @@ -848,7 +840,7 @@ IsHTMLParagraph(nsIContent* aContent) } static PRBool -IsEmptyContent(nsIContent* aContainer) +IsEmptyContainer(nsIContent* aContainer) { // Check each kid and if each kid is empty text content (or there // are no kids) then return true. @@ -873,8 +865,9 @@ IsEmptyHTMLParagraph(nsIContent* aContent) // It's not an HTML paragraph so return false return PR_FALSE; } - return IsEmptyContent(aContent); + return IsEmptyContainer(aContent); } +#endif nsresult nsCSSFrameConstructor::CreateInputFrame(nsIPresContext *aPresContext, @@ -1261,10 +1254,13 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresContext* aPres } // The caption frame is a floater container - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); nsFrameConstructorSaveState floaterSaveState; aState.PushFloaterContainingBlock(aNewCaptionFrame, floaterSaveState, - haveFLS); + haveFirstLetterStyle, + haveFirstLineStyle); // Process the child content nsFrameItems childItems; @@ -1709,13 +1705,15 @@ nsCSSFrameConstructor::ConstructTableCellFrameOnly(nsIPresContext* aPre bodyPseudoStyle, nsnull); if (aProcessChildren) { - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, - aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); // The area frame is a floater container nsFrameConstructorSaveState floaterSaveState; aState.PushFloaterContainingBlock(aNewCellBodyFrame, floaterSaveState, - haveFLS); + haveFirstLetterStyle, + haveFirstLineStyle); // Process the child content nsFrameItems childItems; @@ -2085,10 +2083,13 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresContext* aPresCo nsFrameConstructorSaveState floaterSaveState; nsFrameItems childItems; - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aDocElement, - styleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aDocElement, styleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState); - aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aDocElement, areaFrame, PR_TRUE, childItems, isBlockFrame); @@ -2204,10 +2205,13 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresContext* aPresCo nsFrameItems childItems; // XXX these next lines are wrong for BoxFrame - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aDocElement, - styleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aDocElement, styleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState); - aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aDocElement, areaFrame, PR_TRUE, childItems, isBlockFrame); @@ -2986,14 +2990,13 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex const PRInt32 kNoSizeSpecified = -1; if (eWidgetRendering_Gfx == mode) { - // Construct a frame-based listbox or combobox - nsIDOMHTMLSelectElement* select = nsnull; + // Construct a frame-based listbox or combobox + nsCOMPtr sel(do_QueryInterface(aContent)); PRInt32 size = 1; - nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); - if (NS_SUCCEEDED(result)) { - select->GetSize(&size); + if (sel) { + sel->GetSize(&size); PRBool multipleSelect = PR_FALSE; - select->GetMultiple(&multipleSelect); + sel->GetMultiple(&multipleSelect); // Construct a combobox if size=1 or no size is specified and its multiple select if (((1 == size) || (kNoSizeSpecified == size)) && (PR_FALSE == multipleSelect)) { // Construct a frame-based combo box. @@ -3100,7 +3103,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); aFrameHasBeenInitialized = PR_TRUE; } - NS_RELEASE(select); } else { rv = NS_NewNativeSelectControlFrame(&aNewFrame); } @@ -4179,11 +4181,13 @@ nsCSSFrameConstructor::InitializeScrollFrame(nsIPresContext* aPresConte if (aProcessChildren) { // The area frame is a floater container - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, - aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); nsFrameConstructorSaveState floaterSaveState; aState.PushFloaterContainingBlock(scrolledFrame, floaterSaveState, - haveFLS); + haveFirstLetterStyle, + haveFirstLineStyle); // Process children nsFrameConstructorSaveState absoluteSaveState; @@ -4326,11 +4330,15 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPre nsFrameConstructorSaveState floaterSaveState; nsFrameItems childItems; - PRBool haveFLS = aDisplay->IsBlockLevel() - ? HaveFirstLetterStyle(aPresContext, aContent, aStyleContext) - : PR_FALSE; + PRBool haveFirstLetterStyle = PR_FALSE, haveFirstLineStyle = PR_FALSE; + if (aDisplay->IsBlockLevel()) { + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + } aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState); - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aContent, newFrame, PR_TRUE, childItems, PR_TRUE); @@ -4366,10 +4374,14 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPre nsFrameConstructorSaveState floaterSaveState; nsFrameItems childItems; - PRBool haveFLS = aDisplay->IsBlockLevel() - ? HaveFirstLetterStyle(aPresContext, aContent, aStyleContext) - : PR_FALSE; - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, haveFLS); + PRBool haveFirstLetterStyle = PR_FALSE, haveFirstLineStyle = PR_FALSE; + if (aDisplay->IsBlockLevel()) { + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + } + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); ProcessChildren(aPresContext, aState, aContent, newFrame, PR_TRUE, childItems, PR_TRUE); @@ -4414,9 +4426,12 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPre aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState); if (isBlockFrame) { - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, - aStyleContext); - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, haveFLS); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); } ProcessChildren(aPresContext, aState, aContent, newFrame, PR_TRUE, childItems, isBlockFrame); @@ -4600,12 +4615,16 @@ nsCSSFrameConstructor::ConstructBlock(nsIPresContext* aPresContext, aStyleContext, PR_FALSE); // See if the block has first-letter style applied to it... - PRBool haveFLS = HaveFirstLetterStyle(aPresContext, aContent, aStyleContext); + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); // Process the child content nsFrameItems childItems; nsFrameConstructorSaveState floaterSaveState; - aState.PushFloaterContainingBlock(aNewFrame, floaterSaveState, haveFLS); + aState.PushFloaterContainingBlock(aNewFrame, floaterSaveState, + haveFirstLetterStyle, + haveFirstLineStyle); nsresult rv = ProcessChildren(aPresContext, aState, aContent, aNewFrame, PR_TRUE, childItems, PR_TRUE); @@ -5111,6 +5130,67 @@ ContentIsLogicalFirstChild(nsIContent* aContent, nsIContent* aContainingBlock) return PR_FALSE; } +nsresult +nsCSSFrameConstructor::MaybeCreateContainerFrame(nsIPresContext* aPresContext, + nsIContent* aContainer) +{ + nsresult rv = NS_OK; +#if 0 + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + + // See if aContainer's parent has a frame... + nsCOMPtr containerParent; + aContainer->GetParent(*getter_AddRefs(containerParent)); + if (containerParent) { + nsIFrame* parentFrame = GetFrameFor(shell, aPresContext, containerParent); + if (parentFrame) { + // aContainer's parent has a frame. Maybe aContainer needs a + // frame now? If it's display none, then it doesn't. + nsCOMPtr parentStyleContext; + parentFrame->GetStyleContext(getter_AddRefs(parentStyleContext)); + nsCOMPtr styleContext; + aPresContext->ResolveStyleContextFor(aContainer, parentStyleContext, + PR_FALSE, + getter_AddRefs(styleContext)); + const nsStyleDisplay* display = (const nsStyleDisplay*) + styleContext->GetStyleData(eStyleStruct_Display); + if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { + // aContainer's display is not none and it has a parent + // frame. Now we see if it needs a frame after new content + // was appended. + if (IsHTMLParagraph(aContainer)) { + if (!IsEmptyContainer(aContainer)) { + // It's an HTML paragraph (P) and it has some + // content. Because of the previous checks we now know + // that the P used to have nothing but empty content and + // therefore had no frame created. This condition is no + // longer true so we create a frame for aContainer (and + // its children) and insert them into the tree... + PRInt32 ix; + containerParent->IndexOf(aContainer, ix); + if (ix >= 0) { +#ifdef DEBUG_kipp + printf("Recreating frame for HTML:P\n"); +#endif + ContentInserted(aPresContext, containerParent, aContainer, ix); + } + } + } + } + } + else { + // If aContainer's parent has no frame then there is no need + // in trying to create a frame for aContainer. + } + } + else { + // aContainer has no parent. Odd. + } +#endif + return rv; +} + NS_IMETHODIMP nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -5178,14 +5258,19 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, containingBlock->GetStyleContext(getter_AddRefs(blockSC)); nsCOMPtr blockContent; containingBlock->GetContent(getter_AddRefs(blockContent)); - PRBool haveFLS = PR_FALSE; - if (HaveFirstLetterStyle(aPresContext, blockContent, blockSC)) { - haveFLS = PR_TRUE; - } + PRBool haveFirstLetterStyle = + HaveFirstLetterStyle(aPresContext, blockContent, blockSC); + PRBool haveFirstLineStyle = PR_FALSE; PRBool containerIsBlock = containingBlock == parentFrame; PRBool whitespaceDoesntMatter = PR_FALSE; PRBool okToSkip = PR_FALSE; if (containerIsBlock) { + // See if the container has :first-line style too + haveFirstLineStyle = + HaveFirstLineStyle(aPresContext, blockContent, blockSC); + + // Setup the whitespaceDoesntMatter flag so that we know whether + // or not we can skip over empty text frames. const nsStyleText* st; parentFrame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) st); whitespaceDoesntMatter = !st->WhiteSpaceIsSignificant(); @@ -5218,15 +5303,20 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, for (i = aNewIndexInContainer; i < count; i++) { nsCOMPtr childContent; aContainer->ChildAt(i, *getter_AddRefs(childContent)); - if (okToSkip && IsEmptyTextContent(childContent)) { - continue; - } + + // Block containers sometimes don't create frames for the kids + if (containerIsBlock) { + if (okToSkip && IsEmptyTextContent(childContent)) { + // Don't create a frame for useless compressible whitespace + continue; + } #if 0 - if (containerIsBlock && whitespaceDoesntMatter && - IsEmptyHTMLParagraph(childContent)) { - continue; - } + if (whitespaceDoesntMatter && IsEmptyHTMLParagraph(childContent)) { + // Don't create a frame for empty html paragraph's + continue; + } #endif + } // Construct a child frame okToSkip = PR_FALSE; @@ -5245,7 +5335,7 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } // See if we just created a frame in a :first-letter situation - if (haveFLS && + if (haveFirstLetterStyle && (0 == aNewIndexInContainer) && (frameItems.childList == frameItems.lastChild)) { MakeFirstLetterFrame(aPresContext, state, aContainer, childContent, @@ -5253,10 +5343,18 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } } - // Adjust parent frame for table inner/outer frame - // we need to do this here because we need both the parent frame and the constructed frame + if (haveFirstLineStyle) { + // It's possible that some of the new frames go into a + // first-line frame. Look at them and see... + AppendFirstLineFrames(aPresContext, state, aContainer, parentFrame, + frameItems); + } + + // Adjust parent frame for table inner/outer frame. We need to do + // this here because we need both the parent frame and the + // constructed frame nsresult result = NS_OK; - nsIFrame *adjustedParentFrame=parentFrame; + nsIFrame* adjustedParentFrame = parentFrame; firstAppendedFrame = frameItems.childList; if (nsnull != firstAppendedFrame) { const nsStyleDisplay* firstAppendedFrameDisplay; @@ -5268,7 +5366,7 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } // Notify the parent frame passing it the list of new frames - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result) && firstAppendedFrame) { // Append the flowed frames to the principal child list AppendFrames(aPresContext, shell, state.mFrameManager, aContainer, adjustedParentFrame, firstAppendedFrame); @@ -5304,94 +5402,30 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, } } - // Here we have been notified that content has been insert - // so if the select now has a single item - // we need to go in and removed the dummy frame - nsCOMPtr selectElement; - nsresult res = aContainer->QueryInterface(nsCOMTypeInfo::GetIID(), - (void**)getter_AddRefs(selectElement)); - if (NS_SUCCEEDED(res) && selectElement) { + // Here we have been notified that content has been appended so if + // the select now has a single item we need to go in and removed + // the dummy frame. + nsCOMPtr sel(do_QueryInterface(aContainer)); + if (sel) { nsCOMPtr childContent; aContainer->ChildAt(aNewIndexInContainer, *getter_AddRefs(childContent)); if (childContent) { - RemoveDummyFrameFromSelect(aPresContext, shell, aContainer, childContent, selectElement); + RemoveDummyFrameFromSelect(aPresContext, shell, aContainer, + childContent, sel); } } } else { -#if 0 // Since the parentFrame wasn't found, aContainer didn't have a // frame created for it. Maybe now that it has a new child it // should get a frame... MaybeCreateContainerFrame(aPresContext, aContainer); -#endif } return NS_OK; } -#if 0 -nsresult -nsCSSFrameConstructor::MaybeCreateContainerFrame(nsIPresContext* aPresContext, - nsIContent* aContainer) -{ - nsresult rv = NS_OK; - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - - // See if aContainer's parent has a frame... - nsCOMPtr containerParent; - aContainer->GetParent(*getter_AddRefs(containerParent)); - if (containerParent) { - parentFrame = GetFrameFor(shell, aPresContext, containerParent); - if (parentFrame) { - // aContainer's parent has a frame. Maybe aContainer needs a - // frame now? If it's display none, then it doesn't. - nsCOMPtr parentStyleContext; - parentFrame->GetStyleContext(getter_AddRefs(parentStyleContext)); - nsCOMPtr styleContext; - aPresContext->ResolveStyleContextFor(aContainer, parentStyleContext, - PR_FALSE, - getter_AddRefs(styleContext)); - const nsStyleDisplay* display = (const nsStyleDisplay*) - styleContext->GetStyleData(eStyleStruct_Display); - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // aContainer's display is not none and it has a parent - // frame. Now we see if it needs a frame after new content - // was appended. - if (IsHTMLParagraph(aContainer)) { - if (!IsEmptyContent(aContainer)) { - // It's an HTML paragraph (P) and it has some - // content. Because of the previous checks we now know - // that the P used to have nothing but empty content and - // therefore had no frame created. This condition is no - // longer true so we create a frame for aContainer (and - // its children) and insert them into the tree... - PRInt32 ix; - containerParent->IndexOf(aContainer, ix); - if (ix >= 0) { -#ifdef DEBUG_kipp - printf("ContentAppended: recreating frame for HTML:P\n"); -#endif - ContentInserted(aPresContext, containerParent, aContainer, ix); - } - } - } - } - } - else { - // If aContainer's parent has no frame then there is no need - // in trying to create a frame for aContainer. - } - } - else { - // aContainer has no parent. Odd. - } - return rv; -} -#endif - nsresult nsCSSFrameConstructor::MakeFirstLetterFrame(nsIPresContext* aPresContext, nsFrameConstructorState& aState, @@ -5669,20 +5703,19 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, nextSibling = FindNextSibling(shell, aContainer, aIndexInContainer); } - // Get the geometric parent. + // Get the geometric parent. Use the prev sibling if we have it; + // otherwise use the next sibling nsIFrame* parentFrame; - if ((nsnull == prevSibling) && (nsnull == nextSibling)) { - + if (nsnull != prevSibling) { + prevSibling->GetParent(&parentFrame); + } + else if (nextSibling) { + nextSibling->GetParent(&parentFrame); + } + else { // No previous or next sibling so treat this like an appended frame. isAppend = PR_TRUE; shell->GetPrimaryFrameFor(aContainer, &parentFrame); - } else { - // Use the prev sibling if we have it; otherwise use the next sibling - if (nsnull != prevSibling) { - prevSibling->GetParent(&parentFrame); - } else { - nextSibling->GetParent(&parentFrame); - } } // Construct a new frame @@ -5692,60 +5725,49 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, GetAbsoluteContainingBlock(aPresContext, parentFrame), GetFloaterContainingBlock(aPresContext, parentFrame)); - // Examine the floater-container-block (which is the nearest - // block element up the tree) and see if :first-letter style - // applies. + PRBool needFixup = PR_FALSE; nsIFrame* containingBlock = state.mFloatedItems.containingBlock; nsCOMPtr blockSC; - containingBlock->GetStyleContext(getter_AddRefs(blockSC)); nsCOMPtr blockContent; - containingBlock->GetContent(getter_AddRefs(blockContent)); - PRBool haveFLS = - HaveFirstLetterStyle(aPresContext, blockContent, blockSC); - PRBool needFixup = PR_FALSE; - if (haveFLS) { - // Trap out to special routine that handles adjusting a blocks - // frame tree when first-letter style is present. -#ifdef NOISY_FIRST_LETTER - printf("ContentInserted: indexInContainer=%d containingBlock=", - aIndexInContainer); - nsFrame::ListTag(stdout, containingBlock); - printf("\n"); - printf(" parentFrame="); - nsFrame::ListTag(stdout, parentFrame); - if (prevSibling) { - printf(" prevSibling="); - nsFrame::ListTag(stdout, prevSibling); - } - printf("\n"); -#endif + PRBool haveFirstLetterStyle = PR_FALSE; + PRBool haveFirstLineStyle = PR_FALSE; + const nsStyleDisplay* parentDisplay; + parentFrame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)parentDisplay); - // Get the correct parentFrame and prevSibling - if a - // letter-frame is present, use its parent. - nsCOMPtr type; - parentFrame->GetFrameType(getter_AddRefs(type)); - if (type.get() == nsLayoutAtoms::letterFrame) { - if (prevSibling) { - prevSibling = parentFrame; + // Examine the parentFrame where the insertion is taking + // place. If its a certain kind of container then some special + // processing is done. + if ((NS_STYLE_DISPLAY_BLOCK == parentDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == parentDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE_BLOCK == parentDisplay->mDisplay)) { + // Dig up the special style flags + containingBlock->GetStyleContext(getter_AddRefs(blockSC)); + containingBlock->GetContent(getter_AddRefs(blockContent)); + HaveSpecialBlockStyle(aPresContext, blockContent, blockSC, + &haveFirstLetterStyle, + &haveFirstLineStyle); + + if (haveFirstLetterStyle) { + // Get the correct parentFrame and prevSibling - if a + // letter-frame is present, use its parent. + nsCOMPtr parentFrameType; + parentFrame->GetFrameType(getter_AddRefs(parentFrameType)); + if (parentFrameType == nsLayoutAtoms::letterFrame) { + if (prevSibling) { + prevSibling = parentFrame; + } + parentFrame->GetParent(&parentFrame); } - parentFrame->GetParent(&parentFrame); -#ifdef NOISY_FIRST_LETTER - printf(" ==> revised parentFrame="); - nsFrame::ListTag(stdout, parentFrame); - printf("\n"); -#endif - } - if (0 == aIndexInContainer) { - // See if after we construct the new first child if we will - // need to fixup the second child's frames. - state.mFirstLetterStyle = PR_TRUE; - if ((parentFrame == containingBlock) || - ContentIsLogicalFirstChild(aChild, blockContent)) { - needFixup = PR_TRUE; -#ifdef NOISY_FIRST_LETTER - printf(" ==> needFixup=yes\n"); -#endif + if (0 == aIndexInContainer) { + // See if after we construct the new first child if we will + // need to fixup the second child's frames. + state.mFirstLetterStyle = PR_TRUE; + if ((parentFrame == containingBlock) || + ContentIsLogicalFirstChild(aChild, blockContent)) { + needFixup = PR_TRUE; + } } } } @@ -5754,18 +5776,33 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, frameItems); // See if we just created a frame in a :first-letter situation - if (haveFLS && (0 == aIndexInContainer)) { + if (haveFirstLetterStyle && (0 == aIndexInContainer)) { MakeFirstLetterFrame(aPresContext, state, aContainer, aChild, blockContent, parentFrame, frameItems); } + + if (haveFirstLineStyle) { + // It's possible that the new frame goes into a first-line + // frame. Look at it and see... + if (isAppend) { + // Use append logic when appending + AppendFirstLineFrames(aPresContext, state, aContainer, parentFrame, + frameItems); + } + else { + // Use more complicated insert logic when inserting + InsertFirstLineFrames(aPresContext, state, aContainer, + containingBlock, &parentFrame, + prevSibling, frameItems); + } + } nsIFrame* newFrame = frameItems.childList; - if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) { // Notify the parent frame if (isAppend) { - rv = AppendFrames(aPresContext, shell, state.mFrameManager, aContainer, - parentFrame, newFrame); + rv = AppendFrames(aPresContext, shell, state.mFrameManager, + aContainer, parentFrame, newFrame); } else { if (!prevSibling) { // We're inserting the new frame as the first child. See if the @@ -5831,6 +5868,12 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, } } } + else { + // Since the parentFrame wasn't found, aContainer didn't have a + // frame created for it. Maybe now that it has a new child it + // should get a frame... + MaybeCreateContainerFrame(aPresContext, aContainer); + } // Here we have been notified that content has been insert // so if the select now has a single item @@ -6003,7 +6046,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, // we need to add a pseudo frame so select gets sized as the best it can // so here we see if it is a select and then we get the number of options nsresult result = NS_ERROR_FAILURE; - if (aContainer && nsnull != childFrame) { + if (aContainer && childFrame) { nsCOMPtr selectElement; result = aContainer->QueryInterface(nsCOMTypeInfo::GetIID(), (void**)getter_AddRefs(selectElement)); @@ -6085,6 +6128,23 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, } #endif // INCLUDE_XUL +#if 0 + // It's possible that we just made an HTML paragraph empty... + if (IsEmptyHTMLParagraph(aContainer)) { + nsCOMPtr containerParent; + aContainer->GetParent(*getter_AddRefs(containerParent)); + if (containerParent) { + PRInt32 ix; + containerParent->IndexOf(aContainer, ix); + if (ix >= 0) { + // No point in doing the fixup + needFixup = PR_FALSE; + rv = ContentRemoved(aPresContext, containerParent, aContainer, ix); + } + } + } +#endif + if (childFrame) { // Get the childFrame's parent frame nsIFrame* parentFrame; @@ -7598,6 +7658,67 @@ nsCSSFrameConstructor::GetFirstLetterStyle(nsIPresContext* aPresContext, return fls; } +nsIStyleContext* +nsCSSFrameConstructor::GetFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext) +{ + nsIStyleContext* fls = nsnull; + aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::firstLinePseudo, + aStyleContext, PR_FALSE, &fls); + return fls; +} + +// Predicate to see if a given content (block element) has +// first-letter style applied to it. +PRBool +nsCSSFrameConstructor::HaveFirstLetterStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext) +{ + nsCOMPtr fls; + aPresContext->ProbePseudoStyleContextFor(aContent, + nsHTMLAtoms::firstLetterPseudo, + aStyleContext, PR_FALSE, + getter_AddRefs(fls)); + PRBool result = PR_FALSE; + if (fls) { + result = PR_TRUE; + } + return result; +} + +PRBool +nsCSSFrameConstructor::HaveFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext) +{ + nsCOMPtr fls; + aPresContext->ProbePseudoStyleContextFor(aContent, + nsHTMLAtoms::firstLinePseudo, + aStyleContext, PR_FALSE, + getter_AddRefs(fls)); + PRBool result = PR_FALSE; + if (fls) { + result = PR_TRUE; + } + return result; +} + +void +nsCSSFrameConstructor::HaveSpecialBlockStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext, + PRBool* aHaveFirstLetterStyle, + PRBool* aHaveFirstLineStyle) +{ + *aHaveFirstLetterStyle = + HaveFirstLetterStyle(aPresContext, aContent, aStyleContext); + *aHaveFirstLineStyle = + HaveFirstLineStyle(aPresContext, aContent, aStyleContext); +} + PRBool nsCSSFrameConstructor::ShouldCreateFirstLetterFrame( nsIPresContext* aPresContext, @@ -7675,15 +7796,16 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresContext* aPresContext, for (PRInt32 i = 0; i < count; i++) { nsCOMPtr childContent; if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) { - if (okToSkip && IsEmptyTextContent(childContent)) { - continue; - } + if (aParentIsBlock) { + if (okToSkip && IsEmptyTextContent(childContent)) { + continue; + } #if 0 - if (aParentIsBlock && whitespaceDoesntMatter && - IsEmptyHTMLParagraph(childContent)) { - continue; - } + if (whitespaceDoesntMatter && IsEmptyHTMLParagraph(childContent)) { + continue; + } #endif + } // Construct a child frame okToSkip = PR_FALSE; @@ -7729,9 +7851,363 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresContext* aPresContext, } } + if (aParentIsBlock && aState.mFirstLineStyle) { + rv = WrapFramesInFirstLineFrame(aPresContext, aState, aContent, aFrame, + aFrameItems); + } + return rv; } +//---------------------------------------------------------------------- + +// Support for :first-line style + +// XXX this predicate and its cousins need to migrated to a single +// place in layout - something in nsStyleDisplay maybe? +static PRBool +IsInlineFrame(nsIFrame* aFrame) +{ + const nsStyleDisplay* display; + aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + switch (display->mDisplay) { + case NS_STYLE_DISPLAY_INLINE: + case NS_STYLE_DISPLAY_INLINE_BLOCK: + case NS_STYLE_DISPLAY_INLINE_TABLE: + return PR_TRUE; + default: + break; + } + return PR_FALSE; +} + +static void +ReparentFrame(nsIPresContext* aPresContext, + nsIFrame* aNewParentFrame, + nsIStyleContext* aParentStyleContext, + nsIFrame* aFrame) +{ + aFrame->ReResolveStyleContext(aPresContext, aParentStyleContext, + NS_STYLE_HINT_REFLOW, + nsnull, nsnull); + aFrame->SetParent(aNewParentFrame); +} + +// 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. +nsresult +nsCSSFrameConstructor::WrapFramesInFirstLineFrame( + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aFrame, + nsFrameItems& aFrameItems) +{ + nsresult rv = NS_OK; + + // Find the first and last inline frame in aFrameItems + nsIFrame* kid = aFrameItems.childList; + nsIFrame* firstInlineFrame = nsnull; + nsIFrame* lastInlineFrame = nsnull; + while (kid) { + if (IsInlineFrame(kid)) { + if (!firstInlineFrame) firstInlineFrame = kid; + lastInlineFrame = kid; + } + else { + break; + } + kid->GetNextSibling(&kid); + } + + // If we don't find any inline frames, then there is nothing to do + if (!firstInlineFrame) { + return rv; + } + + // Create line frame + nsCOMPtr parentStyle; + aFrame->GetStyleContext(getter_AddRefs(parentStyle)); + nsCOMPtr firstLineStyle( + getter_AddRefs(GetFirstLineStyle(aPresContext, aContent, parentStyle)) + ); + nsIFrame* lineFrame; + rv = NS_NewFirstLineFrame(&lineFrame); + if (NS_SUCCEEDED(rv)) { + // Initialize the line frame + rv = lineFrame->Init(*aPresContext, aContent, aFrame, + firstLineStyle, nsnull); + + // Mangle the list of frames we are giving to the block: first + // chop the list in two after lastInlineFrame + nsIFrame* secondBlockFrame; + lastInlineFrame->GetNextSibling(&secondBlockFrame); + lastInlineFrame->SetNextSibling(nsnull); + + // The lineFrame will be the block's first child; the rest of the + // frame list (after lastInlineFrame) will be the second and + // subsequent children; join the list together and reset + // aFrameItems appropriately. + if (secondBlockFrame) { + lineFrame->SetNextSibling(secondBlockFrame); + } + if (aFrameItems.childList == lastInlineFrame) { + // Just in case the block had exactly one inline child + aFrameItems.lastChild = lineFrame; + } + aFrameItems.childList = lineFrame; + + // Give the inline frames to the lineFrame after reparenting them + kid = firstInlineFrame; + while (kid) { + ReparentFrame(aPresContext, lineFrame, firstLineStyle, kid); + kid->GetNextSibling(&kid); + } + lineFrame->SetInitialChildList(*aPresContext, nsnull, firstInlineFrame); + } + + return rv; +} + +// Special routine to handle appending a new frame to a block frame's +// child list. Takes care of placing the new frame into the right +// place when first-line style is present. +nsresult +nsCSSFrameConstructor::AppendFirstLineFrames( + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsFrameItems& aFrameItems) +{ + // It's possible that aBlockFrame needs to have a first-line frame + // created because it doesn't currently have any children. + nsIFrame* blockKid; + aBlockFrame->FirstChild(nsnull, &blockKid); + if (!blockKid) { + return WrapFramesInFirstLineFrame(aPresContext, aState, aContent, + aBlockFrame, aFrameItems); + } + + // Examine the last block child - if it's a first-line frame then + // appended frames need special treatment. + nsresult rv = NS_OK; + nsFrameList blockFrames(blockKid); + nsIFrame* lastBlockKid = blockFrames.LastChild(); + nsCOMPtr frameType; + lastBlockKid->GetFrameType(getter_AddRefs(frameType)); + if (frameType != nsLayoutAtoms::lineFrame) { + // No first-line frame at the end of the list, therefore there is + // an interveening block between any first-line frame the frames + // we are appending. Therefore, we don't need any special + // treatment of the appended frames. + return rv; + } + nsIFrame* lineFrame = lastBlockKid; + nsCOMPtr firstLineStyle; + lineFrame->GetStyleContext(getter_AddRefs(firstLineStyle)); + + // Find the first and last inline frame in aFrameItems + nsIFrame* kid = aFrameItems.childList; + nsIFrame* firstInlineFrame = nsnull; + nsIFrame* lastInlineFrame = nsnull; + while (kid) { + if (IsInlineFrame(kid)) { + if (!firstInlineFrame) firstInlineFrame = kid; + lastInlineFrame = kid; + } + else { + break; + } + kid->GetNextSibling(&kid); + } + + // If we don't find any inline frames, then there is nothing to do + if (!firstInlineFrame) { + return rv; + } + + // The inline frames get appended to the lineFrame. Make sure they + // are reparented properly. + nsIFrame* remainingFrames; + lastInlineFrame->GetNextSibling(&remainingFrames); + lastInlineFrame->SetNextSibling(nsnull); + kid = firstInlineFrame; + while (kid) { + ReparentFrame(aPresContext, lineFrame, firstLineStyle, kid); + kid->GetNextSibling(&kid); + } + aState.mFrameManager->AppendFrames(*aPresContext, *aState.mPresShell, + lineFrame, nsnull, firstInlineFrame); + + // The remaining frames get appended to the block frame + if (remainingFrames) { + aFrameItems.childList = remainingFrames; + } + else { + aFrameItems.childList = nsnull; + aFrameItems.lastChild = nsnull; + } + + return rv; +} + +// Special routine to handle inserting a new frame into a block +// frame's child list. Takes care of placing the new frame into the +// right place when first-line style is present. +nsresult +nsCSSFrameConstructor::InsertFirstLineFrames( + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsIFrame** aParentFrame, + nsIFrame* aPrevSibling, + nsFrameItems& aFrameItems) +{ + nsresult rv = NS_OK; +#if 0 + nsIFrame* parentFrame = *aParentFrame; + nsIFrame* newFrame = aFrameItems.childList; + PRBool isInline = IsInlineFrame(newFrame); + + if (!aPrevSibling) { + // Insertion will become the first frame. Two cases: we either + // already have a first-line frame or we don't. + nsIFrame* firstBlockKid; + aBlockFrame->FirstChild(nsnull, &firstBlockKid); + nsCOMPtr frameType; + firstBlockKid->GetFrameType(getter_AddRefs(frameType)); + if (frameType == nsLayoutAtoms::lineFrame) { + // We already have a first-line frame + nsIFrame* lineFrame = firstBlockKid; + nsCOMPtr firstLineStyle; + lineFrame->GetStyleContext(getter_AddRefs(firstLineStyle)); + + if (isInline) { + // Easy case: the new inline frame will go into the lineFrame. + ReparentFrame(aPresContext, lineFrame, firstLineStyle, newFrame); + aState.mFrameManager->InsertFrames(*aPresContext, *aState.mPresShell, + lineFrame, nsnull, nsnull, + newFrame); + + // Since the frame is going into the lineFrame, don't let it + // go into the block too. + aFrameItems.childList = nsnull; + aFrameItems.lastChild = nsnull; + } + else { + // Harder case: We are about to insert a block level element + // before the first-line frame. + // XXX need a method to steal away frames from the line-frame + } + } + else { + // We do not have a first-line frame + if (isInline) { + // We now need a first-line frame to contain the inline frame. + nsIFrame* lineFrame; + rv = NS_NewFirstLineFrame(&lineFrame); + if (NS_SUCCEEDED(rv)) { + // Lookup first-line style context + nsCOMPtr parentStyle; + aBlockFrame->GetStyleContext(getter_AddRefs(parentStyle)); + nsCOMPtr firstLineStyle( + getter_AddRefs(GetFirstLineStyle(aPresContext, aContent, + parentStyle)) + ); + + // Initialize the line frame + rv = lineFrame->Init(*aPresContext, aContent, aBlockFrame, + firstLineStyle, nsnull); + + // Make sure the caller inserts the lineFrame into the + // blocks list of children. + aFrameItems.childList = lineFrame; + aFrameItems.lastChild = lineFrame; + + // Give the inline frames to the lineFrame after + // reparenting them + ReparentFrame(aPresContext, lineFrame, firstLineStyle, newFrame); + lineFrame->SetInitialChildList(*aPresContext, nsnull, newFrame); + } + } + else { + // Easy case: the regular insertion logic can insert the new + // frame because its a block frame. + } + } + } + else { + // Insertion will not be the first frame. + nsIFrame* prevSiblingParent; + aPrevSibling->GetParent(&prevSiblingParent); + if (prevSiblingParent == aBlockFrame) { + // Easy case: The prev-siblings parent is the block + // frame. Therefore the prev-sibling is not currently in a + // line-frame. Therefore the new frame which is going after it, + // regardless of type, is not going into a line-frame. + } + else { + // If the prevSiblingParent is not the block-frame then it must + // be a line-frame (if it were a letter-frame, that logic would + // already have adjusted the prev-sibling to be the + // letter-frame). + if (isInline) { + // Easy case: the insertion can go where the caller thinks it + // should go (which is into prevSiblingParent). + } + else { + // Block elements don't end up in line-frames, therefore + // change the insertion point to aBlockFrame. However, there + // might be more inline elements following aPrevSibling that + // need to be pulled out of the line-frame and become children + // of the block. + nsIFrame* nextSibling; + aPrevSibling->GetNextSibling(&nextSibling); + nsIFrame* nextLineFrame; + prevSiblingParent->GetNextInFlow(&nextLineFrame); + if (nextSibling || nextLineFrame) { + // Oy. We have work to do. Create a list of the new frames + // that are going into the block by stripping them away from + // the line-frame(s). + nsFrameList list(nextSibling); + if (nextSibling) { + nsLineFrame* lineFrame = (nsLineFrame*) prevSiblingParent; + lineFrame->StealFramesFrom(nextSibling); + } + + nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame; + for (;;) { + nextLineFrame->GetNextInFlow(&nextLineFrame); + if (!nextLineFrame) { + break; + } + nsIFrame* kids; + nextLineFrame->FirstChild(nsnull, &kids); + } + } + else { + // We got lucky: aPrevSibling was the last inline frame in + // the line-frame. + ReparentFrame(aPresContext, aBlockFrame, firstLineStyle, newFrame); + aState.mFrameManager->InsertFrames(*aPresContext, *aState.mPresShell, + aBlockFrame, nsnull, + prevSiblingParent, newFrame); + aFrameItems.childList = nsnull; + aFrameItems.lastChild = nsnull; + } + } + } + } + +#endif + return rv; +} + +//---------------------------------------------------------------------- + // Determine how many characters in the text fragment apply to the // first letter static PRInt32 @@ -7783,15 +8259,15 @@ TotalLength(nsTextFragment* aFragments, PRInt32 aNumFragments) return sum; } -static PRBool NeedFirstLetterContinuation(nsIContent* aContent) +static PRBool +NeedFirstLetterContinuation(nsIContent* aContent) { NS_PRECONDITION(aContent, "null ptr"); PRBool result = PR_FALSE; if (aContent) { - nsITextContent* tc = nsnull; - nsresult rv = aContent->QueryInterface(kITextContentIID, (void**) &tc); - if (NS_SUCCEEDED(rv)) { + nsCOMPtr tc(do_QueryInterface(aContent)); + if (tc) { nsTextFragment* frags = nsnull; PRInt32 numFrags = 0; tc->GetText((const nsTextFragment*&)frags, numFrags); diff --git a/layout/html/style/src/nsCSSFrameConstructor.h b/layout/html/style/src/nsCSSFrameConstructor.h index a6ff6d4c0d1..31ded2af593 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.h +++ b/layout/html/style/src/nsCSSFrameConstructor.h @@ -627,9 +627,27 @@ InitializeScrollFrame(nsIPresContext* aPresContext, // Methods support creating block frames and their children - nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aStyleContext); + static nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static nsIStyleContext* GetFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static PRBool HaveFirstLetterStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static PRBool HaveFirstLineStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext); + + static void HaveSpecialBlockStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aStyleContext, + PRBool* aHaveFirstLetterStyle, + PRBool* aHaveFirstLineStyle); PRBool ShouldCreateFirstLetterFrame(nsIPresContext* aPresContext, nsIContent* aContent, @@ -679,6 +697,29 @@ InitializeScrollFrame(nsIPresContext* aPresContext, nsFrameItems& aFloatingItems, nsIStyleContext* aStyleContext); + nsresult WrapFramesInFirstLineFrame(nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aFrame, + nsFrameItems& aFrameItems); + + nsresult AppendFirstLineFrames(nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsFrameItems& aFrameItems); + + nsresult InsertFirstLineFrames(nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aBlockFrame, + nsIFrame** aParentFrame, + nsIFrame* aPrevSibling, + nsFrameItems& aFrameItems); + + nsresult MaybeCreateContainerFrame(nsIPresContext* aPresContext, + nsIContent* aContainer); + protected: nsIDocument* mDocument; diff --git a/layout/html/table/src/nsTableCellFrame.cpp b/layout/html/table/src/nsTableCellFrame.cpp index 0af53e0f739..5a0ea6605d6 100644 --- a/layout/html/table/src/nsTableCellFrame.cpp +++ b/layout/html/table/src/nsTableCellFrame.cpp @@ -1150,3 +1150,15 @@ nsPoint nsTableCellFrame::GetCollapseOffset() return mCollapseOffset; } + +NS_IMETHODIMP +nsTableCellFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableCellFrame.h b/layout/html/table/src/nsTableCellFrame.h index 7c221d691ff..5c4b0e028fb 100644 --- a/layout/html/table/src/nsTableCellFrame.h +++ b/layout/html/table/src/nsTableCellFrame.h @@ -111,6 +111,8 @@ public: */ NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + NS_IMETHOD GetFrameName(nsString& aResult) const; virtual void VerticallyAlignChild(); diff --git a/layout/html/table/src/nsTableColFrame.cpp b/layout/html/table/src/nsTableColFrame.cpp index c96e6e0f2da..c107150b864 100644 --- a/layout/html/table/src/nsTableColFrame.cpp +++ b/layout/html/table/src/nsTableColFrame.cpp @@ -174,3 +174,15 @@ nsTableColFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableCol", aResult); } + +NS_IMETHODIMP +nsTableColFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableColFrame.h b/layout/html/table/src/nsTableColFrame.h index 6078dc88efc..93cb9623b64 100644 --- a/layout/html/table/src/nsTableColFrame.h +++ b/layout/html/table/src/nsTableColFrame.h @@ -82,6 +82,7 @@ public: nsReflowStatus& aStatus); NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; /** return the index of the column the col represents. always >= 0 */ virtual PRInt32 GetColumnIndex (); diff --git a/layout/html/table/src/nsTableColGroupFrame.cpp b/layout/html/table/src/nsTableColGroupFrame.cpp index 1bd4fc5d2ba..833d9ec86a0 100644 --- a/layout/html/table/src/nsTableColGroupFrame.cpp +++ b/layout/html/table/src/nsTableColGroupFrame.cpp @@ -700,3 +700,15 @@ nsTableColGroupFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableColGroup", aResult); } + +NS_IMETHODIMP +nsTableColGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableColGroupFrame.h b/layout/html/table/src/nsTableColGroupFrame.h index 759cbc31533..538185dad40 100644 --- a/layout/html/table/src/nsTableColGroupFrame.h +++ b/layout/html/table/src/nsTableColGroupFrame.h @@ -79,6 +79,7 @@ public: nsReflowStatus& aStatus); NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; /** returns the number of columns represented by this group. * if there are col children, count them (taking into account the span of each) diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index 8e9ce484586..17048642b13 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -5362,3 +5362,14 @@ PRBool nsTableFrame::ColIsSpannedInto(PRInt32 aColIndex) } +NS_IMETHODIMP +nsTableFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index c65c68a093e..16cf81ae7cf 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -235,6 +235,8 @@ public: /** @see nsIFrame::GetFrameName */ NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + /** get the max border thickness for each edge */ void GetTableBorder(nsMargin &aBorder); diff --git a/layout/html/table/src/nsTableOuterFrame.cpp b/layout/html/table/src/nsTableOuterFrame.cpp index c5d845c6808..e4be249b8a8 100644 --- a/layout/html/table/src/nsTableOuterFrame.cpp +++ b/layout/html/table/src/nsTableOuterFrame.cpp @@ -1184,3 +1184,15 @@ nsTableOuterFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableOuter", aResult); } + +NS_IMETHODIMP +nsTableOuterFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableOuterFrame.h b/layout/html/table/src/nsTableOuterFrame.h index 9815a25e7f3..bbc72137184 100644 --- a/layout/html/table/src/nsTableOuterFrame.h +++ b/layout/html/table/src/nsTableOuterFrame.h @@ -92,6 +92,8 @@ public: /** @see nsIFrame::GetFrameName */ NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + /** SetSelected needs to be overridden to talk to inner tableframe */ NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, nsSpread aSpread); diff --git a/layout/html/table/src/nsTableRowFrame.cpp b/layout/html/table/src/nsTableRowFrame.cpp index 1a13def1b85..ed757211c4f 100644 --- a/layout/html/table/src/nsTableRowFrame.cpp +++ b/layout/html/table/src/nsTableRowFrame.cpp @@ -1587,5 +1587,14 @@ nsTableRowFrame::GetFrameName(nsString& aResult) const return MakeFrameName("TableRow", aResult); } - - +NS_IMETHODIMP +nsTableRowFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableRowFrame.h b/layout/html/table/src/nsTableRowFrame.h index 7d3abcd21e2..b7dce14074c 100644 --- a/layout/html/table/src/nsTableRowFrame.h +++ b/layout/html/table/src/nsTableRowFrame.h @@ -148,6 +148,8 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; /** set mTallestCell to 0 in anticipation of recalculating it */ void ResetMaxChildHeight(); diff --git a/layout/html/table/src/nsTableRowGroupFrame.cpp b/layout/html/table/src/nsTableRowGroupFrame.cpp index 5d06d250e98..7f46ceba742 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -1561,3 +1561,15 @@ nsTableRowGroupFrame::GetFrameName(nsString& aResult) const return MakeFrameName("TableRowGroup", aResult); } + +NS_IMETHODIMP +nsTableRowGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/html/table/src/nsTableRowGroupFrame.h b/layout/html/table/src/nsTableRowGroupFrame.h index f5f1300f58d..962970d5e1a 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.h +++ b/layout/html/table/src/nsTableRowGroupFrame.h @@ -154,6 +154,8 @@ public: */ NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + NS_IMETHOD GetFrameName(nsString& aResult) const; /** set aCount to the number of child rows (not necessarily == number of child frames) */ diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 0af53e0f739..5a0ea6605d6 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -1150,3 +1150,15 @@ nsPoint nsTableCellFrame::GetCollapseOffset() return mCollapseOffset; } + +NS_IMETHODIMP +nsTableCellFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h index 7c221d691ff..5c4b0e028fb 100644 --- a/layout/tables/nsTableCellFrame.h +++ b/layout/tables/nsTableCellFrame.h @@ -111,6 +111,8 @@ public: */ NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + NS_IMETHOD GetFrameName(nsString& aResult) const; virtual void VerticallyAlignChild(); diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp index c96e6e0f2da..c107150b864 100644 --- a/layout/tables/nsTableColFrame.cpp +++ b/layout/tables/nsTableColFrame.cpp @@ -174,3 +174,15 @@ nsTableColFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableCol", aResult); } + +NS_IMETHODIMP +nsTableColFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableColFrame.h b/layout/tables/nsTableColFrame.h index 6078dc88efc..93cb9623b64 100644 --- a/layout/tables/nsTableColFrame.h +++ b/layout/tables/nsTableColFrame.h @@ -82,6 +82,7 @@ public: nsReflowStatus& aStatus); NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; /** return the index of the column the col represents. always >= 0 */ virtual PRInt32 GetColumnIndex (); diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index 1bd4fc5d2ba..833d9ec86a0 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -700,3 +700,15 @@ nsTableColGroupFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableColGroup", aResult); } + +NS_IMETHODIMP +nsTableColGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableColGroupFrame.h b/layout/tables/nsTableColGroupFrame.h index 759cbc31533..538185dad40 100644 --- a/layout/tables/nsTableColGroupFrame.h +++ b/layout/tables/nsTableColGroupFrame.h @@ -79,6 +79,7 @@ public: nsReflowStatus& aStatus); NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; /** returns the number of columns represented by this group. * if there are col children, count them (taking into account the span of each) diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 8e9ce484586..17048642b13 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -5362,3 +5362,14 @@ PRBool nsTableFrame::ColIsSpannedInto(PRInt32 aColIndex) } +NS_IMETHODIMP +nsTableFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index c65c68a093e..16cf81ae7cf 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -235,6 +235,8 @@ public: /** @see nsIFrame::GetFrameName */ NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + /** get the max border thickness for each edge */ void GetTableBorder(nsMargin &aBorder); diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index c5d845c6808..e4be249b8a8 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -1184,3 +1184,15 @@ nsTableOuterFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableOuter", aResult); } + +NS_IMETHODIMP +nsTableOuterFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index 9815a25e7f3..bbc72137184 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/layout/tables/nsTableOuterFrame.h @@ -92,6 +92,8 @@ public: /** @see nsIFrame::GetFrameName */ NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + /** SetSelected needs to be overridden to talk to inner tableframe */ NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, nsSpread aSpread); diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 1a13def1b85..ed757211c4f 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -1587,5 +1587,14 @@ nsTableRowFrame::GetFrameName(nsString& aResult) const return MakeFrameName("TableRow", aResult); } - - +NS_IMETHODIMP +nsTableRowFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index 7d3abcd21e2..b7dce14074c 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -148,6 +148,8 @@ public: NS_IMETHOD GetFrameType(nsIAtom** aType) const; NS_IMETHOD GetFrameName(nsString& aResult) const; + + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; /** set mTallestCell to 0 in anticipation of recalculating it */ void ResetMaxChildHeight(); diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 5d06d250e98..7f46ceba742 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -1561,3 +1561,15 @@ nsTableRowGroupFrame::GetFrameName(nsString& aResult) const return MakeFrameName("TableRowGroup", aResult); } + +NS_IMETHODIMP +nsTableRowGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (aResult) { + PRUint32 sum = sizeof(*this); + // XXX write me + *aResult = sum; + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index f5f1300f58d..962970d5e1a 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -154,6 +154,8 @@ public: */ NS_IMETHOD GetFrameType(nsIAtom** aType) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; + NS_IMETHOD GetFrameName(nsString& aResult) const; /** set aCount to the number of child rows (not necessarily == number of child frames) */