Make sure that Init() failures for image frames don't mean no alt text. Also

fixes a crasher when reframing fixed-pos frames.

This change adds an assertion in ConstructHTMLFrame that InitAndRestoreFrame
should succeed (unless it returns NS_ERROR_FRAME_REPLACED).  This is an interim
change; eventually we want to bail out on errors, but there may be frame impls
that return errors in non-error conditions from Init() (eg nsFrameSetFrame did
that) and we're a little close to freeze.

Bug 202506, r=rbs, sr=roc+moz
This commit is contained in:
bzbarsky%mit.edu 2003-04-21 23:57:47 +00:00
Родитель de711ed4d0
Коммит c72ee5ce87
14 изменённых файлов: 276 добавлений и 176 удалений

Просмотреть файл

@ -1421,10 +1421,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIPresContext* aPresContex
content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
// Create an image frame and initialize it
nsIFrame* imageFrame;
NS_NewImageFrame(shell, &imageFrame);
imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull);
nsIFrame* imageFrame = nsnull;
rv = NS_NewImageFrame(shell, &imageFrame);
if (!imageFrame) {
return rv;
}
rv = imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull);
if (NS_FAILED(rv)) {
imageFrame->Destroy(aPresContext);
return rv == NS_ERROR_FRAME_REPLACED ? NS_OK : rv;
}
// Return the image frame
*aFrame = imageFrame;
@ -4973,69 +4981,89 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell,
}
}
InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame);
rv = InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame);
if (rv == NS_ERROR_FRAME_REPLACED) {
// The frame called CantRenderReplacedElement from inside Init(). That
// failed to do anything useful, since the frame was not in the frame
// tree yet... Create an alternate frame ourselves
newFrame->Destroy(aPresContext);
// See if we need to create a view, e.g. the frame is absolutely
// positioned
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, aParentFrame, PR_FALSE);
if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) {
// XXXbz This should really be made to work for <object> too...
return NS_OK;
}
// Process the child content if requested
nsFrameItems childItems;
if (processChildren) {
if (isPositionedContainingBlock) {
// The area frame becomes a container for child frames that are
// absolutely positioned
nsFrameConstructorSaveState absoluteSaveState;
aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState);
// Try to construct the alternate frame
newFrame = nsnull;
rv = ConstructAlternateFrame(aPresShell, aPresContext, aContent,
aStyleContext, geometricParent,
aParentFrame, newFrame);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking");
} else {
NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed");
// See if we need to create a view, e.g. the frame is absolutely
// positioned
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, aParentFrame, PR_FALSE);
// Process the child content if requested
nsFrameItems childItems;
if (processChildren) {
if (isPositionedContainingBlock) {
// The area frame becomes a container for child frames that are
// absolutely positioned
nsFrameConstructorSaveState absoluteSaveState;
aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Set the frame's absolute list if there were any absolutely positioned children
if (aState.mAbsoluteItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::absoluteList,
aState.mAbsoluteItems.childList);
// Set the frame's absolute list if there were any absolutely positioned children
if (aState.mAbsoluteItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::absoluteList,
aState.mAbsoluteItems.childList);
}
}
else if (isFloaterContainer) {
// If the frame can contain floaters, then push a floater
// containing block
PRBool haveFirstLetterStyle, haveFirstLineStyle;
HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext,
&haveFirstLetterStyle, &haveFirstLineStyle);
nsFrameConstructorSaveState floaterSaveState;
aState.PushFloaterContainingBlock(newFrame, floaterSaveState,
PR_FALSE, PR_FALSE);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Set the frame's floater list if there were any floated children
if (aState.mFloatedItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::floaterList,
aState.mFloatedItems.childList);
}
} else {
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
}
}
else if (isFloaterContainer) {
// If the frame can contain floaters, then push a floater
// containing block
PRBool haveFirstLetterStyle, haveFirstLineStyle;
HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext,
&haveFirstLetterStyle, &haveFirstLineStyle);
nsFrameConstructorSaveState floaterSaveState;
aState.PushFloaterContainingBlock(newFrame, floaterSaveState,
PR_FALSE, PR_FALSE);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Set the frame's floater list if there were any floated children
if (aState.mFloatedItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::floaterList,
aState.mFloatedItems.childList);
}
} else {
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// if there are any anonymous children create frames for them
CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame,
PR_FALSE, childItems);
// Set the frame's initial child list
if (childItems.childList) {
newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
}
}
// if there are any anonymous children create frames for them
CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame,
PR_FALSE, childItems);
// Set the frame's initial child list
if (childItems.childList) {
newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
}
}
// If the frame is positioned, then create a placeholder frame
@ -10757,7 +10785,8 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsIContent* aContent,
nsStyleContext* aStyleContext,
nsIFrame* aParentFrame,
nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame)
{
nsresult rv;
@ -10802,9 +10831,10 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
} else {
NS_NewInlineFrame(aPresShell, &containerFrame);
}
containerFrame->Init(aPresContext, aContent, aParentFrame, aStyleContext, nsnull);
containerFrame->Init(aPresContext, aContent, aGeometricParent, aStyleContext, nsnull);
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame,
aStyleContext, nsnull, PR_FALSE);
aStyleContext, aContentParent,
PR_FALSE);
// If the frame is out-of-flow, then mark it as such
if (isOutOfFlow) {
@ -10942,7 +10972,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
// image can't be rendered
nsIFrame* newFrame;
rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext,
parentFrame, newFrame);
parentFrame, nsnull, newFrame);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFrameManager> frameManager;
@ -10956,6 +10986,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
frameManager->SetPrimaryFrameFor(content, newFrame);
// Replace the old frame with the new frame
// XXXbz If this fails, we leak the content node newFrame points to!
frameManager->ReplaceFrame(aPresContext, *presShell, parentFrame,
listName, aFrame, newFrame);
@ -12035,11 +12066,21 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext,
// state onto a temporary state object.
CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState);
// Save parent frame because this frame is going away
// Save parent frame because this frame is going away. But if
// this is an out-of-flow, we want to get the _placeholder_'s
// parent.
nsIFrame* parent = nsnull;
if (frame)
frame->GetParent(&parent);
if (frame) {
nsFrameState state;
frame->GetFrameState(&state);
if (state & NS_FRAME_OUT_OF_FLOW) {
shell->GetPlaceholderFrameFor(frame, &frame);
NS_ASSERTION(frame, "Out-of-flow with no placeholder?");
}
frame->GetParent(&parent);
}
// Remove the frames associated with the content object on which the
// attribute change occurred.
rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE);

