diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1144,18 +1144,17 @@ public: // floated until a new float containing block is pushed. // XXX we should get rid of null float containing blocks and teach the // various frame classes to deal with floats instead. void PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock, nsFrameConstructorSaveState& aSaveState); // Function to return the proper geometric parent for a frame with display // struct given by aStyleDisplay and parent's frame given by - // aContentParentFrame. If the frame is not allowed to be positioned, pass - // false for aCanBePositioned. + // aContentParentFrame. nsIFrame* GetGeometricParent(const nsStyleDisplay* aStyleDisplay, nsIFrame* aContentParentFrame); /** * Function to add a new frame to the right frame list. This MUST be called * on frames before their children have been processed if the frames might * conceivably be out-of-flow; otherwise cleanup in error cases won't work * right. Also, this MUST be called on frames after they have been @@ -2178,109 +2177,16 @@ nsCSSFrameConstructor::CreateGeneratedCo // NS_FRAME_GENERATED_CONTENT. aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT; ConstructFrameInternal(aState, container, aParentFrame, elemName, kNameSpaceID_None, pseudoStyleContext, aFrameItems, PR_TRUE); aState.mAdditionalStateBits = savedStateBits; } -nsresult -nsCSSFrameConstructor::CreateInputFrame(nsFrameConstructorState& aState, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIAtom* aTag, - nsStyleContext* aStyleContext, - nsIFrame** aFrame, - const nsStyleDisplay* aStyleDisplay, - PRBool& aFrameHasBeenInitialized, - PRBool& aAddedToFrameList, - nsFrameItems& aFrameItems, - PRBool aHasPseudoParent) -{ - // Make sure to keep IsSpecialContent in synch with this code - - // Note: do not do anything in this method that assumes pseudo-frames have - // been processed. If you feel the urge to do something like that, fix - // callers accordingly. - nsCOMPtr control = do_QueryInterface(aContent); - if (!control) { - NS_ERROR("input doesn't implement nsIFormControl?"); - return NS_OK; - } - - switch (control->GetType()) { - case NS_FORM_INPUT_SUBMIT: - case NS_FORM_INPUT_RESET: - case NS_FORM_INPUT_BUTTON: - { - nsresult rv = ConstructButtonFrame(aState, aContent, aParentFrame, - aTag, aStyleContext, aFrame, - aStyleDisplay, aFrameItems, - aHasPseudoParent); - aAddedToFrameList = PR_TRUE; - aFrameHasBeenInitialized = PR_TRUE; - return rv; - } - - case NS_FORM_INPUT_CHECKBOX: - *aFrame = NS_NewGfxCheckboxControlFrame(mPresShell, aStyleContext); - return *aFrame ? NS_OK : NS_ERROR_OUT_OF_MEMORY; - - case NS_FORM_INPUT_RADIO: - *aFrame = NS_NewGfxRadioControlFrame(mPresShell, aStyleContext); - return *aFrame ? NS_OK : NS_ERROR_OUT_OF_MEMORY; - - case NS_FORM_INPUT_FILE: - { - *aFrame = NS_NewFileControlFrame(mPresShell, aStyleContext); - return *aFrame ? NS_OK : NS_ERROR_OUT_OF_MEMORY; - } - - case NS_FORM_INPUT_HIDDEN: - return NS_OK; // this does not create a frame so it needs special handling - // in IsSpecialContent - - case NS_FORM_INPUT_IMAGE: - return CreateHTMLImageFrame(aContent, aStyleContext, - NS_NewImageControlFrame, aFrame); - - case NS_FORM_INPUT_TEXT: - case NS_FORM_INPUT_PASSWORD: - { - *aFrame = NS_NewTextControlFrame(mPresShell, aStyleContext); - - return NS_UNLIKELY(!*aFrame) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; - } - - default: - NS_ASSERTION(0, "Unknown input type!"); - return NS_ERROR_INVALID_ARG; - } -} - -nsresult -nsCSSFrameConstructor::CreateHTMLImageFrame(nsIContent* aContent, - nsStyleContext* aStyleContext, - ImageFrameCreatorFunc aFunc, - nsIFrame** aFrame) -{ - *aFrame = nsnull; - - // Make sure to keep IsSpecialContent in synch with this code - if (nsImageFrame::ShouldCreateImageFrameFor(aContent, aStyleContext)) { - *aFrame = (*aFunc)(mPresShell, aStyleContext); - - if (NS_UNLIKELY(!*aFrame)) - return NS_ERROR_OUT_OF_MEMORY; - } - - return NS_OK; -} - static PRBool TextIsOnlyWhitespace(nsIContent* aContent) { return aContent->IsNodeOfType(nsINode::eTEXT) && aContent->TextIsOnlyWhitespace(); } /**************************************************** @@ -3187,76 +3093,28 @@ nsCSSFrameConstructor::GetParentFrame(PR aParentFrame = pseudoParentFrame; aIsPseudoParent = PR_TRUE; } aState.mAdditionalStateBits = savedStateBits; return rv; } -static PRBool -IsSpecialContent(nsIContent* aContent, - nsIAtom* aTag, - PRInt32 aNameSpaceID, - nsStyleContext* aStyleContext) +/* static */ +PRBool +nsCSSFrameConstructor::IsSpecialContent(nsIContent* aContent, + nsIAtom* aTag, + PRInt32 aNameSpaceID, + nsStyleContext* aStyleContext) { // Gross hack. Return true if this is a content node that we'd create a // frame for based on something other than display -- in other words if this // is a node that could never have a nsTableCellFrame, for example. - if (aContent->IsNodeOfType(nsINode::eHTML) || - aNameSpaceID == kNameSpaceID_XHTML) { - // XXXbz this is duplicating some logic from ConstructHTMLFrame.... - // Would be nice to avoid that. :( - - if (aTag == nsGkAtoms::input) { - nsCOMPtr control = do_QueryInterface(aContent); - if (control) { - PRInt32 type = control->GetType(); - if (NS_FORM_INPUT_HIDDEN == type) { - return PR_FALSE; // input hidden does not create a special frame - } - else if (NS_FORM_INPUT_IMAGE == type) { - return nsImageFrame::ShouldCreateImageFrameFor(aContent, aStyleContext); - } - } - - return PR_TRUE; - } - - if (aTag == nsGkAtoms::img || - aTag == nsGkAtoms::mozgeneratedcontentimage) { - return nsImageFrame::ShouldCreateImageFrameFor(aContent, aStyleContext); - } - - if (aTag == nsGkAtoms::object || - aTag == nsGkAtoms::applet || - aTag == nsGkAtoms::embed) { - return !(aContent->IntrinsicState() & - (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | - NS_EVENT_STATE_SUPPRESSED)); - } - - return - aTag == nsGkAtoms::br || - aTag == nsGkAtoms::wbr || - aTag == nsGkAtoms::textarea || - aTag == nsGkAtoms::select || - aTag == nsGkAtoms::fieldset || - aTag == nsGkAtoms::legend || - aTag == nsGkAtoms::frameset || - aTag == nsGkAtoms::iframe || - aTag == nsGkAtoms::spacer || - aTag == nsGkAtoms::button || - aTag == nsGkAtoms::isindex || - aTag == nsGkAtoms::canvas || -#if defined(MOZ_MEDIA) - aTag == nsGkAtoms::video || - aTag == nsGkAtoms::audio || -#endif - PR_FALSE; + if (FindHTMLData(aContent, aTag, aNameSpaceID, aStyleContext)) { + return PR_TRUE; } if (aNameSpaceID == kNameSpaceID_XUL) return #ifdef MOZ_XUL aTag == nsGkAtoms::button || aTag == nsGkAtoms::checkbox || @@ -3931,25 +3789,16 @@ NeedFrameFor(nsIFrame* aParentFrame, // want to be reconstructing frames. It's not even clear that these // should be considered ignorable just because they evaluate to // whitespace. return !aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) || !TextIsOnlyWhitespace(aChildContent) || aParentFrame->IsGeneratedContentFrame(); } -const nsStyleDisplay* -nsCSSFrameConstructor::GetDisplay(nsIFrame* aFrame) -{ - if (nsnull == aFrame) { - return nsnull; - } - return aFrame->GetStyleContext()->GetStyleDisplay(); -} - /*********************************************** * END TABLE SECTION ***********************************************/ static PRBool CheckOverflow(nsPresContext* aPresContext, const nsStyleDisplay* aDisplay) { if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) @@ -4633,25 +4482,20 @@ nsCSSFrameConstructor::CreatePlaceholder } nsresult nsCSSFrameConstructor::ConstructButtonFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsStyleContext* aStyleContext, - nsIFrame** aNewFrame, const nsStyleDisplay* aStyleDisplay, nsFrameItems& aFrameItems, - PRBool aHasPseudoParent) -{ - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - + nsIFrame** aNewFrame) +{ *aNewFrame = nsnull; nsIFrame* buttonFrame = nsnull; if (nsGkAtoms::button == aTag) { buttonFrame = NS_NewHTMLButtonControlFrame(mPresShell, aStyleContext); } else { buttonFrame = NS_NewGfxButtonControlFrame(mPresShell, aStyleContext); @@ -4757,20 +4601,19 @@ nsCSSFrameConstructor::ConstructButtonFr } nsresult nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsStyleContext* aStyleContext, - nsIFrame*& aNewFrame, const nsStyleDisplay* aStyleDisplay, - PRBool& aFrameHasBeenInitialized, - nsFrameItems& aFrameItems) + nsFrameItems& aFrameItems, + nsIFrame** aNewFrame) { nsresult rv = NS_OK; const PRInt32 kNoSizeSpecified = -1; // Construct a frame-based listbox or combobox nsCOMPtr sel(do_QueryInterface(aContent)); PRInt32 size = 1; if (sel) { @@ -4858,18 +4701,17 @@ nsCSSFrameConstructor::ConstructSelectFr // Initialize the additional popup child list which contains the // dropdown list frame. nsFrameItems popupItems; popupItems.AddChild(listFrame); comboboxFrame->SetInitialChildList(nsGkAtoms::selectPopupList, popupItems.childList); - aNewFrame = comboboxFrame; - aFrameHasBeenInitialized = PR_TRUE; + *aNewFrame = comboboxFrame; aState.mFrameState = historyState; if (aState.mFrameState && aState.mFrameManager) { // Restore frame state for the entire subtree of |comboboxFrame|. aState.mFrameManager->RestoreFrameState(comboboxFrame, aState.mFrameState); } } else { /////////////////////////////////////////////////////////////////// @@ -4887,19 +4729,17 @@ nsCSSFrameConstructor::ConstructSelectFr mPresShell, aStyleContext, NS_BLOCK_FLOAT_MGR); // ******* this code stolen from Initialze ScrollFrame ******** // please adjust this code to use BuildScrollFrame. InitializeSelectFrame(aState, listFrame, scrolledFrame, aContent, aParentFrame, aStyleContext, PR_FALSE, aFrameItems); - aNewFrame = listFrame; - - aFrameHasBeenInitialized = PR_TRUE; + *aNewFrame = listFrame; } } return rv; } /** * Used to be InitializeScrollFrame but now it's only used for the select tag @@ -4986,20 +4826,19 @@ nsCSSFrameConstructor::InitializeSelectF } nsresult nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsStyleContext* aStyleContext, - nsIFrame*& aNewFrame, + const nsStyleDisplay* aStyleDisplay, nsFrameItems& aFrameItems, - const nsStyleDisplay* aStyleDisplay, - PRBool& aFrameHasBeenInitialized) + nsIFrame** aNewFrame) { nsIFrame* newFrame = NS_NewFieldSetFrame(mPresShell, aStyleContext); if (NS_UNLIKELY(!newFrame)) { return NS_ERROR_OUT_OF_MEMORY; } // Initialize it InitAndRestoreFrame(aState, aContent, @@ -5068,20 +4907,17 @@ nsCSSFrameConstructor::ConstructFieldSet // Set the scrolled frame's initial child lists blockFrame->SetInitialChildList(nsnull, childItems.childList); // Set the scroll frame's initial child list newFrame->SetInitialChildList(nsnull, legendFrame ? legendFrame : blockFrame); // our new frame returned is the top frame which is the list frame. - aNewFrame = newFrame; - - // yes we have already initialized our frame - aFrameHasBeenInitialized = PR_TRUE; + *aNewFrame = newFrame; return NS_OK; } static nsIFrame* FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame) { for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) { @@ -5159,300 +4995,319 @@ nsCSSFrameConstructor::ConstructTextFram aFrameItems.AddChild(newFrame); // Text frames don't go in the content->frame hash table, because // they're anonymous. This keeps the hash table smaller return rv; } -nsresult -nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIAtom* aTag, - PRInt32 aNameSpaceID, - nsStyleContext* aStyleContext, - nsFrameItems& aFrameItems, - PRBool aHasPseudoParent) +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindDataByInt(PRInt32 aInt, + nsIContent* aContent, + nsStyleContext* aStyleContext, + const FrameConstructionDataByInt* aDataPtr, + PRUint32 aDataLength) +{ + for (const FrameConstructionDataByInt *curData = aDataPtr, + *endData = aDataPtr + aDataLength; + curData != endData; + ++curData) { + if (curData->mInt == aInt) { + const FrameConstructionData* data = &curData->mData; + if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) { + return data->mFunc.mDataGetter(aContent, aStyleContext); + } + + return data; + } + } + + return nsnull; +} + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindDataByTag(nsIAtom* aTag, + nsIContent* aContent, + nsStyleContext* aStyleContext, + const FrameConstructionDataByTag* aDataPtr, + PRUint32 aDataLength) +{ + for (const FrameConstructionDataByTag *curData = aDataPtr, + *endData = aDataPtr + aDataLength; + curData != endData; + ++curData) { + if (*curData->mTag == aTag) { + const FrameConstructionData* data = &curData->mData; + if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) { + return data->mFunc.mDataGetter(aContent, aStyleContext); + } + + return data; + } + } + + return nsnull; +} + +#define FCDATA_DECL(_flags, _func) \ + { _flags, { (FrameCreationFunc)_func } } +#define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func) +#define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) } +#define SIMPLE_INT_CHAIN(_int, _func) \ + { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) } +#define COMPLEX_INT_CREATE(_int, _func) \ + { _int, { FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func } } + +#define SIMPLE_TAG_CREATE(_tag, _func) \ + { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) } +#define SIMPLE_TAG_CHAIN(_tag, _func) \ + { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) } +#define COMPLEX_TAG_CREATE(_tag, _func) \ + { &nsGkAtoms::_tag, { FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func } } + +/* static */ +const nsCSSFrameConstructor::FrameConstructionDataByInt +nsCSSFrameConstructor::sHTMLInputData[] = { + SIMPLE_INT_CREATE(NS_FORM_INPUT_CHECKBOX, NS_NewGfxCheckboxControlFrame), + SIMPLE_INT_CREATE(NS_FORM_INPUT_RADIO, NS_NewGfxRadioControlFrame), + SIMPLE_INT_CREATE(NS_FORM_INPUT_FILE, NS_NewFileControlFrame), + SIMPLE_INT_CHAIN(NS_FORM_INPUT_IMAGE, + nsCSSFrameConstructor::FindImgControlData), + SIMPLE_INT_CREATE(NS_FORM_INPUT_TEXT, NS_NewTextControlFrame), + SIMPLE_INT_CREATE(NS_FORM_INPUT_PASSWORD, NS_NewTextControlFrame), + COMPLEX_INT_CREATE(NS_FORM_INPUT_SUBMIT, + &nsCSSFrameConstructor::ConstructButtonFrame), + COMPLEX_INT_CREATE(NS_FORM_INPUT_RESET, + &nsCSSFrameConstructor::ConstructButtonFrame), + COMPLEX_INT_CREATE(NS_FORM_INPUT_BUTTON, + &nsCSSFrameConstructor::ConstructButtonFrame) + // Keeping hidden inputs out of here on purpose for so they get frames by + // display (in practice, none). +}; + +/* static */ +const nsCSSFrameConstructor::FrameConstructionDataByInt +nsCSSFrameConstructor::sHTMLObjectData[] = { + SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING, + NS_NewEmptyFrame), + SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_PLUGIN, + NS_NewObjectFrame), + SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_IMAGE, + NS_NewImageFrame), + SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT, + NS_NewSubDocumentFrame) + // Nothing for TYPE_NULL so we'll construct frames by display there +}; + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindObjectData(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + // GetDisplayedType isn't necessarily nsIObjectLoadingContent::TYPE_NULL for + // cases when the object is broken/suppressed/etc (e.g. a broken image), but + // we want to treat those cases as TYPE_NULL + PRUint32 type; + if (aContent->IntrinsicState() & + (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | + NS_EVENT_STATE_SUPPRESSED)) { + type = nsIObjectLoadingContent::TYPE_NULL; + } else { + nsCOMPtr objContent(do_QueryInterface(aContent)); + NS_ASSERTION(objContent, + "applet, embed and object must implement " + "nsIObjectLoadingContent!"); + + objContent->GetDisplayedType(&type); + } + + return FindDataByInt((PRInt32)type, aContent, aStyleContext, + sHTMLObjectData, NS_ARRAY_LENGTH(sHTMLObjectData)); +} + +/* static */ +const nsCSSFrameConstructor::FrameConstructionDataByTag +nsCSSFrameConstructor::sHTMLData[] = { + SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData), + SIMPLE_TAG_CHAIN(mozgeneratedcontentimage, + nsCSSFrameConstructor::FindImgData), + { &nsGkAtoms::br, FCDATA_DECL(FCDATA_SKIP_FRAMEMAP, NS_NewBRFrame) }, + SIMPLE_TAG_CREATE(wbr, NS_NewBRFrame), + SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData), + SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame), + COMPLEX_TAG_CREATE(select, &nsCSSFrameConstructor::ConstructSelectFrame), + SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData), + SIMPLE_TAG_CHAIN(applet, nsCSSFrameConstructor::FindObjectData), + SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData), + COMPLEX_TAG_CREATE(fieldset, &nsCSSFrameConstructor::ConstructFieldSetFrame), + SIMPLE_TAG_CREATE(legend, NS_NewLegendFrame), + SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame), + SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame), + SIMPLE_TAG_CREATE(spacer, NS_NewSpacerFrame), + COMPLEX_TAG_CREATE(button, &nsCSSFrameConstructor::ConstructButtonFrame), + SIMPLE_TAG_CREATE(canvas, NS_NewHTMLCanvasFrame), +#if defined(MOZ_MEDIA) + SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame), + SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame), +#endif + SIMPLE_TAG_CREATE(isindex, NS_NewIsIndexFrame) +}; + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindHTMLData(nsIContent* aContent, + nsIAtom* aTag, + PRInt32 aNameSpaceID, + nsStyleContext* aStyleContext) { // Ignore the tag if it's not HTML content and if it doesn't extend (via XBL) // a valid HTML namespace. This check must match the one in // ShouldHaveFirstLineStyle. if (!aContent->IsNodeOfType(nsINode::eHTML) && aNameSpaceID != kNameSpaceID_XHTML) { - return NS_OK; - } - - PRBool frameHasBeenInitialized = PR_FALSE; - nsIFrame* newFrame = nsnull; // the frame we construct - PRBool addToHashTable = PR_TRUE; - PRBool addedToFrameList = PR_FALSE; - nsresult rv = NS_OK; - - PRBool triedFrame = PR_FALSE; - - // See if the element is absolute or fixed positioned + return nsnull; + } + + return FindDataByTag(aTag, aContent, aStyleContext, sHTMLData, + NS_ARRAY_LENGTH(sHTMLData)); +} + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData +nsCSSFrameConstructor::sHTMLImgData = SIMPLE_FCDATA(NS_NewImageFrame); + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindImgData(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + if (!nsImageFrame::ShouldCreateImageFrameFor(aContent, aStyleContext)) { + return nsnull; + } + + return &sHTMLImgData; +} + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData +nsCSSFrameConstructor::sHTMLImgControlData = + SIMPLE_FCDATA(NS_NewImageControlFrame); + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindImgControlData(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + if (!nsImageFrame::ShouldCreateImageFrameFor(aContent, aStyleContext)) { + return nsnull; + } + + return &sHTMLImgControlData; +} + +/* static */ +const nsCSSFrameConstructor::FrameConstructionData* +nsCSSFrameConstructor::FindInputData(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + nsCOMPtr control = do_QueryInterface(aContent); + NS_ASSERTION(control, "input doesn't implement nsIFormControl?"); + + return FindDataByInt(control->GetType(), aContent, aStyleContext, + sHTMLInputData, NS_ARRAY_LENGTH(sHTMLInputData)); +} + +nsresult +nsCSSFrameConstructor::ConstructFrameFromData(const FrameConstructionData* aData, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsIAtom* aTag, + nsStyleContext* aStyleContext, + nsFrameItems& aFrameItems, + PRBool aHasPseudoParent) +{ + if (!aData) { + // nothing to do + return NS_OK; + } + + PRUint32 bits = aData->mBits; + + NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER), + "Should have dealt with this inside the data finder"); + + // We found something, so not creating by display type. Process + // pseudo-frames now. + if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { + ProcessPseudoFrames(aState, aFrameItems); + } + const nsStyleDisplay* display = aStyleContext->GetStyleDisplay(); - // Create a frame based on the tag - if (nsGkAtoms::img == aTag || nsGkAtoms::mozgeneratedcontentimage == aTag) { - // Make sure to keep IsSpecialContent in synch with this code - rv = CreateHTMLImageFrame(aContent, aStyleContext, NS_NewImageFrame, - &newFrame); - if (newFrame) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - } - } - else if (nsGkAtoms::br == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewBRFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - - // BR frames don't go in the content->frame hash table: typically - // there are many BR content objects and this would increase the size - // of the hash table, and it's doubtful we need the mapping anyway - addToHashTable = PR_FALSE; - } - else if (nsGkAtoms::wbr == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewWBRFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::input == aTag) { - // Make sure to keep IsSpecialContent in synch with this code - rv = CreateInputFrame(aState, aContent, aParentFrame, - aTag, aStyleContext, &newFrame, - display, frameHasBeenInitialized, - addedToFrameList, aFrameItems, - aHasPseudoParent); - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty() && - newFrame && !addedToFrameList) { - // We'll still be adding this new frame, and it's a replaced - // element, so process pseudo-frames now. - ProcessPseudoFrames(aState, aFrameItems); - } - } - else if (nsGkAtoms::textarea == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewTextControlFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::select == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - rv = ConstructSelectFrame(aState, aContent, aParentFrame, - aTag, aStyleContext, newFrame, - display, frameHasBeenInitialized, - aFrameItems); - if (newFrame) { - NS_ASSERTION(nsPlaceholderFrame::GetRealFrameFor(aFrameItems.lastChild) == - newFrame, - "Frame didn't get added to aFrameItems?"); - addedToFrameList = PR_TRUE; - } - } - else if (nsGkAtoms::object == aTag || - nsGkAtoms::applet == aTag || - nsGkAtoms::embed == aTag) { - // Make sure to keep IsSpecialContent in synch with this code - if (!(aContent->IntrinsicState() & - (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | - NS_EVENT_STATE_SUPPRESSED))) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - - nsCOMPtr objContent(do_QueryInterface(aContent)); - NS_ASSERTION(objContent, - "applet, embed and object must implement nsIObjectLoadingContent!"); - if (!objContent) { - // XBL might trigger this... - return NS_ERROR_UNEXPECTED; - } - - PRUint32 type; - objContent->GetDisplayedType(&type); - if (type == nsIObjectLoadingContent::TYPE_LOADING) { - // Ideally, this should show the standby attribute - // XXX Should we return something that is replaced, or make - // nsFrame replaced but not its subclasses? - newFrame = NS_NewEmptyFrame(mPresShell, aStyleContext); - } - else if (type == nsIObjectLoadingContent::TYPE_PLUGIN) - newFrame = NS_NewObjectFrame(mPresShell, aStyleContext); - else if (type == nsIObjectLoadingContent::TYPE_IMAGE) - newFrame = NS_NewImageFrame(mPresShell, aStyleContext); - else if (type == nsIObjectLoadingContent::TYPE_DOCUMENT) - newFrame = NS_NewSubDocumentFrame(mPresShell, aStyleContext); -#ifdef DEBUG - else - NS_ERROR("Shouldn't get here if we're not broken and not " - "suppressed and not blocked"); -#endif - - triedFrame = PR_TRUE; - } - } - else if (nsGkAtoms::fieldset == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - rv = ConstructFieldSetFrame(aState, aContent, aParentFrame, - aTag, aStyleContext, newFrame, - aFrameItems, display, frameHasBeenInitialized); - NS_ASSERTION(nsPlaceholderFrame::GetRealFrameFor(aFrameItems.lastChild) == - newFrame, - "Frame didn't get added to aFrameItems?"); - addedToFrameList = PR_TRUE; - } - else if (nsGkAtoms::legend == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewLegendFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::frameset == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - - newFrame = NS_NewHTMLFramesetFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::iframe == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - - newFrame = NS_NewSubDocumentFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::spacer == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewSpacerFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::button == aTag) { - rv = ConstructButtonFrame(aState, aContent, aParentFrame, - aTag, aStyleContext, &newFrame, - display, aFrameItems, aHasPseudoParent); - // the html4 button needs to act just like a - // regular button except contain html content - // so it must be replaced or html outside it will - // draw into its borders. -EDV - frameHasBeenInitialized = PR_TRUE; - addedToFrameList = PR_TRUE; - } - else if (nsGkAtoms::isindex == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewIsIndexFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } - else if (nsGkAtoms::canvas == aTag) { - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewHTMLCanvasFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } -#if defined(MOZ_MEDIA) - else if (nsGkAtoms::video == aTag || nsGkAtoms::audio == aTag) { - // We create video frames for audio elements so we can show controls. - // Note that html.css specifies display:none for audio elements - // without the "controls" attribute. - if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aFrameItems); - } - newFrame = NS_NewHTMLVideoFrame(mPresShell, aStyleContext); - triedFrame = PR_TRUE; - } -#endif - if (NS_UNLIKELY(triedFrame && !newFrame)) { - return NS_ERROR_OUT_OF_MEMORY; - } - else if (NS_FAILED(rv) || !newFrame) { - return rv; - } - - // If we succeeded in creating a frame then initialize it, process its - // children (if requested), and set the initial child list - - // Note: at this point we should construct kids for newFrame only if - // it's not a leaf and hasn't been initialized yet. - - if (!frameHasBeenInitialized) { - NS_ASSERTION(!addedToFrameList, - "Frames that were already added to the frame list should be " - "initialized by now!"); - nsIFrame* geometricParent = aState.GetGeometricParent(display, - aParentFrame); - - rv = InitAndRestoreFrame(aState, aContent, geometricParent, nsnull, newFrame); + nsIFrame* newFrame; + if (bits & FCDATA_FUNC_IS_FULL_CTOR) { + nsresult rv = + (this->*(aData->mFullConstructor))(aState, aContent, aParentFrame, + aTag, aStyleContext, display, + aFrameItems, &newFrame); + if (NS_FAILED(rv)) { + return rv; + } + } else { + newFrame = + (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext); + if (!newFrame) { + return NS_ERROR_OUT_OF_MEMORY; + } + + PRBool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW); + + nsIFrame* geometricParent = + allowOutOfFlow ? aState.GetGeometricParent(display, aParentFrame) + : aParentFrame; + nsresult rv = InitAndRestoreFrame(aState, aContent, geometricParent, nsnull, + newFrame); NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed"); - // See if we need to create a view + // See whether we need to create a view nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); rv = aState.AddChild(newFrame, aFrameItems, aContent, aStyleContext, - aParentFrame); - if (NS_FAILED(rv)) { - return rv; - } - addedToFrameList = PR_TRUE; - + aParentFrame, allowOutOfFlow, allowOutOfFlow); + if (NS_FAILED(rv)) { + return rv; + } + // Process the child content if requested nsFrameItems childItems; nsFrameConstructorSaveState absoluteSaveState; - if (display->IsPositioned()) { + if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) { + aState.PushAbsoluteContainingBlock(nsnull, absoluteSaveState); + } else if (display->IsPositioned()) { aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState); } // Process the child frames. Don't allow block styles; anything that's a // special HTML frame but wants those should do its own ProcessChildren. rv = ProcessChildren(aState, aContent, aStyleContext, newFrame, PR_TRUE, childItems, PR_FALSE); // Set the frame's initial child list newFrame->SetInitialChildList(nsnull, childItems.childList); } - if (!addedToFrameList) { - // Gotta do it here. Note that things like absolutely positioned replaced - // elements and the like will end up in this code. So use the AddChild - // on the state. - rv = aState.AddChild(newFrame, aFrameItems, aContent, aStyleContext, - aParentFrame); - if (NS_FAILED(rv)) { - return rv; - } - } - - if (addToHashTable) { - // Add a mapping from content object to primary frame. Note that for - // floated and positioned frames this is the out-of-flow frame and not - // the placeholder frame + if (!(bits & FCDATA_SKIP_FRAMEMAP)) { aState.mFrameManager->SetPrimaryFrameFor(aContent, newFrame); } - return rv; + return NS_OK; } nsresult nsCSSFrameConstructor::CreateAnonymousFrames(nsIAtom* aTag, nsFrameConstructorState& aState, nsIContent* aParent, nsIFrame* aNewFrame, nsFrameItems& aChildItems, @@ -7271,18 +7126,20 @@ nsCSSFrameConstructor::ConstructFrameInt // a hint; the paint code will do the right thing in any case. { styleContext->GetStyleBackground(); } nsIFrame* lastChild = frameItems->lastChild; // Handle specific frame types - rv = ConstructHTMLFrame(aState, aContent, adjParentFrame, aTag, aNameSpaceID, - styleContext, *frameItems, pseudoParent); + rv = ConstructFrameFromData(FindHTMLData(aContent, aTag, aNameSpaceID, + styleContext), + aState, aContent, adjParentFrame, aTag, + styleContext, *frameItems, pseudoParent); // Failing to find a matching HTML frame, try creating a specialized // XUL frame. This is temporary, pending planned factoring of this // whole process into separate, pluggable steps. if (NS_SUCCEEDED(rv) && (!frameItems->childList || lastChild == frameItems->lastChild)) { PRBool haltProcessing; @@ -10984,17 +10841,17 @@ nsCSSFrameConstructor::ShouldHaveFirstLi nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext, nsCSSPseudoElements::firstLine, mPresShell->GetPresContext()); if (hasFirstLine) { // But disable for fieldsets PRInt32 namespaceID; nsIAtom* tag = mDocument->BindingManager()->ResolveTag(aContent, &namespaceID); - // This check must match the one in ConstructHTMLFrame. + // This check must match the one in FindHTMLData. hasFirstLine = tag != nsGkAtoms::fieldset || (namespaceID != kNameSpaceID_XHTML && !aContent->IsNodeOfType(nsINode::eHTML)); } return hasFirstLine; } diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -503,16 +503,161 @@ private: nsresult GetParentFrame(PRInt32 aNameSpaceID, nsIFrame& aParentFrameIn, nsIAtom* aChildFrameType, nsFrameConstructorState& aState, nsIFrame*& aParentFrame, PRBool& aIsPseudoParent); +private: + /* A constructor function that just creates an nsIFrame object. The caller + is responsible for initializing the object, adding it to frame lists, + constructing frames for the children, etc. + + @param nsIPresShell the presshell whose arena should be used to allocate + the frame. + @param nsStyleContext the style context to use for the frame. */ + typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*); + + /* A function that can be used to get a FrameConstructionData. Such + a function is allowed to return null. + + @param nsIContent the node for which the frame is being constructed. + @param nsStyleContext the style context to be used for the frame. + */ + struct FrameConstructionData; + typedef const FrameConstructionData* + (* FrameConstructionDataGetter)(nsIContent*, nsStyleContext*); + + /* A constructor function that's used for complicated construction tasks. + This is expected to create the new frame, initialize it, add whatever + needs to be added to aFrameItems (XXXbz is that really necessary? Could + caller add? Might there be cases when *aNewFrame or its placeholder is + not the thing that ends up in aFrameItems? If not, would it be safe to do + the add into the frame construction state after processing kids? Look + into this as a followup!), process children as needed, etc. It is NOT + expected to deal with the primary frame map. + + @param aState the frame construction state to use. + @param aContent the content node to construct the frame for. + @param aParentFrame the frame to set as the parent of the + newly-constructed frame. + @param aTag the content's XBL-resolved tag. + @param aStyleContext the style context to use for the new frame. + @param aFrameItems the frame list to add the new frame (or its + placeholder) to. + @param aFrame out param handing out the frame that was constructed. This + frame is what the caller will add to the primary frame map. + */ + typedef nsresult + (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsIAtom* aTag, + nsStyleContext* aStyleContext, + const nsStyleDisplay* aStyleDisplay, + nsFrameItems& aFrameItems, + nsIFrame** aFrame); + + /* Bits that modify the way a FrameConstructionData is handled */ + + /* If the FCDATA_SKIP_FRAMEMAP bit is set, then the frame created should not + be added to the primary frame map */ +#define FCDATA_SKIP_FRAMEMAP 0x1 + /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the + FrameConstructionData is a getter function that can be used to get the + actual FrameConstructionData to use. */ +#define FCDATA_FUNC_IS_DATA_GETTER 0x2 + /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData + has an mFullConstructor. In this case, there is no relevant mData or + mFunc */ +#define FCDATA_FUNC_IS_FULL_CTOR 0x4 + /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to + float or be absolutely positioned. This cannot be used with + FCDATA_FUNC_IS_FULL_CTOR */ +#define FCDATA_DISALLOW_OUT_OF_FLOW 0x8 + /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a + null absolute containing block before processing children for this + frame. If this is not set, the frame will be pushed as the + absolute containing block as needed, based on its style */ +#define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10 + + /* Structure representing information about how a frame should be + constructed. */ + struct FrameConstructionData { + // Flag bits that can modify the way the construction happens + PRUint32 mBits; + // We have exactly one of three types of functions, so use a union for + // better cache locality for the ones that aren't pointer-to-member. That + // one needs to be separate, because we can't cast between it and the + // others and hence wouldn't be able to initialize the union without a + // constructor and all the resulting generated code. See documentation + // above for FrameCreationFunc, FrameConstructionDataGetter, and + // FrameFullConstructor to see what the functions would do. + union Func { + FrameCreationFunc mCreationFunc; + FrameConstructionDataGetter mDataGetter; + } mFunc; + FrameFullConstructor mFullConstructor; + }; + + /* Structure representing a mapping of an atom to a FrameConstructionData. + This can be used with non-static atoms, assuming that the nsIAtom* is + stored somewhere that this struct can point to (that is, a static + nsIAtom*) and that it's allocated before the struct is ever used. */ + struct FrameConstructionDataByTag { + // Pointer to nsIAtom* is used because we want to initialize this + // statically, so before our atom tables are set up. + const nsIAtom * const * const mTag; + const FrameConstructionData mData; + }; + + /* Structure representing a mapping of an integer to a + FrameConstructionData. There are no magic integer values here. */ + struct FrameConstructionDataByInt { + /* Could be used for display or whatever else */ + const PRInt32 mInt; + const FrameConstructionData mData; + }; + + /* Arrays of the above structs used for HTML frame construction */ + // construction + static const FrameConstructionDataByInt sHTMLInputData[]; + // , , construction + static const FrameConstructionDataByInt sHTMLObjectData[]; + // HTML frame construction + static const FrameConstructionData sHTMLImgData; + // HTML frame construction + static const FrameConstructionData sHTMLImgControlData; + // HTML by-tag frame construction + static const FrameConstructionDataByTag sHTMLData[]; + + /* A function that takes an integer, content, style context, and array of + FrameConstructionDataByInts and finds the appropriate frame construction + data to use and returns it. This can return null if none of the integers + match or if the matching integer has a FrameConstructionDataGetter that + returns null. */ + static const FrameConstructionData* + FindDataByInt(PRInt32 aInt, nsIContent* aContent, + nsStyleContext* aStyleContext, + const FrameConstructionDataByInt* aDataPtr, + PRUint32 aDataLength); + + /* A function that takes a tag, content, style context, and array of + FrameConstructionDataByTags and finds the appropriate frame construction + data to use and returns it. This can return null if none of the tags + match or if the matching tag has a FrameConstructionDataGetter that + returns null. */ + static const FrameConstructionData* + FindDataByTag(nsIAtom* aTag, nsIContent* aContent, + nsStyleContext* aStyleContext, + const FrameConstructionDataByTag* aDataPtr, + PRUint32 aDataLength); + /** * Function to adjust aParentFrame and aFrameItems to deal with table * pseudo-frames that may have to be inserted. * @param aState the nsFrameConstructorState we're using. * @param aChildContent the content node we want to construct a frame for * @param aParentFrame the frame we think should be the parent. This will be * adjusted to point to a pseudo-frame if needed. * @param aTag tag that would be used for frame construction @@ -538,18 +683,16 @@ private: nsIAtom* aTag, PRInt32 aNameSpaceID, nsStyleContext* aChildStyle, nsFrameItems* & aFrameItems, nsFrameConstructorSaveState& aSaveState, PRBool& aSuppressFrame, PRBool& aCreatedPseudo); - const nsStyleDisplay* GetDisplay(nsIFrame* aFrame); - // END TABLE SECTION protected: static nsresult CreatePlaceholderFrameFor(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* aFrame, nsStyleContext* aStyleContext, nsIFrame* aParentFrame, @@ -559,44 +702,41 @@ protected: private: // ConstructButtonFrame puts the new frame in aFrameItems and // handles the kids of the button. nsresult ConstructButtonFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsStyleContext* aStyleContext, - nsIFrame** aNewFrame, const nsStyleDisplay* aStyleDisplay, nsFrameItems& aFrameItems, - PRBool aHasPseudoParent); + nsIFrame** aNewFrame); // ConstructSelectFrame puts the new frame in aFrameItems and // handles the kids of the select. nsresult ConstructSelectFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsStyleContext* aStyleContext, - nsIFrame*& aNewFrame, const nsStyleDisplay* aStyleDisplay, - PRBool& aFrameHasBeenInitialized, - nsFrameItems& aFrameItems); + nsFrameItems& aFrameItems, + nsIFrame** aNewFrame); // ConstructFieldSetFrame puts the new frame in aFrameItems and // handles the kids of the fieldset nsresult ConstructFieldSetFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsStyleContext* aStyleContext, - nsIFrame*& aNewFrame, + const nsStyleDisplay* aStyleDisplay, nsFrameItems& aFrameItems, - const nsStyleDisplay* aStyleDisplay, - PRBool& aFrameHasBeenInitialized); + nsIFrame** aNewFrame); nsresult ConstructTextFrame(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsStyleContext* aStyleContext, nsFrameItems& aFrameItems, PRBool aPseudoParent); @@ -610,24 +750,60 @@ private: // and add it to aFrameItems. Return true if page-break-after:always is set on aStyleContext. // Don't do this for row groups, rows or cell, because tables handle those internally. PRBool PageBreakBefore(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsStyleContext* aStyleContext, nsFrameItems& aFrameItems); - nsresult ConstructHTMLFrame(nsFrameConstructorState& aState, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIAtom* aTag, - PRInt32 aNameSpaceID, - nsStyleContext* aStyleContext, - nsFrameItems& aFrameItems, - PRBool aHasPseudoParent); + static PRBool IsSpecialContent(nsIContent* aContent, + nsIAtom* aTag, + PRInt32 aNameSpaceID, + nsStyleContext* aStyleContext); + + // Function to find FrameConstructionData for aContent. Will return + // null if aContent is not HTML. + static const FrameConstructionData* FindHTMLData(nsIContent* aContent, + nsIAtom* aTag, + PRInt32 aNameSpaceID, + nsStyleContext* aStyleContext); + // HTML data-finding helper functions + static const FrameConstructionData* + FindImgData(nsIContent* aContent, nsStyleContext* aStyleContext); + static const FrameConstructionData* + FindImgControlData(nsIContent* aContent, nsStyleContext* aStyleContext); + static const FrameConstructionData* + FindInputData(nsIContent* aContent, nsStyleContext* aStyleContext); + static const FrameConstructionData* + FindObjectData(nsIContent* aContent, nsStyleContext* aStyleContext); + + /* Construct a frame from the given FrameConstructionData. This function + will handle adding the frame to frame lists, processing children, adding + it to the primary frame map, and so forth. + + @param aData the FrameConstructionData to use. + @param aState the frame construction state to use. + @param aContent the content node to construct the frame for. + @param aParentFrame the frame to set as the parent of the + newly-constructed frame. + @param aTag the content's XBL-resolved tag. + @param aStyleContext the style context to use for the new frame. + @param aFrameItems the frame list to add the new frame (or its + placeholder) to. + @param aHasPseudoParent whether aParentFrame is a table pseudo-frame. + */ + nsresult ConstructFrameFromData(const FrameConstructionData* aData, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsIAtom* aTag, + nsStyleContext* aStyleContext, + nsFrameItems& aFrameItems, + PRBool aHasPseudoParent); nsresult ConstructFrameInternal( nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, PRInt32 aNameSpaceID, nsStyleContext* aStyleContext, nsFrameItems& aFrameItems, @@ -734,43 +910,16 @@ private: nsresult ProcessChildren(nsFrameConstructorState& aState, nsIContent* aContent, nsStyleContext* aStyleContext, nsIFrame* aFrame, PRBool aCanHaveGeneratedContent, nsFrameItems& aFrameItems, PRBool aAllowBlockStyles); - // @param OUT aFrame the newly created frame - nsresult CreateInputFrame(nsFrameConstructorState& aState, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIAtom* aTag, - nsStyleContext* aStyleContext, - nsIFrame** aFrame, - const nsStyleDisplay* aStyleDisplay, - PRBool& aFrameHasBeenInitialized, - PRBool& aAddedToFrameList, - nsFrameItems& aFrameItems, - PRBool aHasPseudoParent); - - // A function that can be invoked to create some sort of image frame. - typedef nsIFrame* (* ImageFrameCreatorFunc)(nsIPresShell*, nsStyleContext*); - - /** - * CreateHTMLImageFrame will do some tests on aContent, and if it determines - * that the content should get an image frame it'll create one via aFunc and - * return it in *aFrame. Note that if this content node isn't supposed to - * have an image frame this method will return NS_OK and set *aFrame to null. - */ - nsresult CreateHTMLImageFrame(nsIContent* aContent, - nsStyleContext* aStyleContext, - ImageFrameCreatorFunc aFunc, - nsIFrame** aFrame); - nsIFrame* GetFrameFor(nsIContent* aContent); /** * These two functions are used when we start frame creation from a non-root * element. They should recreate the same state that we would have * arrived at if we had built frames from the root frame to aFrame. * Therefore, any calls to PushFloatContainingBlock and * PushAbsoluteContainingBlock during frame construction should get