Bug 243519. Rework root element frame construction and the CanvasFrame so that the CanvasFrame is an abs-pos container and the root element frame can be positioned. r=fantasai,sr=dbaron

This commit is contained in:
Robert O'Callahan 2008-09-06 21:35:05 +12:00
Родитель c04d96c610
Коммит c2ca6a7204
48 изменённых файлов: 769 добавлений и 367 удалений

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

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="position:absolute;">Hello</div>
<div style="position:fixed;">Kitty</div>
<script>
document.body.offsetTop;
document.documentElement.style.display = "table";
document.body.offsetTop;
document.documentElement..style.display = "";
document.body.offsetTop;
document.documentElement.style.position = "absolute";
document.body.offsetTop;
document.documentElement.style.display = "table";
document.body.offsetTop;
document.documentElement..style.display = "";
document.body.offsetTop;
document.documentElement.style.position = "fixed";
document.body.offsetTop;
document.documentElement.style.display = "table";
document.body.offsetTop;
document.documentElement..style.display = "";
</script>
</body>
</html>

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

@ -3,6 +3,7 @@ load 143862-1.html
load 143862-2.html load 143862-2.html
load 243159-1.html load 243159-1.html
load 243159-2.xhtml load 243159-2.xhtml
load 243519-1.html
load 306940-1.html load 306940-1.html
load 310267-1.xml load 310267-1.xml
load 310638-1.svg load 310638-1.svg

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