Просмотреть файл

@ -472,7 +472,8 @@ protected:
nsIPresContext* aPresContext,
nsIContent* aContent,
nsStyleContext* aStyleContext,
nsIFrame* aParentFrame,
nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame);
nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext,

Просмотреть файл

@ -56,4 +56,8 @@
#define NS_POSITION_BEFORE_TABLE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 3)
/** Error code to return from nsIFrame::Init() if the frame got
replaced by alt text or something like that **/
#define NS_ERROR_FRAME_REPLACED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LAYOUT, 4)
#endif // nsLayoutErrors_h___

Просмотреть файл

@ -56,4 +56,8 @@
#define NS_POSITION_BEFORE_TABLE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 3)
/** Error code to return from nsIFrame::Init() if the frame got
replaced by alt text or something like that **/
#define NS_ERROR_FRAME_REPLACED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LAYOUT, 4)
#endif // nsLayoutErrors_h___

Просмотреть файл

@ -326,15 +326,15 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// find the highest ancestor that is a frameset
nsresult rv = NS_OK;
nsIFrame* parentFrame = nsnull;
GetParent((nsIFrame**)&parentFrame);
GetParent(&parentFrame);
mTopLevelFrameset = (nsHTMLFramesetFrame*)this;
while (parentFrame) {
nsHTMLFramesetFrame* frameset;
rv = parentFrame->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame),
(void**)&frameset);
if (NS_SUCCEEDED(rv)) {
nsHTMLFramesetFrame* frameset = nsnull;
CallQueryInterface(parentFrame, &frameset);
if (frameset) {
mTopLevelFrameset = frameset;
parentFrame->GetParent((nsIFrame**)&parentFrame);
parentFrame->GetParent(&parentFrame);
} else {
break;
}
@ -342,8 +342,7 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// create the view. a view is needed since it needs to be a mouse grabber
nsIView* view;
nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView),
(void **)&view);
nsresult result = CallCreateInstance(kViewCID, &view);
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIViewManager> viewMan;

Просмотреть файл

@ -98,6 +98,8 @@
#include "nsIPrefService.h"
#include "gfxIImageFrame.h"
#include "nsLayoutErrors.h"
#ifdef DEBUG
#undef NOISY_IMAGE_LOADING
#undef NOISY_ICON_LOADING
@ -320,8 +322,8 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
PRBool loadBlocked = PR_FALSE;
imageLoader->GetImageBlocked(&loadBlocked);
HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE,
presShell);
rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE,
presShell);
}
return rv;
@ -425,14 +427,14 @@ nsImageFrame::ConvertPxRectToTwips(const nsRect& aRect) const
NSIntPixelsToTwips(aRect.height, p2t)); // height
}
void
nsresult
nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
{
if (aStatus == NS_ERROR_IMAGE_BLOCKED &&
!(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) {
// don't display any alt feedback in this case; we're blocking images
// from that site and don't care to see anything from them
return;
return NS_OK;
}
// If we have an image map, don't do anything here
@ -442,7 +444,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
nsAutoString usemap;
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap);
if (!usemap.IsEmpty()) {
return;
return NS_OK;
}
// check if we want to honor the ALT text in the IMG frame, or let the preShell make it into inline text
@ -465,7 +467,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
// check for style property that indicates the icon should always be shown
const nsStyleUIReset* styleData;
GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData);
::GetStyleData(this, &styleData);
if (styleData->mForceBrokenImageIcon) {
forceIcon = PR_TRUE;
}
@ -489,11 +491,13 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame);
aPresShell->CantRenderReplacedElement(mPresContext,
primaryFrame ? primaryFrame : this);
} else {
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
return NS_ERROR_FRAME_REPLACED;
}
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
return NS_OK;
}
nsresult

Просмотреть файл

@ -233,9 +233,10 @@ private:
/**
* Function to call when a load fails; this handles things like alt
* text, broken image icons, etc
* text, broken image icons, etc. Returns NS_ERROR_FRAME_REPLACED
* if it called CantRenderReplacedElement, NS_OK otherwise.
*/
void HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell);
nsresult HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell);
nsImageMap* mImageMap;

Просмотреть файл

@ -638,13 +638,13 @@ nsObjectFrame::Init(nsIPresContext* aPresContext,
aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame * aNewFrame = nsnull;
rv = NS_NewImageFrame(shell, &aNewFrame);
if(rv != NS_OK)
if (NS_FAILED(rv))
return rv;
// XXX we're using the same style context for ourselves and the
// image frame. If this ever changes, please fix HandleChild() to deal.
rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow);
if(rv == NS_OK)
if (NS_SUCCEEDED(rv))
{
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE);
mFrames.AppendFrame(this, aNewFrame);

Просмотреть файл

@ -98,6 +98,8 @@
#include "nsIPrefService.h"
#include "gfxIImageFrame.h"
#include "nsLayoutErrors.h"
#ifdef DEBUG
#undef NOISY_IMAGE_LOADING
#undef NOISY_ICON_LOADING
@ -320,8 +322,8 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
PRBool loadBlocked = PR_FALSE;
imageLoader->GetImageBlocked(&loadBlocked);
HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE,
presShell);
rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE,
presShell);
}
return rv;
@ -425,14 +427,14 @@ nsImageFrame::ConvertPxRectToTwips(const nsRect& aRect) const
NSIntPixelsToTwips(aRect.height, p2t)); // height
}
void
nsresult
nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
{
if (aStatus == NS_ERROR_IMAGE_BLOCKED &&
!(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) {
// don't display any alt feedback in this case; we're blocking images
// from that site and don't care to see anything from them
return;
return NS_OK;
}
// If we have an image map, don't do anything here
@ -442,7 +444,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
nsAutoString usemap;
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap);
if (!usemap.IsEmpty()) {
return;
return NS_OK;
}
// check if we want to honor the ALT text in the IMG frame, or let the preShell make it into inline text
@ -465,7 +467,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
// check for style property that indicates the icon should always be shown
const nsStyleUIReset* styleData;
GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData);
::GetStyleData(this, &styleData);
if (styleData->mForceBrokenImageIcon) {
forceIcon = PR_TRUE;
}
@ -489,11 +491,13 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame);
aPresShell->CantRenderReplacedElement(mPresContext,
primaryFrame ? primaryFrame : this);
} else {
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
return NS_ERROR_FRAME_REPLACED;
}
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
return NS_OK;
}
nsresult