@ -1806,9 +1806,9 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument,
, mUpdateCount(0) , mUpdateCount(0)
, mQuotesDirty(PR_FALSE) , mQuotesDirty(PR_FALSE)
, mCountersDirty(PR_FALSE) , mCountersDirty(PR_FALSE)
, mInitialContainingBlockIsAbsPosContainer(PR_FALSE)
, mIsDestroyingFrameTree(PR_FALSE) , mIsDestroyingFrameTree(PR_FALSE)
, mRebuildAllStyleData(PR_FALSE) , mRebuildAllStyleData(PR_FALSE)
, mHasRootAbsPosContainingBlock(PR_FALSE)
{ {
if (!gGotXBLFormPrefs) { if (!gGotXBLFormPrefs) {
gGotXBLFormPrefs = PR_TRUE; gGotXBLFormPrefs = PR_TRUE;
@ -3972,32 +3972,6 @@ nsCSSFrameConstructor::GetDisplay(nsIFrame* aFrame)
* END TABLE SECTION * END TABLE SECTION
***********************************************/ ***********************************************/
nsresult
nsCSSFrameConstructor::ConstructDocElementTableFrame(nsIContent* aDocElement,
nsIFrame* aParentFrame,
nsIFrame** aNewTableFrame,
nsFrameConstructorState& aState)
{
nsFrameItems frameItems;
// XXXbz this is wrong. We should at least be setting the fixed container in
// the framestate here. Better yet, we should pass through aState
// unmodified. Can't do that, though, because then a fixed or absolute
// positioned root table with auto offsets would look for a block to compute
// its hypothetical box and crash. So we just disable fixed positioning
// altogether in documents where the root is a table. Oh, well.
nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull,
aState.mFrameState);
ConstructFrame(state, aDocElement, aParentFrame, frameItems);
*aNewTableFrame = frameItems.childList;
if (!*aNewTableFrame) {
NS_WARNING("cannot get table contentFrame");
// XXXbz maybe better to return the error from ConstructFrame?
return NS_ERROR_FAILURE;
}
return NS_OK;
}
static PRBool CheckOverflow(nsPresContext* aPresContext, static PRBool CheckOverflow(nsPresContext* aPresContext,
const nsStyleDisplay* aDisplay) const nsStyleDisplay* aDisplay)
{ {
@ -4093,29 +4067,6 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
nsIFrame* aParentFrame, nsIFrame* aParentFrame,
nsIFrame** aNewFrame) nsIFrame** aNewFrame)
{ {
// how the root frame hierarchy should look
/*
---------------No Scrollbars------
AreaFrame or BoxFrame (InitialContainingBlock)
---------------Gfx Scrollbars ------
ScrollFrame
^
|
|
AreaFrame or BoxFrame (InitialContainingBlock)
*/
*aNewFrame = nsnull; *aNewFrame = nsnull;
if (!mTempFrameTreeState) if (!mTempFrameTreeState)
@ -4189,8 +4140,13 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
"Scrollbars should have been propagated to the viewport"); "Scrollbars should have been propagated to the viewport");
#endif #endif
nsIFrame* contentFrame = nsnull; nsFrameConstructorSaveState absoluteSaveState;
PRBool isBlockFrame = PR_FALSE; if (mHasRootAbsPosContainingBlock) {
// Push the absolute containing block now so we can absolutely position
// the root element
aState.PushAbsoluteContainingBlock(mDocElementContainingBlock, absoluteSaveState);
}
nsresult rv; nsresult rv;
// The rules from CSS 2.1, section 9.2.4, have already been applied // The rules from CSS 2.1, section 9.2.4, have already been applied
@ -4202,19 +4158,40 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
aDocElement->GetNameSpaceID(), aDocElement->GetNameSpaceID(),
styleContext); styleContext);
// contentFrame is the primary frame for the root element. *aNewFrame
// is the frame that will be the child of the initial containing block.
// These are usually the same frame but they can be different, in
// particular if the root frame is positioned, in which case
// contentFrame is the out-of-flow frame and *aNewFrame is the
// placeholder.
nsIFrame* contentFrame;
PRBool processChildren = PR_FALSE;
if (docElemIsTable) { if (docElemIsTable) {
nsIFrame* innerTableFrame;
nsFrameItems frameItems;
// if the document is a table then just populate it. // if the document is a table then just populate it.
rv = ConstructDocElementTableFrame(aDocElement, aParentFrame, &contentFrame, rv = ConstructTableFrame(aState, aDocElement,
aState); aParentFrame, styleContext,
if (NS_FAILED(rv)) { kNameSpaceID_None, PR_FALSE, frameItems, contentFrame,
innerTableFrame);
if (NS_FAILED(rv))
return rv; return rv;
} if (!contentFrame || !frameItems.childList)
styleContext = contentFrame->GetStyleContext(); return NS_ERROR_FAILURE;
*aNewFrame = frameItems.childList;
NS_ASSERTION(!frameItems.childList->GetNextSibling(),
"multiple root element frames");
} else { } else {
// otherwise build a box or a block // otherwise build a box or a block
#ifdef MOZ_XUL #ifdef MOZ_XUL
if (aDocElement->IsNodeOfType(nsINode::eXUL)) { if (aDocElement->IsNodeOfType(nsINode::eXUL)) {
contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext); contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext);
if (NS_UNLIKELY(!contentFrame)) {
return NS_ERROR_OUT_OF_MEMORY;
}
InitAndRestoreFrame(aState, aDocElement, aParentFrame, nsnull, contentFrame);
*aNewFrame = contentFrame;
processChildren = PR_TRUE;
} }
else else
#endif #endif
@ -4222,6 +4199,26 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
if (aDocElement->GetNameSpaceID() == kNameSpaceID_SVG) { if (aDocElement->GetNameSpaceID() == kNameSpaceID_SVG) {
if (aDocElement->Tag() == nsGkAtoms::svg && NS_SVGEnabled()) { if (aDocElement->Tag() == nsGkAtoms::svg && NS_SVGEnabled()) {
contentFrame = NS_NewSVGOuterSVGFrame(mPresShell, aDocElement, styleContext); contentFrame = NS_NewSVGOuterSVGFrame(mPresShell, aDocElement, styleContext);
if (NS_UNLIKELY(!contentFrame)) {
return NS_ERROR_OUT_OF_MEMORY;
}
InitAndRestoreFrame(aState, aDocElement,
aState.GetGeometricParent(display, aParentFrame),
nsnull, contentFrame);
// AddChild takes care of transforming the frame tree for fixed-pos
// or abs-pos situations
nsFrameItems frameItems;
rv = aState.AddChild(contentFrame, frameItems, aDocElement,
styleContext, aParentFrame);
if (NS_FAILED(rv) || !frameItems.childList) {
return rv;
}
*aNewFrame = frameItems.childList;
processChildren = PR_TRUE;
// See if we need to create a view, e.g. the frame is absolutely positioned
nsHTMLContainerFrame::CreateViewForFrame(contentFrame, aParentFrame, PR_FALSE);
} else { } else {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -4229,25 +4226,27 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
else else
#endif #endif
{ {
contentFrame = NS_NewDocumentElementFrame(mPresShell, styleContext); contentFrame = NS_NewBlockFrame(mPresShell, styleContext,
isBlockFrame = PR_TRUE; NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
if (!contentFrame)
return NS_ERROR_OUT_OF_MEMORY;
nsFrameItems frameItems;
rv = ConstructBlock(aState, display, aDocElement,
aState.GetGeometricParent(display, aParentFrame),
aParentFrame, styleContext, &contentFrame,
frameItems, display->IsPositioned());
if (NS_FAILED(rv) || !frameItems.childList)
return rv;
*aNewFrame = frameItems.childList;
NS_ASSERTION(!frameItems.childList->GetNextSibling(),
"multiple root element frames");
} }
if (NS_UNLIKELY(!contentFrame)) {
return NS_ERROR_OUT_OF_MEMORY;
}
// initialize the child
InitAndRestoreFrame(aState, aDocElement, aParentFrame, nsnull, contentFrame);
} }
// set the primary frame // set the primary frame
aState.mFrameManager->SetPrimaryFrameFor(aDocElement, contentFrame); aState.mFrameManager->SetPrimaryFrameFor(aDocElement, contentFrame);
*aNewFrame = contentFrame;
mInitialContainingBlock = contentFrame; mInitialContainingBlock = contentFrame;
mInitialContainingBlockIsAbsPosContainer = PR_FALSE;
// Figure out which frame has the main style for the document element, // Figure out which frame has the main style for the document element,
// assigning it to mRootElementStyleFrame. // assigning it to mRootElementStyleFrame.
@ -4259,31 +4258,19 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
mRootElementStyleFrame = mInitialContainingBlock; mRootElementStyleFrame = mInitialContainingBlock;
} }
// if it was a table then we don't need to process our children. if (processChildren) {
if (!docElemIsTable) { // Still need to process the child content
// Process the child content nsFrameItems childItems;
nsFrameConstructorSaveState absoluteSaveState;
nsFrameConstructorSaveState floatSaveState;
nsFrameItems childItems;
if (isBlockFrame) {
PRBool haveFirstLetterStyle, haveFirstLineStyle;
ShouldHaveSpecialBlockStyle(aDocElement, styleContext,
&haveFirstLetterStyle, &haveFirstLineStyle);
mInitialContainingBlockIsAbsPosContainer = PR_TRUE;
aState.PushAbsoluteContainingBlock(contentFrame, absoluteSaveState);
aState.PushFloatContainingBlock(contentFrame, floatSaveState,
haveFirstLetterStyle,
haveFirstLineStyle);
}
// Create any anonymous frames the doc element frame requires // Create any anonymous frames the doc element frame requires
// This must happen before ProcessChildren to ensure that popups are // This must happen before ProcessChildren to ensure that popups are
// never constructed before the popupset. // never constructed before the popupset.
CreateAnonymousFrames(nsnull, aState, aDocElement, contentFrame, CreateAnonymousFrames(nsnull, aState, aDocElement, contentFrame,
PR_FALSE, childItems, PR_TRUE); PR_FALSE, childItems, PR_TRUE);
NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame),
"Only XUL and SVG frames should reach here");
ProcessChildren(aState, aDocElement, contentFrame, PR_TRUE, childItems, ProcessChildren(aState, aDocElement, contentFrame, PR_TRUE, childItems,
isBlockFrame); PR_FALSE);
// Set the initial child lists // Set the initial child lists
contentFrame->SetInitialChildList(nsnull, childItems.childList); contentFrame->SetInitialChildList(nsnull, childItems.childList);
@ -4300,35 +4287,61 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement,
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC); AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
NS_PRECONDITION(aNewFrame, "null out param"); NS_PRECONDITION(aNewFrame, "null out param");
// how the root frame hierarchy should look
/* /*
how the root frame hierarchy should look
---------------No Scrollbars------ Galley presentation, non-XUL, with scrolling (i.e. not a frameset):
ViewportFrame [fixed-cb]
nsHTMLScrollFrame
CanvasFrame [abs-cb]
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
nsTableOuterFrame, nsPlaceholderFrame)
Galley presentation, non-XUL, without scrolling (i.e. a frameset):
ViewPortFrame (FixedContainingBlock) <---- RootView ViewportFrame [fixed-cb]
CanvasFrame [abs-cb]
root element frame (nsBlockFrame)
^ Galley presentation, XUL
|
RootFrame(DocElementContainingBlock)
ViewportFrame [fixed-cb]
nsRootBoxFrame
root element frame (nsDocElementBoxFrame)
Print presentation, non-XUL
---------------Gfx Scrollbars ------ ViewportFrame
nsSimplePageSequenceFrame
nsPageFrame [fixed-cb]
nsPageContentFrame
CanvasFrame [abs-cb]
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
nsTableOuterFrame, nsPlaceholderFrame)
Print-preview presentation, non-XUL
ViewPortFrame (FixedContainingBlock) <---- RootView ViewportFrame
nsHTMLScrollFrame
nsSimplePageSequenceFrame
nsPageFrame [fixed-cb]
nsPageContentFrame
CanvasFrame [abs-cb]
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
nsTableOuterFrame, nsPlaceholderFrame)
^ Print/print preview of XUL is not supported.
| [fixed-cb]: the default containing block for fixed-pos content
ScrollFrame [abs-cb]: the default containing block for abs-pos content
^
|
RootFrame(DocElementContainingBlock)
Meaning of nsCSSFrameConstructor fields:
mInitialContainingBlock is "root element frame".
mDocElementContainingBlock is the parent of mInitialContainingBlock
(i.e. CanvasFrame or nsRootBoxFrame)
mFixedContainingBlock is the [fixed-cb]
mGfxScrollFrame is the nsHTMLScrollFrame mentioned above, or null if there isn't one
mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't one
*/ */
// Set up our style rule observer. // Set up our style rule observer.
@ -4394,6 +4407,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement,
{ {
// pass a temporary stylecontext, the correct one will be set later // pass a temporary stylecontext, the correct one will be set later
rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle); rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
mHasRootAbsPosContainingBlock = PR_TRUE;
} }
rootPseudo = nsCSSAnonBoxes::canvas; rootPseudo = nsCSSAnonBoxes::canvas;
@ -4522,14 +4536,15 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement,
if (isPaginated) { // paginated if (isPaginated) { // paginated
// Create the first page // Create the first page
// Set the initial child lists // Set the initial child lists
nsIFrame *pageFrame, *pageContentFrame; nsIFrame *pageFrame, *canvasFrame;
ConstructPageFrame(mPresShell, presContext, rootFrame, nsnull, ConstructPageFrame(mPresShell, presContext, rootFrame, nsnull,
pageFrame, pageContentFrame); pageFrame, canvasFrame);
rootFrame->SetInitialChildList(nsnull, pageFrame); rootFrame->SetInitialChildList(nsnull, pageFrame);
// The eventual parent of the document element frame. // The eventual parent of the document element frame.
// XXX should this be set for every new page (in ConstructPageFrame)? // XXX should this be set for every new page (in ConstructPageFrame)?
mDocElementContainingBlock = pageContentFrame; mDocElementContainingBlock = canvasFrame;
mHasRootAbsPosContainingBlock = PR_TRUE;
} }
viewportFrame->SetInitialChildList(nsnull, newFrame); viewportFrame->SetInitialChildList(nsnull, newFrame);
@ -4540,12 +4555,12 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement,
} }
nsresult nsresult
nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell, nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsIFrame* aParentFrame, nsIFrame* aParentFrame,
nsIFrame* aPrevPageFrame, nsIFrame* aPrevPageFrame,
nsIFrame*& aPageFrame, nsIFrame*& aPageFrame,
nsIFrame*& aPageContentFrame) nsIFrame*& aCanvasFrame)
{ {
nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext(); nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
nsStyleSet *styleSet = aPresShell->StyleSet(); nsStyleSet *styleSet = aPresShell->StyleSet();
@ -4568,8 +4583,8 @@ nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell,
nsCSSAnonBoxes::pageContent, nsCSSAnonBoxes::pageContent,
pagePseudoStyle); pagePseudoStyle);
aPageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle); nsIFrame* pageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
if (NS_UNLIKELY(!aPageContentFrame)) if (NS_UNLIKELY(!pageContentFrame))
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
// Initialize the page content frame and force it to have a view. Also make it the // Initialize the page content frame and force it to have a view. Also make it the
@ -4579,10 +4594,26 @@ nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell,
prevPageContentFrame = aPrevPageFrame->GetFirstChild(nsnull); prevPageContentFrame = aPrevPageFrame->GetFirstChild(nsnull);
NS_ASSERTION(prevPageContentFrame, "missing page content frame"); NS_ASSERTION(prevPageContentFrame, "missing page content frame");
} }
aPageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame); pageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame);
mFixedContainingBlock = aPageContentFrame; aPageFrame->SetInitialChildList(nsnull, pageContentFrame);
mFixedContainingBlock = pageContentFrame;
aPageFrame->SetInitialChildList(nsnull, aPageContentFrame); nsRefPtr<nsStyleContext> canvasPseudoStyle;
canvasPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
nsCSSAnonBoxes::canvas,
pageContentPseudoStyle);
aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
if (NS_UNLIKELY(!aCanvasFrame))
return NS_ERROR_OUT_OF_MEMORY;
nsIFrame* prevCanvasFrame = nsnull;
if (prevPageContentFrame) {
prevCanvasFrame = prevPageContentFrame->GetFirstChild(nsnull);
NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
}
aCanvasFrame->Init(nsnull, pageContentFrame, prevCanvasFrame);
pageContentFrame->SetInitialChildList(nsnull, aCanvasFrame);
return NS_OK; return NS_OK;
} }
@ -6681,17 +6712,24 @@ already_AddRefed<nsStyleContext>
nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame, nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame,
nsIContent* aContent) nsIContent* aContent)
{ {
nsStyleContext* parentStyleContext; nsStyleContext* parentStyleContext = nsnull;
if (aContent->GetParent()) { if (aContent->GetParent()) {
aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nsnull); aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nsnull);
// Resolve the style context based on the content object and the parent if (aParentFrame) {
// style context // Resolve the style context based on the content object and the parent
parentStyleContext = aParentFrame->GetStyleContext(); // style context
parentStyleContext = aParentFrame->GetStyleContext();
} else {
// Perhaps aParentFrame is a canvasFrame and we're replicating
// fixed-pos frames.
// XXX should we create a way to tell ConstructFrame which style
// context to use, and pass it the style context for the
// previous page's fixed-pos frame?
}
} else { } else {
// This has got to be a call from ConstructDocElementTableFrame. // This has got to be a call from ConstructDocElementTableFrame.
// Not sure how best to asserrt that here. // Not sure how best to assert that here.
parentStyleContext = nsnull;
} }
nsStyleSet *styleSet = mPresShell->StyleSet(); nsStyleSet *styleSet = mPresShell->StyleSet();
@ -7504,17 +7542,23 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchyInternal()
nsIContent *rootContent = mDocument->GetRootContent(); nsIContent *rootContent = mDocument->GetRootContent();
if (rootContent) { if (rootContent) {
// Before removing the frames associated with the content object, ask them to save their
// state onto a temporary state object.
CaptureStateForFramesOf(rootContent, mTempFrameTreeState);
nsFrameConstructorState state(mPresShell, mFixedContainingBlock, nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
nsnull, nsnull, mTempFrameTreeState); nsnull, nsnull, mTempFrameTreeState);
// Before removing the frames associated with the content object, ask them to save their
// state onto a temporary state object.
CaptureStateFor(state.mFrameManager->GetRootFrame(), mTempFrameTreeState);
// Get the frame that corresponds to the document element // Get the frame that corresponds to the document element
nsIFrame* docElementFrame = nsIFrame* docElementFrame =
state.mFrameManager->GetPrimaryFrameFor(rootContent, -1); state.mFrameManager->GetPrimaryFrameFor(rootContent, -1);
if (docElementFrame) {
// Destroy out-of-flow frames that might not be in the frame subtree
// rooted at docElementFrame
::DeletingFrameSubtree(state.mFrameManager, docElementFrame);
}
// Remove any existing fixed items: they are always on the // Remove any existing fixed items: they are always on the
// FixedContainingBlock. Note that this has to be done before we call // FixedContainingBlock. Note that this has to be done before we call
// ClearPlaceholderFrameMap(), since RemoveFixedItems uses the // ClearPlaceholderFrameMap(), since RemoveFixedItems uses the
@ -7532,17 +7576,14 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchyInternal()
// XXXbz So why can't we reuse ContentRemoved? // XXXbz So why can't we reuse ContentRemoved?
NS_ASSERTION(docElementFrame->GetParent() == mDocElementContainingBlock,
"Unexpected doc element parent frame");
// Notify self that we will destroy the entire frame tree, this blocks // Notify self that we will destroy the entire frame tree, this blocks
// RemoveMappingsForFrameSubtree() which would otherwise lead to a // RemoveMappingsForFrameSubtree() which would otherwise lead to a
// crash since we cleared the placeholder map above (bug 398982). // crash since we cleared the placeholder map above (bug 398982).
PRBool wasDestroyingFrameTree = mIsDestroyingFrameTree; PRBool wasDestroyingFrameTree = mIsDestroyingFrameTree;
WillDestroyFrameTree(); WillDestroyFrameTree();
// Remove the old document element hieararchy // Remove the old document element hierarchy
rv = state.mFrameManager->RemoveFrame(mDocElementContainingBlock, rv = state.mFrameManager->RemoveFrame(docElementFrame->GetParent(),
nsnull, docElementFrame); GetChildListNameFor(docElementFrame), docElementFrame);
mIsDestroyingFrameTree = wasDestroyingFrameTree; mIsDestroyingFrameTree = wasDestroyingFrameTree;
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
@ -7639,9 +7680,8 @@ nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame)
if (containingBlock) if (containingBlock)
return AdjustAbsoluteContainingBlock(containingBlock); return AdjustAbsoluteContainingBlock(containingBlock);
// If we didn't find it, then use the initial containing block if it // If we didn't find it, then use the document element containing block
// supports abs pos kids. return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nsnull;
return mInitialContainingBlockIsAbsPosContainer ? mInitialContainingBlock : nsnull;
} }
nsIFrame* nsIFrame*
@ -10226,9 +10266,9 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
} }
} else if (nsGkAtoms::pageFrame == frameType) { } else if (nsGkAtoms::pageFrame == frameType) {
nsIFrame* pageContentFrame; nsIFrame* canvasFrame;
rv = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame, rv = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame,
newFrame, pageContentFrame); newFrame, canvasFrame);
} else if (nsGkAtoms::tableOuterFrame == frameType) { } else if (nsGkAtoms::tableOuterFrame == frameType) {
rv = CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame, rv = CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
content, styleContext, &newFrame); content, styleContext, &newFrame);
@ -10417,17 +10457,17 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
nsresult nsresult
nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame) nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
{ {
// Now deal with fixed-pos things.... They should appear on all pages, and // Now deal with fixed-pos things.... They should appear on all pages,
// the placeholders must be kids of a block, so we want to move over the // so we want to move over the placeholders when processing the child
// placeholders when processing the child of the pageContentFrame. // of the pageContentFrame.
nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow(); nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
if (!prevPageContentFrame) { if (!prevPageContentFrame) {
return NS_OK; return NS_OK;
} }
nsIFrame* docRootFrame = aParentFrame->GetFirstChild(nsnull); nsIFrame* canvasFrame = aParentFrame->GetFirstChild(nsnull);
nsIFrame* prevDocRootFrame = prevPageContentFrame->GetFirstChild(nsnull); nsIFrame* prevCanvasFrame = prevPageContentFrame->GetFirstChild(nsnull);
if (!docRootFrame || !prevDocRootFrame) { if (!canvasFrame || !prevCanvasFrame) {
// document's root element frame missing // document's root element frame missing
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
@ -10455,19 +10495,19 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
nsIFrame* prevPlaceholder = nsnull; nsIFrame* prevPlaceholder = nsnull;
mPresShell->GetPlaceholderFrameFor(fixed, &prevPlaceholder); mPresShell->GetPlaceholderFrameFor(fixed, &prevPlaceholder);
if (prevPlaceholder && if (prevPlaceholder &&
nsLayoutUtils::IsProperAncestorFrame(prevDocRootFrame, prevPlaceholder)) { nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
nsresult rv = ConstructFrame(state, fixed->GetContent(), nsresult rv = ConstructFrame(state, fixed->GetContent(),
docRootFrame, fixedPlaceholders); canvasFrame, fixedPlaceholders);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
} }
// Add the placeholders to our primary child list. // Add the placeholders to our primary child list.
// XXXbz this is a little screwed up, since the fixed frames will have the // XXXbz this is a little screwed up, since the fixed frames will have
// wrong parent block and hence auto-positioning will be broken. Oh, well. // broken auto-positioning. Oh, well.
NS_ASSERTION(!docRootFrame->GetFirstChild(nsnull), NS_ASSERTION(!canvasFrame->GetFirstChild(nsnull),
"leaking frames; doc root continuation must be empty"); "leaking frames; doc root continuation must be empty");
docRootFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList); canvasFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList);
return NS_OK; return NS_OK;
} }

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

@ -270,7 +270,7 @@ private:
nsIFrame* aParentFrame, nsIFrame* aParentFrame,
nsIFrame* aPrevPageFrame, nsIFrame* aPrevPageFrame,
nsIFrame*& aPageFrame, nsIFrame*& aPageFrame,
nsIFrame*& aPageContentFrame); nsIFrame*& aCanvasFrame);
void DoContentStateChanged(nsIContent* aContent, void DoContentStateChanged(nsIContent* aContent,
PRInt32 aStateMask); PRInt32 aStateMask);
@ -1164,6 +1164,9 @@ private:
nsIDocument* mDocument; // Weak ref nsIDocument* mDocument; // Weak ref
nsIPresShell* mPresShell; // Weak ref nsIPresShell* mPresShell; // Weak ref
// See the comment at the start of ConstructRootFrame for more details
// about the following frames.
// This is not the real CSS 2.1 "initial containing block"! It is just // This is not the real CSS 2.1 "initial containing block"! It is just
// the outermost frame for the root element. // the outermost frame for the root element.
nsIFrame* mInitialContainingBlock; nsIFrame* mInitialContainingBlock;
@ -1181,9 +1184,10 @@ private:
PRUint16 mUpdateCount; PRUint16 mUpdateCount;
PRPackedBool mQuotesDirty : 1; PRPackedBool mQuotesDirty : 1;
PRPackedBool mCountersDirty : 1; PRPackedBool mCountersDirty : 1;
PRPackedBool mInitialContainingBlockIsAbsPosContainer : 1;
PRPackedBool mIsDestroyingFrameTree : 1; PRPackedBool mIsDestroyingFrameTree : 1;
PRPackedBool mRebuildAllStyleData : 1; PRPackedBool mRebuildAllStyleData : 1;
// This is true if mDocElementContainingBlock supports absolute positioning
PRPackedBool mHasRootAbsPosContainingBlock : 1;
nsRevocableEventPtr<RestyleEvent> mRestyleEvent; nsRevocableEventPtr<RestyleEvent> mRestyleEvent;

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

@ -52,17 +52,6 @@
#include "nsBlockFrame.h" #include "nsBlockFrame.h"
#endif #endif
nsresult
nsAbsoluteContainingBlock::FirstChild(const nsIFrame* aDelegatingFrame,
nsIAtom* aListName,
nsIFrame** aFirstChild) const
{
NS_PRECONDITION(GetChildListName() == aListName, "unexpected child list name");
*aFirstChild = mAbsoluteFrames.FirstChild();
return NS_OK;
}
nsresult nsresult
nsAbsoluteContainingBlock::SetInitialChildList(nsIFrame* aDelegatingFrame, nsAbsoluteContainingBlock::SetInitialChildList(nsIFrame* aDelegatingFrame,
nsIAtom* aListName, nsIAtom* aListName,

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

@ -84,10 +84,7 @@ public:
nsIAtom* GetChildListName() const { return mChildListName; } nsIAtom* GetChildListName() const { return mChildListName; }
#endif #endif
nsresult FirstChild(const nsIFrame* aDelegatingFrame, nsIFrame* GetFirstChild() const { return mAbsoluteFrames.FirstChild(); }
nsIAtom* aListName,
nsIFrame** aFirstChild) const;
nsIFrame* GetFirstChild() { return mAbsoluteFrames.FirstChild(); }
nsresult SetInitialChildList(nsIFrame* aDelegatingFrame, nsresult SetInitialChildList(nsIFrame* aDelegatingFrame,
nsIAtom* aListName, nsIAtom* aListName,

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

@ -520,9 +520,7 @@ nsIFrame*
nsBlockFrame::GetFirstChild(nsIAtom* aListName) const nsBlockFrame::GetFirstChild(nsIAtom* aListName) const
{ {
if (nsGkAtoms::absoluteList == aListName) { if (nsGkAtoms::absoluteList == aListName) {
nsIFrame* result = nsnull; return mAbsoluteContainer.GetFirstChild();
mAbsoluteContainer.FirstChild(this, aListName, &result);
return result;
} }
else if (nsnull == aListName) { else if (nsnull == aListName) {
return (mLines.empty()) ? nsnull : mLines.front()->mFirstChild; return (mLines.empty()) ? nsnull : mLines.front()->mFirstChild;
@ -803,9 +801,11 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
cbSize.width -= border.LeftRight(); cbSize.width -= border.LeftRight();
cbSize.height -= border.TopBottom(); cbSize.height -= border.TopBottom();
if (frame->GetParent()->GetContent() == frame->GetContent()) { if (frame->GetParent()->GetContent() == frame->GetContent() &&
// We are a wrapped frame for the content. Use the container's frame->GetParent()->GetType() != nsGkAtoms::canvasFrame) {
// dimensions, if they have been precomputed. // We are a wrapped frame for the content (and the wrapper is not the
// canvas frame, whose size is not meaningful here).
// Use the container's dimensions, if they have been precomputed.
// XXX This is a hack! We really should be waiting until the outermost // XXX This is a hack! We really should be waiting until the outermost
// frame is fully reflowed and using the resulting dimensions, even // frame is fully reflowed and using the resulting dimensions, even
// if they're intrinsic. // if they're intrinsic.
@ -816,14 +816,10 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
// content. // content.
const nsHTMLReflowState* aLastRS = &aReflowState; const nsHTMLReflowState* aLastRS = &aReflowState;
const nsHTMLReflowState* lastButOneRS = &aReflowState; const nsHTMLReflowState* lastButOneRS = &aReflowState;
PRBool isCanvasBlock = PR_FALSE;
while (aLastRS->parentReflowState && while (aLastRS->parentReflowState &&
aLastRS->parentReflowState->frame->GetContent() == frame->GetContent()) { aLastRS->parentReflowState->frame->GetContent() == frame->GetContent()) {
lastButOneRS = aLastRS; lastButOneRS = aLastRS;
aLastRS = aLastRS->parentReflowState; aLastRS = aLastRS->parentReflowState;
if (aLastRS->frame->GetType() == nsGkAtoms::canvasFrame) {
isCanvasBlock = PR_TRUE;
}
} }
if (aLastRS != &aReflowState) { if (aLastRS != &aReflowState) {
// Scrollbars need to be specifically excluded, if present, because they are outside the // Scrollbars need to be specifically excluded, if present, because they are outside the
@ -844,23 +840,11 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
} }
// We found a reflow state for the outermost wrapping frame, so use // We found a reflow state for the outermost wrapping frame, so use
// its computed metrics if available // its computed metrics if available
// XXX grotesque hack for Firefox 2 compatibility until we can if (aLastRS->ComputedWidth() != NS_UNCONSTRAINEDSIZE) {
// properly fix abs-pos containers! If this is the block for
// the root element, don't adjust the width here, just use the block's
// width. We have to do this because the abs-pos frame will be
// positioned relative to the block, not the canvas frame, and the
// block might have borders and margin which will throw things off
// if we use the canvas frame width.
// Positioning abs-pos frames relative to the canvas is bug 425432.
if (aLastRS->ComputedWidth() != NS_UNCONSTRAINEDSIZE && !isCanvasBlock) {
cbSize.width = PR_MAX(0, cbSize.width = PR_MAX(0,
aLastRS->ComputedWidth() + aLastRS->mComputedPadding.LeftRight() - scrollbars.LeftRight()); aLastRS->ComputedWidth() + aLastRS->mComputedPadding.LeftRight() - scrollbars.LeftRight());
} }
if (aLastRS->ComputedHeight() != NS_UNCONSTRAINEDSIZE) { if (aLastRS->ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
// XXX This can be terribly wrong if we're the root element's block,
// because our margin and borders will be included in the height
// here but the abs-pos element(s) are positioned relative to
// our content rect...
cbSize.height = PR_MAX(0, cbSize.height = PR_MAX(0,
aLastRS->ComputedHeight() + aLastRS->mComputedPadding.TopBottom() - scrollbars.TopBottom()); aLastRS->ComputedHeight() + aLastRS->mComputedPadding.TopBottom() - scrollbars.TopBottom());
} }

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

@ -1584,6 +1584,9 @@ nsContainerFrame::List(FILE* out, PRInt32 aIndent) const
PRInt32 listIndex = 0; PRInt32 listIndex = 0;
PRBool outputOneList = PR_FALSE; PRBool outputOneList = PR_FALSE;
do { do {
if (!outputOneList) {
fputs("\n", out);
}
nsIFrame* kid = GetFirstChild(listName); nsIFrame* kid = GetFirstChild(listName);
if (nsnull != kid) { if (nsnull != kid) {
if (outputOneList) { if (outputOneList) {

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

@ -5559,12 +5559,19 @@ nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
parent = parent->GetParent(); parent = parent->GetParent();
} while (parent); } while (parent);
// We can get here if aProspectiveParent is the scrollframe for a viewport if (aProspectiveParent->GetStyleContext()->GetPseudoType() ==
// and the kids are the anonymous scrollbars. nsCSSAnonBoxes::viewportScroll) {
NS_ASSERTION(aProspectiveParent->GetStyleContext()->GetPseudoType() == // aProspectiveParent is the scrollframe for a viewport
nsCSSAnonBoxes::viewportScroll, // and the kids are the anonymous scrollbars
return aProspectiveParent;
}
// We can get here if the root element is absolutely positioned.
// We can't test for this very accurately, but it can only happen
// when the prospective parent is a canvas frame.
NS_ASSERTION(aProspectiveParent->GetType() == nsGkAtoms::canvasFrame,
"Should have found a parent before this"); "Should have found a parent before this");
return aProspectiveParent; return nsnull;
} }
nsresult nsresult

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

@ -54,6 +54,7 @@
#include "nsIPresShell.h" #include "nsIPresShell.h"
#include "nsIScrollPositionListener.h" #include "nsIScrollPositionListener.h"
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsAbsoluteContainingBlock.h"
// for focus // for focus
#include "nsIDOMWindowInternal.h" #include "nsIDOMWindowInternal.h"
@ -67,6 +68,8 @@
//#define DEBUG_CANVAS_FOCUS //#define DEBUG_CANVAS_FOCUS
#endif #endif
#define CANVAS_ABS_POS_CHILD_LIST NS_CONTAINER_LIST_COUNT_INCL_OC
// Interface IDs // Interface IDs
/** /**
@ -81,7 +84,8 @@ class CanvasFrame : public nsHTMLContainerFrame,
public nsICanvasFrame { public nsICanvasFrame {
public: public:
CanvasFrame(nsStyleContext* aContext) CanvasFrame(nsStyleContext* aContext)
: nsHTMLContainerFrame(aContext), mDoPaintFocus(PR_FALSE) {} : nsHTMLContainerFrame(aContext), mDoPaintFocus(PR_FALSE),
mAbsoluteContainer(nsGkAtoms::absoluteList) {}
// nsISupports // nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@ -91,6 +95,8 @@ public:
nsIFrame* aPrevInFlow); nsIFrame* aPrevInFlow);
virtual void Destroy(); virtual void Destroy();
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD AppendFrames(nsIAtom* aListName, NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList); nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIAtom* aListName, NS_IMETHOD InsertFrames(nsIAtom* aListName,
@ -99,6 +105,9 @@ public:
NS_IMETHOD RemoveFrame(nsIAtom* aListName, NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame); nsIFrame* aOldFrame);
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext); virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext); virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
NS_IMETHOD Reflow(nsPresContext* aPresContext, NS_IMETHOD Reflow(nsPresContext* aPresContext,
@ -106,6 +115,11 @@ public:
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus); nsReflowStatus& aStatus);
virtual PRBool IsContainingBlock() const { return PR_TRUE; } virtual PRBool IsContainingBlock() const { return PR_TRUE; }
virtual PRBool IsFrameOfType(PRUint32 aFlags) const
{
return nsHTMLContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eCanContainOverflowContainers));
}
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
@ -128,6 +142,21 @@ public:
*/ */
virtual nsIAtom* GetType() const; virtual nsIAtom* GetType() const;
virtual nsresult StealFrame(nsPresContext* aPresContext,
nsIFrame* aChild,
PRBool aForceNormal)
{
NS_ASSERTION(!aForceNormal, "No-one should be passing this in here");
// CanvasFrame keeps overflow container continuations of its child
// frame in main child list
nsresult rv = nsContainerFrame::StealFrame(aPresContext, aChild, PR_TRUE);
if (NS_FAILED(rv)) {
rv = nsContainerFrame::StealFrame(aPresContext, aChild);
}
return rv;
}
#ifdef DEBUG #ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const; NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif #endif
@ -141,8 +170,9 @@ protected:
virtual PRIntn GetSkipSides() const; virtual PRIntn GetSkipSides() const;
// Data members // Data members
PRPackedBool mDoPaintFocus; PRPackedBool mDoPaintFocus;
nsCOMPtr<nsIViewManager> mViewManager; nsCOMPtr<nsIViewManager> mViewManager;
nsAbsoluteContainingBlock mAbsoluteContainer;
private: private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
@ -198,6 +228,8 @@ CanvasFrame::Init(nsIContent* aContent,
void void
CanvasFrame::Destroy() CanvasFrame::Destroy()
{ {
mAbsoluteContainer.DestroyFrames(this);
nsIScrollableView* scrollingView = nsnull; nsIScrollableView* scrollingView = nsnull;
mViewManager->GetRootScrollableView(&scrollingView); mViewManager->GetRootScrollableView(&scrollingView);
if (scrollingView) { if (scrollingView) {
@ -246,20 +278,32 @@ CanvasFrame::SetHasFocus(PRBool aHasFocus)
{ {
if (mDoPaintFocus != aHasFocus) { if (mDoPaintFocus != aHasFocus) {
mDoPaintFocus = aHasFocus; mDoPaintFocus = aHasFocus;
nsIViewManager* vm = PresContext()->PresShell()->GetViewManager(); mViewManager->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
if (vm) {
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
}
} }
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
CanvasFrame::SetInitialChildList(nsIAtom* aListName,
nsIFrame* aChildList)
{
if (nsGkAtoms::absoluteList == aListName)
return mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList);
NS_ASSERTION(aListName || !aChildList || !aChildList->GetNextSibling(),
"Primary child list can have at most one frame in it");
return nsHTMLContainerFrame::SetInitialChildList(aListName, aChildList);
}
NS_IMETHODIMP NS_IMETHODIMP
CanvasFrame::AppendFrames(nsIAtom* aListName, CanvasFrame::AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList) nsIFrame* aFrameList)
{ {
nsresult rv; nsresult rv;
if (nsGkAtoms::absoluteList == aListName)
return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
NS_ASSERTION(!aListName, "unexpected child list name"); NS_ASSERTION(!aListName, "unexpected child list name");
NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame"); NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame");
if (aListName) { if (aListName) {
@ -292,6 +336,9 @@ CanvasFrame::InsertFrames(nsIAtom* aListName,
{ {
nsresult rv; nsresult rv;
if (nsGkAtoms::absoluteList == aListName)
return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList);
// Because we only support a single child frame inserting is the same // Because we only support a single child frame inserting is the same
// as appending // as appending
NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame"); NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
@ -310,6 +357,9 @@ CanvasFrame::RemoveFrame(nsIAtom* aListName,
{ {
nsresult rv; nsresult rv;
if (nsGkAtoms::absoluteList == aListName)
return mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
NS_ASSERTION(!aListName, "unexpected child list name"); NS_ASSERTION(!aListName, "unexpected child list name");
if (aListName) { if (aListName) {
// We only support the unnamed principal child list // We only support the unnamed principal child list
@ -335,6 +385,24 @@ CanvasFrame::RemoveFrame(nsIAtom* aListName,
return rv; return rv;
} }
nsIAtom*
CanvasFrame::GetAdditionalChildListName(PRInt32 aIndex) const
{
if (CANVAS_ABS_POS_CHILD_LIST == aIndex)
return nsGkAtoms::absoluteList;
return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex);
}
nsIFrame*
CanvasFrame::GetFirstChild(nsIAtom* aListName) const
{
if (nsGkAtoms::absoluteList == aListName)
return mAbsoluteContainer.GetFirstChild();
return nsHTMLContainerFrame::GetFirstChild(aListName);
}
nsRect CanvasFrame::CanvasArea() const nsRect CanvasFrame::CanvasArea() const
{ {
nsRect result(GetOverflowRect()); nsRect result(GetOverflowRect());
@ -419,6 +487,13 @@ CanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) const nsDisplayListSet& aLists)
{ {
nsresult rv; nsresult rv;
if (GetPrevInFlow()) {
DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
}
aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetFirstChild(), aDirtyRect);
// Force a background to be shown. We may have a background propagated to us, // Force a background to be shown. We may have a background propagated to us,
// in which case GetStyleBackground wouldn't have the right background // in which case GetStyleBackground wouldn't have the right background
// and the code in nsFrame::DisplayBorderBackgroundOutline might not give us // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
@ -432,8 +507,8 @@ CanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsIFrame* kid = GetFirstChild(nsnull); nsIFrame* kid;
if (kid) { for (kid = GetFirstChild(nsnull); kid; kid = kid->GetNextSibling()) {
// Put our child into its own pseudo-stack. // Put our child into its own pseudo-stack.
rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists, rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists,
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT); DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
@ -528,7 +603,7 @@ CanvasFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
} }
NS_IMETHODIMP NS_IMETHODIMP
CanvasFrame::Reflow(nsPresContext* aPresContext, CanvasFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus) nsReflowStatus& aStatus)
@ -540,7 +615,28 @@ CanvasFrame::Reflow(nsPresContext* aPresContext,
// Initialize OUT parameter // Initialize OUT parameter
aStatus = NS_FRAME_COMPLETE; aStatus = NS_FRAME_COMPLETE;
// Reflow our one and only child frame CanvasFrame* prevCanvasFrame = static_cast<CanvasFrame*>
(GetPrevInFlow());
if (prevCanvasFrame) {
nsIFrame* overflow = prevCanvasFrame->GetOverflowFrames(aPresContext, PR_TRUE);
if (overflow) {
NS_ASSERTION(!overflow->GetNextSibling(),
"must have doc root as canvas frame's only child");
nsHTMLContainerFrame::ReparentFrameView(aPresContext, overflow, prevCanvasFrame, this);
// Prepend overflow to the our child list. There may already be
// children placeholders for fixed-pos elements, which don't get
// reflowed but must not be lost until the canvas frame is destroyed.
mFrames.InsertFrames(this, nsnull, overflow);
}
}
// Reflow our one and only normal child frame. It's either the root
// element's frame or a placeholder for that frame, if the root element
// is abs-pos or fixed-pos. We may have additional children which
// are placeholders for continuations of fixed-pos content, but those
// don't need to be reflowed. The normal child is always comes before
// the fixed-pos placeholders, because we insert it at the start
// of the child list, above.
nsHTMLReflowMetrics kidDesiredSize; nsHTMLReflowMetrics kidDesiredSize;
if (mFrames.IsEmpty()) { if (mFrames.IsEmpty()) {
// We have no child frame, so return an empty size // We have no child frame, so return an empty size
@ -549,11 +645,9 @@ CanvasFrame::Reflow(nsPresContext* aPresContext,
nsIFrame* kidFrame = mFrames.FirstChild(); nsIFrame* kidFrame = mFrames.FirstChild();
PRBool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0; PRBool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
// We must specify an unconstrained available height, because constrained
// is only for when we're paginated...
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
nsSize(aReflowState.availableWidth, nsSize(aReflowState.availableWidth,
NS_UNCONSTRAINEDSIZE)); aReflowState.availableHeight));
if (aReflowState.mFlags.mVResize && if (aReflowState.mFlags.mVResize &&
(kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) { (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
@ -562,15 +656,43 @@ CanvasFrame::Reflow(nsPresContext* aPresContext,
kidReflowState.mFlags.mVResize = PR_TRUE; kidReflowState.mFlags.mVResize = PR_TRUE;
} }
nsPoint kidPt(kidReflowState.mComputedMargin.left,
kidReflowState.mComputedMargin.top);
// Apply CSS relative positioning
const nsStyleDisplay* styleDisp = kidFrame->GetStyleDisplay();
if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
kidPt += nsPoint(kidReflowState.mComputedOffsets.left,
kidReflowState.mComputedOffsets.top);
}
// Reflow the frame // Reflow the frame
ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, kidPt.x, kidPt.y, 0, aStatus);
0, aStatus);
// Complete the reflow and position and size the child frame // Complete the reflow and position and size the child frame
FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize, FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize,
kidReflowState.mComputedMargin.left, kidPt.x, kidPt.y, 0);
kidReflowState.mComputedMargin.top, 0);
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
nsIFrame* nextFrame = kidFrame->GetNextInFlow();
NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
"If it's incomplete and has no nif yet, it must flag a nif reflow.");
if (!nextFrame) {
nsresult rv = nsHTMLContainerFrame::CreateNextInFlow(aPresContext,
this, kidFrame, nextFrame);
NS_ENSURE_SUCCESS(rv, rv);
kidFrame->SetNextSibling(nextFrame->GetNextSibling());
nextFrame->SetNextSibling(nsnull);
SetOverflowFrames(aPresContext, nextFrame);
// Root overflow containers will be normal children of
// the canvas frame, but that's ok because there
// aren't any other frames we need to isolate them from
// during reflow.
}
if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
}
}
// If the child frame was just inserted, then we're responsible for making sure // If the child frame was just inserted, then we're responsible for making sure
// it repaints // it repaints
@ -588,18 +710,33 @@ CanvasFrame::Reflow(nsPresContext* aPresContext,
} }
// Return our desired size (which doesn't matter) // Return our desired size (which doesn't matter)
aDesiredSize.width = aReflowState.availableWidth; aDesiredSize.width = aReflowState.ComputedWidth();
aDesiredSize.height = kidDesiredSize.height + aDesiredSize.height = aReflowState.ComputedHeight();
kidReflowState.mComputedMargin.TopBottom();
aDesiredSize.mOverflowArea.UnionRect( aDesiredSize.mOverflowArea.UnionRect(
nsRect(0, 0, aDesiredSize.width, aDesiredSize.height), nsRect(0, 0, aDesiredSize.width, aDesiredSize.height),
kidDesiredSize.mOverflowArea + kidDesiredSize.mOverflowArea + kidPt);
nsPoint(kidReflowState.mComputedMargin.left,
kidReflowState.mComputedMargin.top)); if (mAbsoluteContainer.HasAbsoluteFrames()) {
FinishAndStoreOverflow(&aDesiredSize); PRBool widthChanged = aDesiredSize.width != mRect.width;
PRBool heightChanged = aDesiredSize.height != mRect.height;
nsRect absPosBounds;
mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus,
aDesiredSize.width, aDesiredSize.height,
PR_TRUE, widthChanged, heightChanged,
&absPosBounds);
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, absPosBounds);
}
} }
if (prevCanvasFrame) {
ReflowOverflowContainerChildren(aPresContext, aReflowState,
aDesiredSize.mOverflowArea, 0,
aStatus);
}
FinishAndStoreOverflow(&aDesiredSize);
NS_FRAME_TRACE_REFLOW_OUT("CanvasFrame::Reflow", aStatus); NS_FRAME_TRACE_REFLOW_OUT("CanvasFrame::Reflow", aStatus);
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK; return NS_OK;

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

@ -113,31 +113,24 @@ NS_NewTableCellInnerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
return NS_NewBlockFrame(aPresShell, aContext); return NS_NewBlockFrame(aPresShell, aContext);
} }
// This type of AreaFrame is the document root, a margin root, and the // This type of BlockFrame is a margin root, but does not shrink wrap
// initial containing block for absolutely positioned elements
inline nsIFrame*
NS_NewDocumentElementFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
return NS_NewAreaFrame(aPresShell, aContext, NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
}
// This type of AreaFrame is a margin root, but does not shrink wrap
inline nsIFrame* inline nsIFrame*
NS_NewAbsoluteItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { NS_NewAbsoluteItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
return NS_NewAreaFrame(aPresShell, aContext, NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT); return NS_NewBlockFrame(aPresShell, aContext, NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
} }
// This type of AreaFrame shrink wraps // This type of BlockFrame shrink wraps
inline nsIFrame* inline nsIFrame*
NS_NewFloatingItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { NS_NewFloatingItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
return NS_NewAreaFrame(aPresShell, aContext, return NS_NewBlockFrame(aPresShell, aContext,
NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT); NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
} }
// This type of AreaFrame doesn't use its own space manager and // This type of BlockFrame doesn't use its own space manager and
// doesn't shrink wrap. // doesn't shrink wrap.
inline nsIFrame* inline nsIFrame*
NS_NewRelativeItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags) { NS_NewRelativeItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags) {
return NS_NewAreaFrame(aPresShell, aContext, aFlags); return NS_NewBlockFrame(aPresShell, aContext, aFlags);
} }
nsIFrame* nsIFrame*

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

@ -1531,25 +1531,7 @@ nsHTMLReflowState::ComputeContainingBlockRectangle(nsPresContext* aPres
// If the ancestor is block-level, the containing block is formed by the // If the ancestor is block-level, the containing block is formed by the
// padding edge of the ancestor // padding edge of the ancestor
aContainingBlockWidth += aContainingBlockRS->mComputedPadding.LeftRight(); aContainingBlockWidth += aContainingBlockRS->mComputedPadding.LeftRight();
aContainingBlockHeight += aContainingBlockRS->mComputedPadding.TopBottom();
// If the containing block is the initial containing block and it has a
// height that depends on its content, then use the viewport height instead.
// This gives us a reasonable value against which to compute percentage
// based heights and to do bottom relative positioning
if ((NS_AUTOHEIGHT == aContainingBlockHeight) &&
nsLayoutUtils::IsInitialContainingBlock(aContainingBlockRS->frame)) {
// Use the viewport height as the containing block height
const nsHTMLReflowState* rs = aContainingBlockRS->parentReflowState;
while (rs) {
aContainingBlockHeight = rs->mComputedHeight;
rs = rs->parentReflowState;
}
} else {
aContainingBlockHeight +=
aContainingBlockRS->mComputedPadding.TopBottom();
}
} }
} else { } else {
// an element in quirks mode gets a containing block based on looking for a // an element in quirks mode gets a containing block based on looking for a

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

@ -1073,11 +1073,8 @@ nsPositionedInlineFrame::GetAdditionalChildListName(PRInt32 aIndex) const
nsIFrame* nsIFrame*
nsPositionedInlineFrame::GetFirstChild(nsIAtom* aListName) const nsPositionedInlineFrame::GetFirstChild(nsIAtom* aListName) const
{ {
if (nsGkAtoms::absoluteList == aListName) { if (nsGkAtoms::absoluteList == aListName)
nsIFrame* result = nsnull; return mAbsoluteContainer.GetFirstChild();
mAbsoluteContainer.FirstChild(this, aListName, &result);
return result;
}
return nsInlineFrame::GetFirstChild(aListName); return nsInlineFrame::GetFirstChild(aListName);
} }

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

@ -69,55 +69,6 @@ nsPageContentFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
return nsSize(aAvailableWidth, height); return nsSize(aAvailableWidth, height);
} }
/**
* Returns true if aFrame is a placeholder for one of our fixed frames.
*/
inline PRBool
nsPageContentFrame::IsFixedPlaceholder(nsIFrame* aFrame)
{
if (!aFrame || nsGkAtoms::placeholderFrame != aFrame->GetType())
return PR_FALSE;
return static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame()
->GetParent() == this;
}
/**
* Steals replicated fixed placeholder frames from aDocRoot so they don't
* get in the way of reflow.
*/
inline nsFrameList
nsPageContentFrame::StealFixedPlaceholders(nsIFrame* aDocRoot)
{
nsPresContext* presContext = PresContext();
nsFrameList list;
if (GetPrevInFlow()) {
for (nsIFrame* f = aDocRoot->GetFirstChild(nsnull);
IsFixedPlaceholder(f); f = aDocRoot->GetFirstChild(nsnull)) {
nsresult rv = static_cast<nsContainerFrame*>(aDocRoot)
->StealFrame(presContext, f);
NS_ENSURE_SUCCESS(rv, list);
list.AppendFrame(nsnull, f);
}
}
return list;
}
/**
* Restores stolen replicated fixed placeholder frames to aDocRoot.
*/
static inline nsresult
ReplaceFixedPlaceholders(nsIFrame* aDocRoot,
nsFrameList& aPlaceholderList)
{
nsresult rv = NS_OK;
if (aPlaceholderList.NotEmpty()) {
rv = static_cast<nsContainerFrame*>(aDocRoot)
->AddFrames(aPlaceholderList.FirstChild(), nsnull);
}
return rv;
}
NS_IMETHODIMP NS_IMETHODIMP
nsPageContentFrame::Reflow(nsPresContext* aPresContext, nsPageContentFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
@ -129,67 +80,27 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE; // initialize out parameter aStatus = NS_FRAME_COMPLETE; // initialize out parameter
nsresult rv = NS_OK; nsresult rv = NS_OK;
// A PageContentFrame must always have one child: the doc root element's frame. if (GetPrevInFlow() && (GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
// We only need to get overflow frames if we don't already have that child;
// Also we need to avoid repeating the call to ReplicateFixedFrames.
nsPageContentFrame* prevPageContentFrame = static_cast<nsPageContentFrame*>
(GetPrevInFlow());
if (mFrames.IsEmpty() && prevPageContentFrame) {
// Pull the doc root frame's continuation and copy fixed frames.
nsIFrame* overflow = prevPageContentFrame->GetOverflowFrames(aPresContext, PR_TRUE);
NS_ASSERTION(overflow && !overflow->GetNextSibling(),
"must have doc root as pageContentFrame's only child");
nsHTMLContainerFrame::ReparentFrameView(aPresContext, overflow, prevPageContentFrame, this);
// Prepend overflow to the page content frame. There may already be
// children placeholders which don't get reflowed but must not be
// lost until the page content frame is destroyed.
mFrames.InsertFrames(this, nsnull, overflow);
nsresult rv = aPresContext->PresShell()->FrameConstructor() nsresult rv = aPresContext->PresShell()->FrameConstructor()
->ReplicateFixedFrames(this); ->ReplicateFixedFrames(this);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
// A PageContentFrame must always have one child: the canvas frame.
// Resize our frame allowing it only to be as big as we are // Resize our frame allowing it only to be as big as we are
// XXX Pay attention to the page's border and padding... // XXX Pay attention to the page's border and padding...
if (mFrames.NotEmpty()) { if (mFrames.NotEmpty()) {
nsIFrame* frame = mFrames.FirstChild(); nsIFrame* frame = mFrames.FirstChild();
nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight); nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
kidReflowState.SetComputedHeight(aReflowState.availableHeight);
mPD->mPageContentSize = aReflowState.availableWidth; mPD->mPageContentSize = aReflowState.availableWidth;
// Get replicated fixed frames' placeholders out of the way
nsFrameList stolenPlaceholders = StealFixedPlaceholders(frame);
// Reflow the page content area // Reflow the page content area
rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Put removed fixed placeholders back
rv = ReplaceFixedPlaceholders(frame, stolenPlaceholders);
NS_ENSURE_SUCCESS(rv, rv);
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
nsIFrame* nextFrame = frame->GetNextInFlow();
NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
"If it's incomplete and has no nif yet, it must flag a nif reflow.");
if (!nextFrame) {
nsresult rv = nsHTMLContainerFrame::CreateNextInFlow(aPresContext,
this, frame, nextFrame);
NS_ENSURE_SUCCESS(rv, rv);
frame->SetNextSibling(nextFrame->GetNextSibling());
nextFrame->SetNextSibling(nsnull);
SetOverflowFrames(aPresContext, nextFrame);
// Root overflow containers will be normal children of
// the pageContentFrame, but that's ok because there
// aren't any other frames we need to isolate them from
// during reflow.
}
if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
}
}
// The document element's background should cover the entire canvas, so // The document element's background should cover the entire canvas, so
// take into account the combined area and any space taken up by // take into account the combined area and any space taken up by
// absolutely positioned elements // absolutely positioned elements

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

@ -83,10 +83,6 @@ protected:
nsPageContentFrame(nsStyleContext* aContext) : ViewportFrame(aContext) {} nsPageContentFrame(nsStyleContext* aContext) : ViewportFrame(aContext) {}
nsSharedPageData* mPD; nsSharedPageData* mPD;
private:
PRBool IsFixedPlaceholder(nsIFrame* aFrame);
nsFrameList StealFixedPlaceholders(nsIFrame* aDocRoot);
}; };
#endif /* nsPageContentFrame_h___ */ #endif /* nsPageContentFrame_h___ */

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

@ -179,11 +179,8 @@ ViewportFrame::GetAdditionalChildListName(PRInt32 aIndex) const
nsIFrame* nsIFrame*
ViewportFrame::GetFirstChild(nsIAtom* aListName) const ViewportFrame::GetFirstChild(nsIAtom* aListName) const
{ {
if (nsGkAtoms::fixedList == aListName) { if (nsGkAtoms::fixedList == aListName)
nsIFrame* result = nsnull; return mFixedContainer.GetFirstChild();
mFixedContainer.FirstChild(this, aListName, &result);
return result;
}
return nsContainerFrame::GetFirstChild(aListName); return nsContainerFrame::GetFirstChild(aListName);
} }
@ -309,8 +306,7 @@ ViewportFrame::Reflow(nsPresContext* aPresContext,
nsPoint offset = AdjustReflowStateForScrollbars(&reflowState); nsPoint offset = AdjustReflowStateForScrollbars(&reflowState);
#ifdef DEBUG #ifdef DEBUG
nsIFrame* f; nsIFrame* f = mFixedContainer.GetFirstChild();
mFixedContainer.FirstChild(this, nsGkAtoms::fixedList, &f);
NS_ASSERTION(!f || (offset.x == 0 && offset.y == 0), NS_ASSERTION(!f || (offset.x == 0 && offset.y == 0),
"We don't handle correct positioning of fixed frames with " "We don't handle correct positioning of fixed frames with "
"scrollbars in odd positions"); "scrollbars in odd positions");

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

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" class="reftest-print">
<head>
<title>Fixed DIV, Multipe Page Testcase</title>
<style type="text/css">
div.header { position: fixed;
width: 100%;
height: 1.5em;
top: 0;
font-style: italic;
background-color: white;
color: black }
</style>
</head>
<body>
<div class="header">I stay on the top of the web page and each printed page.</div>
<h1>Fixed DIV, multiple page testcase</h1>
<hr />
<p>Maybe related to bug 163800?</p>
<p>Similar to 193686 and 197808, but there are <i>no</i> forms involved in this crash.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
<p>Repeating text, to get us onto the next page.</p>
</body>
</html>

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

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<style>
body { margin:0; }
.pos { position:absolute; width:100px; height:100px; }
</style>
</head>
<body>
<div style="height:10000px; margin:0; margin:10px; border:20px solid black; padding:30px;"></div>
<script>
window.scrollTo(0,50);
</script>
<div class="pos" style="top:0; left:60px; background:yellow;"></div>
<div class="pos" style="right:0; top:60px; background:orange;"></div>
<div class="pos" style="bottom:0; left:60px; background:brown;"></div>
<div class="pos" style="left:0; top:60px; background:pink;"></div>
</div>
</body>
</html>

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

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<style>
html { margin:10px; border:20px solid black; padding:30px; }
body { height:10000px; margin:0; }
div { position:absolute; width:100px; height:100px; }
</style>
</head>
<body>
<script>
window.scrollTo(0,50);
</script>
<div style="top:0; background:yellow;"></div>
<div style="right:0; background:orange;"></div>
<div style="bottom:0; background:brown;"></div>
<div style="left:0; background:pink;"></div>
</body>
</html>

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

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body style="-moz-column-count:2; margin:0;">
Hello<br>
Kitty
</body>
</html>

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

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html style="-moz-column-count:2;">
<body style="margin:0;">
Hello<br>
Kitty
</body>
</html>

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

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<head>
<style>
body { margin:0; }
.pos { position:absolute; width:100px; height:100px; }
</style>
</head>
<body>
<div class="pos" style="top:0; left:60px; border:10px solid yellow;"></div>
<div class="pos" style="right:0; top:60px; border:10px solid orange;"></div>
<div class="pos" style="bottom:0; left:60px; border:10px solid brown;"></div>
<div class="pos" style="left:0; top:60px; border:10px solid pink;"></div>
<div style="margin:10px; border:20px solid black; padding:30px;"></div>
</div>
</body>
</html>

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

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<head>
<style>
html { margin:10px; border:20px solid black; padding:30px; }
body { margin:0; }
div { position:absolute; width:100px; height:100px; }
</style>
</head>
<body>
<div style="top:0; border:10px solid yellow;"></div>
<div style="right:0; border:10px solid orange;"></div>
<div style="bottom:0; border:10px solid brown;"></div>
<div style="left:0; border:10px solid pink;"></div>
</body>
</html>

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

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html style="background:yellow;">
<body>
<div style="position:absolute; top:100px; left:100px; width:100px; height:100px;
border:10px solid black;"></div>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:absolute; left:100px; top:100px; width:100px; height:100px;
background:yellow; border:10px solid black;">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:fixed; left:100px; top:100px; width:100px; height:100px;
background:yellow; border:10px solid black;">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:absolute; left:100px; top:100px; width:100px; height:100px;
background:yellow; border:10px solid black; display:table;">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:fixed; left:100px; top:100px; width:100px; height:100px;
background:yellow; border:10px solid black; display:table">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="display:table">
<body style="position:absolute; left:100px; top:100px; width:100px; height:100px; border:10px solid black;
background:yellow; margin:0">
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="display:table">
<body style="position:fixed; left:100px; top:100px; width:100px; height:100px; border:10px solid black;
background:yellow; margin:0">
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="background:yellow;">
<body style="margin:0">
<div style="border:10px solid black; width:100px; height:100px;"></div>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:absolute; width:100px; height:100px;
background:yellow; border:10px solid black;">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:absolute; width:100px; height:100px; display:table;
background:yellow; border:10px solid black;">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:fixed; width:100px; height:100px;
background:yellow; border:10px solid black;">
<body>
</body>
</html>

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html style="position:fixed; width:100px; height:100px; display:table;
background:yellow; border:10px solid black;">
<body>
</body>
</html>

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

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<head>
<style>
div { margin:10px; border:20px solid black; padding:30px; height:4in; position:absolute; }
body { margin:0; }
</style>
</head>
<body>
<div></div>
</body>
</html>

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<head>
<style>
html { margin:10px; border:20px solid black; padding:30px; height:4in; position:absolute; }
body { margin:0; }
</style>
</head>
<body>
</body>
</html>

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

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<html>
<body style="margin:0;">
<div style="position:relative; top:100px; left:100px; height:100px; border:10px solid black;">
<div style="position:absolute; bottom:0; height:30px; border:10px solid orange;">
</div>
</body>
</html>

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

@ -0,0 +1,5 @@
<!DOCTYPE HTML>
<html style="position:relative; top:100px; left:100px; height:100px; border:10px solid black;">
<body style="position:absolute; margin:0; bottom:0; height:30px; border:10px solid orange;">
</body>
</html>

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

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect fill="lime" x="100" y="100" width="100" height="100"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 111 B

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

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" style="position:absolute; left:100px; top:100px; overflow:hidden;">
<rect fill="lime" width="100" height="100"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 162 B

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

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html>
<body style="margin:0">
<div style="position:fixed; width:50%; height:50%; left:50px; top:50px; border:10px solid black;"></div>
</body>
</html>

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

@ -0,0 +1,3 @@
<!DOCTYPE HTML>
<html style="width:50%; height:50%; margin:50px; border:10px solid black;">
</html>

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

@ -0,0 +1,3 @@
<!DOCTYPE HTML>
<html style="position:absolute; left:50px; top:50px; width:50%; height:50%; border:10px solid black;">
</html>

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

@ -0,0 +1,2 @@
<html style="width:50%; height:50%; margin:50px; border:10px solid black;">
</html>

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

@ -0,0 +1,2 @@
<html style="position:absolute; left:50px; top:50px; width:50%; height:50%; border:10px solid black;">
</html>

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

@ -0,0 +1,5 @@
<!DOCTYPE HTML>
<html>
<body style="position:absolute; width:50%; height:50%; top:50px; left:50px; margin:0; border:10px solid black;">
</body>
</html>

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

@ -125,6 +125,7 @@ fails == 25888-3r.html 25888-3r-ref.html # bug 25888
== 180085-1.html 180085-1-ref.html == 180085-1.html 180085-1-ref.html
== 180085-2.html 180085-2-ref.html == 180085-2.html 180085-2-ref.html
== 185388-1.html 185388-1-ref.html == 185388-1.html 185388-1-ref.html
!= 200774-1.html about:blank # really a crashtest
== 201215-1.html 201215-1-ref.html == 201215-1.html 201215-1-ref.html
== 201293-1a.html 201293-1-ref.html == 201293-1a.html 201293-1-ref.html
== 201293-1b.html 201293-1-ref.html == 201293-1b.html 201293-1-ref.html
@ -166,6 +167,27 @@ fails == 25888-3r.html 25888-3r-ref.html # bug 25888
== 240470-1.html 240470-1-ref.html == 240470-1.html 240470-1-ref.html
== 243266-1.html 243266-1-ref.html == 243266-1.html 243266-1-ref.html
== 243302-1.html 243302-1-ref.html == 243302-1.html 243302-1-ref.html
== 243519-1.html 243519-1-ref.html
== 243519-2.html 243519-2-ref.html
== 243519-3.html 243519-3-ref.html
== 243519-4a.html 243519-4-ref.html
== 243519-4b.html 243519-4-ref.html
== 243519-4c.html 243519-4-ref.html
== 243519-4d.html 243519-4-ref.html
== 243519-4e.html 243519-4-ref.html
== 243519-4f.html 243519-4-ref.html
== 243519-5a.html 243519-5-ref.html
== 243519-5b.html 243519-5-ref.html
== 243519-5c.html 243519-5-ref.html
== 243519-5d.html 243519-5-ref.html
== 243519-6.html 243519-6-ref.html
== 243519-7.html 243519-7-ref.html
== 243519-8.svg 243519-8-ref.svg
== 243519-9a.html 243519-9-ref.html
== 243519-9b.html 243519-9-ref.html
== 243519-9c.html 243519-9-ref.html
== 243519-9d.html 243519-9-ref.html
== 243519-9e.html 243519-9-ref.html
== 244135-1.html 244135-1-ref.html == 244135-1.html 244135-1-ref.html
== 244135-2.html 244135-2-ref.html == 244135-2.html 244135-2-ref.html
== 244932-1.html 244932-1-ref.html == 244932-1.html 244932-1-ref.html