Просмотреть файл

@ -233,9 +233,10 @@ private:
/**
* Function to call when a load fails; this handles things like alt
* text, broken image icons, etc
* text, broken image icons, etc. Returns NS_ERROR_FRAME_REPLACED
* if it called CantRenderReplacedElement, NS_OK otherwise.
*/
void HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell);
nsresult HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell);
nsImageMap* mImageMap;

Просмотреть файл

@ -638,13 +638,13 @@ nsObjectFrame::Init(nsIPresContext* aPresContext,
aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame * aNewFrame = nsnull;
rv = NS_NewImageFrame(shell, &aNewFrame);
if(rv != NS_OK)
if (NS_FAILED(rv))
return rv;
// XXX we're using the same style context for ourselves and the
// image frame. If this ever changes, please fix HandleChild() to deal.
rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow);
if(rv == NS_OK)
if (NS_SUCCEEDED(rv))
{
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE);
mFrames.AppendFrame(this, aNewFrame);

Просмотреть файл

@ -326,15 +326,15 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// find the highest ancestor that is a frameset
nsresult rv = NS_OK;
nsIFrame* parentFrame = nsnull;
GetParent((nsIFrame**)&parentFrame);
GetParent(&parentFrame);
mTopLevelFrameset = (nsHTMLFramesetFrame*)this;
while (parentFrame) {
nsHTMLFramesetFrame* frameset;
rv = parentFrame->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame),
(void**)&frameset);
if (NS_SUCCEEDED(rv)) {
nsHTMLFramesetFrame* frameset = nsnull;
CallQueryInterface(parentFrame, &frameset);
if (frameset) {
mTopLevelFrameset = frameset;
parentFrame->GetParent((nsIFrame**)&parentFrame);
parentFrame->GetParent(&parentFrame);
} else {
break;
}
@ -342,8 +342,7 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// create the view. a view is needed since it needs to be a mouse grabber
nsIView* view;
nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView),
(void **)&view);
nsresult result = CallCreateInstance(kViewCID, &view);
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIViewManager> viewMan;

Просмотреть файл

@ -1421,10 +1421,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIPresContext* aPresContex
content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
// Create an image frame and initialize it
nsIFrame* imageFrame;
NS_NewImageFrame(shell, &imageFrame);
imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull);
nsIFrame* imageFrame = nsnull;
rv = NS_NewImageFrame(shell, &imageFrame);
if (!imageFrame) {
return rv;
}
rv = imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull);
if (NS_FAILED(rv)) {
imageFrame->Destroy(aPresContext);
return rv == NS_ERROR_FRAME_REPLACED ? NS_OK : rv;
}
// Return the image frame
*aFrame = imageFrame;
@ -4973,69 +4981,89 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell,
}
}
InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame);
rv = InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame);
if (rv == NS_ERROR_FRAME_REPLACED) {
// The frame called CantRenderReplacedElement from inside Init(). That
// failed to do anything useful, since the frame was not in the frame
// tree yet... Create an alternate frame ourselves
newFrame->Destroy(aPresContext);
// See if we need to create a view, e.g. the frame is absolutely
// positioned
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, aParentFrame, PR_FALSE);
if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) {
// XXXbz This should really be made to work for <object> too...
return NS_OK;
}
// Process the child content if requested
nsFrameItems childItems;
if (processChildren) {
if (isPositionedContainingBlock) {
// The area frame becomes a container for child frames that are
// absolutely positioned
nsFrameConstructorSaveState absoluteSaveState;
aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState);
// Try to construct the alternate frame
newFrame = nsnull;
rv = ConstructAlternateFrame(aPresShell, aPresContext, aContent,
aStyleContext, geometricParent,
aParentFrame, newFrame);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking");
} else {
NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed");
// See if we need to create a view, e.g. the frame is absolutely
// positioned
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, aParentFrame, PR_FALSE);
// Process the child content if requested
nsFrameItems childItems;
if (processChildren) {
if (isPositionedContainingBlock) {
// The area frame becomes a container for child frames that are
// absolutely positioned
nsFrameConstructorSaveState absoluteSaveState;
aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Set the frame's absolute list if there were any absolutely positioned children
if (aState.mAbsoluteItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::absoluteList,
aState.mAbsoluteItems.childList);
// Set the frame's absolute list if there were any absolutely positioned children
if (aState.mAbsoluteItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::absoluteList,
aState.mAbsoluteItems.childList);
}
}
else if (isFloaterContainer) {
// If the frame can contain floaters, then push a floater
// containing block
PRBool haveFirstLetterStyle, haveFirstLineStyle;
HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext,
&haveFirstLetterStyle, &haveFirstLineStyle);
nsFrameConstructorSaveState floaterSaveState;
aState.PushFloaterContainingBlock(newFrame, floaterSaveState,
PR_FALSE, PR_FALSE);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Set the frame's floater list if there were any floated children
if (aState.mFloatedItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::floaterList,
aState.mFloatedItems.childList);
}
} else {
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
}
}
else if (isFloaterContainer) {
// If the frame can contain floaters, then push a floater
// containing block
PRBool haveFirstLetterStyle, haveFirstLineStyle;
HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext,
&haveFirstLetterStyle, &haveFirstLineStyle);
nsFrameConstructorSaveState floaterSaveState;
aState.PushFloaterContainingBlock(newFrame, floaterSaveState,
PR_FALSE, PR_FALSE);
// Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// Set the frame's floater list if there were any floated children
if (aState.mFloatedItems.childList) {
newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::floaterList,
aState.mFloatedItems.childList);
}
} else {
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE);
// if there are any anonymous children create frames for them
CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame,
PR_FALSE, childItems);
// Set the frame's initial child list
if (childItems.childList) {
newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
}
}
// if there are any anonymous children create frames for them
CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame,
PR_FALSE, childItems);
// Set the frame's initial child list
if (childItems.childList) {
newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
}
}
// If the frame is positioned, then create a placeholder frame
@ -10757,7 +10785,8 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsIContent* aContent,
nsStyleContext* aStyleContext,
nsIFrame* aParentFrame,
nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame)
{
nsresult rv;
@ -10802,9 +10831,10 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
} else {
NS_NewInlineFrame(aPresShell, &containerFrame);
}
containerFrame->Init(aPresContext, aContent, aParentFrame, aStyleContext, nsnull);
containerFrame->Init(aPresContext, aContent, aGeometricParent, aStyleContext, nsnull);
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame,
aStyleContext, nsnull, PR_FALSE);
aStyleContext, aContentParent,
PR_FALSE);
// If the frame is out-of-flow, then mark it as such
if (isOutOfFlow) {
@ -10942,7 +10972,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
// image can't be rendered
nsIFrame* newFrame;
rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext,
parentFrame, newFrame);
parentFrame, nsnull, newFrame);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFrameManager> frameManager;
@ -10956,6 +10986,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
frameManager->SetPrimaryFrameFor(content, newFrame);
// Replace the old frame with the new frame
// XXXbz If this fails, we leak the content node newFrame points to!
frameManager->ReplaceFrame(aPresContext, *presShell, parentFrame,
listName, aFrame, newFrame);
@ -12035,11 +12066,21 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext,
// state onto a temporary state object.
CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState);
// Save parent frame because this frame is going away
// Save parent frame because this frame is going away. But if
// this is an out-of-flow, we want to get the _placeholder_'s
// parent.
nsIFrame* parent = nsnull;
if (frame)
frame->GetParent(&parent);
if (frame) {
nsFrameState state;
frame->GetFrameState(&state);
if (state & NS_FRAME_OUT_OF_FLOW) {
shell->GetPlaceholderFrameFor(frame, &frame);
NS_ASSERTION(frame, "Out-of-flow with no placeholder?");
}
frame->GetParent(&parent);
}
// Remove the frames associated with the content object on which the
// attribute change occurred.
rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE);

Просмотреть файл

@ -472,7 +472,8 @@ protected:
nsIPresContext* aPresContext,
nsIContent* aContent,
nsStyleContext* aStyleContext,
nsIFrame* aParentFrame,
nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame);
nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext,