зеркало из https://github.com/mozilla/pjs.git
Bug 411585. Traverse all pages after the current page when painting a page, to locate placeholders that we need to traverse in order to paint out-of-flows on the current page. r+sr=dbaron
This commit is contained in:
Родитель
f027bf9559
Коммит
c4eede7145
|
@ -1190,6 +1190,7 @@ public:
|
||||||
NS_DISPLAY_DECL_NAME("Clip")
|
NS_DISPLAY_DECL_NAME("Clip")
|
||||||
|
|
||||||
nsRect GetClipRect() { return mClip; }
|
nsRect GetClipRect() { return mClip; }
|
||||||
|
void SetClipRect(const nsRect& aRect) { mClip = aRect; }
|
||||||
|
|
||||||
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
|
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
|
||||||
nsDisplayItem* aItem);
|
nsDisplayItem* aItem);
|
||||||
|
|
|
@ -824,6 +824,101 @@ void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
aCtx->FillRect(aDirtyRect);
|
aCtx->FillRect(aDirtyRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all leaf display items that are not for descendants of
|
||||||
|
* aBuilder->GetReferenceFrame() from aList, and move all nsDisplayClip
|
||||||
|
* wrappers to their correct locations.
|
||||||
|
* @param aExtraPage the page we constructed aList for
|
||||||
|
* @param aY the Y-coordinate where aPage would be positioned relative
|
||||||
|
* to the main page (aBuilder->GetReferenceFrame()), considering only
|
||||||
|
* the content and ignoring page margins and dead space
|
||||||
|
* @param aList the list that is modified in-place
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
PruneDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aExtraPage, nscoord aY, nsDisplayList* aList)
|
||||||
|
{
|
||||||
|
nsDisplayList newList;
|
||||||
|
// The page which we're really constructing a display list for
|
||||||
|
nsIFrame* mainPage = aBuilder->ReferenceFrame();
|
||||||
|
|
||||||
|
while (PR_TRUE) {
|
||||||
|
nsDisplayItem* i = aList->RemoveBottom();
|
||||||
|
if (!i)
|
||||||
|
break;
|
||||||
|
nsDisplayList* subList = i->GetList();
|
||||||
|
if (subList) {
|
||||||
|
PruneDisplayListForExtraPage(aBuilder, aExtraPage, aY, subList);
|
||||||
|
if (i->GetType() == nsDisplayItem::TYPE_CLIP) {
|
||||||
|
// This might clip an element which should appear on the first
|
||||||
|
// page, and that element might be visible if this uses a 'clip'
|
||||||
|
// property with a negative top.
|
||||||
|
// The clip area needs to be moved because the frame geometry doesn't
|
||||||
|
// put page content frames for adjacent pages vertically adjacent,
|
||||||
|
// there are page margins and dead space between them in print
|
||||||
|
// preview, and in printing all pages are at (0,0)...
|
||||||
|
// XXX we have no way to test this right now that I know of;
|
||||||
|
// the 'clip' property requires an abs-pos element and we never
|
||||||
|
// paint abs-pos elements that start after the main page
|
||||||
|
// (bug 426909).
|
||||||
|
nsDisplayClip* clip = static_cast<nsDisplayClip*>(i);
|
||||||
|
clip->SetClipRect(clip->GetClipRect() + nsPoint(0, aY) -
|
||||||
|
aExtraPage->GetOffsetTo(mainPage));
|
||||||
|
}
|
||||||
|
newList.AppendToTop(i);
|
||||||
|
} else {
|
||||||
|
nsIFrame* f = i->GetUnderlyingFrame();
|
||||||
|
if (f && nsLayoutUtils::IsProperAncestorFrameCrossDoc(mainPage, f)) {
|
||||||
|
// This one is in the page we care about, keep it
|
||||||
|
newList.AppendToTop(i);
|
||||||
|
} else {
|
||||||
|
// We're throwing this away so call its destructor now. The memory
|
||||||
|
// is owned by aBuilder which destroys all items at once.
|
||||||
|
i->nsDisplayItem::~nsDisplayItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aList->AppendToTop(&newList);
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aPage, nscoord aY, nsDisplayList* aList)
|
||||||
|
{
|
||||||
|
nsDisplayList list;
|
||||||
|
// Pass an empty dirty rect since we're only interested in finding
|
||||||
|
// placeholders whose out-of-flows are in the page
|
||||||
|
// aBuilder->GetReferenceFrame(), and the paths to those placeholders
|
||||||
|
// have already been marked as NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO.
|
||||||
|
// Note that we should still do a prune step since we don't want to
|
||||||
|
// rely on dirty-rect checking for correctness.
|
||||||
|
nsresult rv = aPage->BuildDisplayListForStackingContext(aBuilder, nsRect(), &list);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
PruneDisplayListForExtraPage(aBuilder, aPage, aY, &list);
|
||||||
|
aList->AppendToTop(&list);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsIFrame*
|
||||||
|
GetNextPage(nsIFrame* aPageContentFrame)
|
||||||
|
{
|
||||||
|
// XXX ugh
|
||||||
|
nsIFrame* pageFrame = aPageContentFrame->GetParent();
|
||||||
|
NS_ASSERTION(pageFrame->GetType() == nsGkAtoms::pageFrame,
|
||||||
|
"pageContentFrame has unexpected parent");
|
||||||
|
nsIFrame* nextPageFrame = pageFrame->GetNextSibling();
|
||||||
|
if (!nextPageFrame)
|
||||||
|
return nsnull;
|
||||||
|
NS_ASSERTION(nextPageFrame->GetType() == nsGkAtoms::pageFrame,
|
||||||
|
"pageFrame's sibling is not a page frame...");
|
||||||
|
nsIFrame* f = nextPageFrame->GetFirstChild(nsnull);
|
||||||
|
NS_ASSERTION(f, "pageFrame has no page content frame!");
|
||||||
|
NS_ASSERTION(f->GetType() == nsGkAtoms::pageContentFrame,
|
||||||
|
"pageFrame's child is not page content!");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame,
|
nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame,
|
||||||
const nsRegion& aDirtyRegion, nscolor aBackground)
|
const nsRegion& aDirtyRegion, nscolor aBackground)
|
||||||
|
@ -839,6 +934,24 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
|
||||||
nsAutoDisableGetUsedXAssertions disableAssert;
|
nsAutoDisableGetUsedXAssertions disableAssert;
|
||||||
rv =
|
rv =
|
||||||
aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
|
aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv) && aFrame->GetType() == nsGkAtoms::pageContentFrame) {
|
||||||
|
// We may need to paint out-of-flow frames whose placeholders are
|
||||||
|
// on other pages. Add those pages to our display list. Note that
|
||||||
|
// out-of-flow frames can't be placed after their placeholders so
|
||||||
|
// we don't have to process earlier pages. The display lists for
|
||||||
|
// these extra pages are pruned so that only display items for the
|
||||||
|
// page we currently care about (which we would have reached by
|
||||||
|
// following placeholders to their out-of-flows) end up on the list.
|
||||||
|
nsIFrame* page = aFrame;
|
||||||
|
nscoord y = aFrame->GetSize().height;
|
||||||
|
while ((page = GetNextPage(page)) != nsnull) {
|
||||||
|
rv = BuildDisplayListForExtraPage(&builder, page, y, &list);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
break;
|
||||||
|
y += page->GetSize().height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.LeavePresShell(aFrame, dirtyRect);
|
builder.LeavePresShell(aFrame, dirtyRect);
|
||||||
|
|
|
@ -252,18 +252,3 @@ nsPageContentFrame::IsContainingBlock() const
|
||||||
{
|
{
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsPageContentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
||||||
const nsRect& aDirtyRect,
|
|
||||||
const nsDisplayListSet& aLists)
|
|
||||||
{
|
|
||||||
nsDisplayListCollection set;
|
|
||||||
nsresult rv = ViewportFrame::BuildDisplayList(aBuilder, aDirtyRect, set);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return Clip(aBuilder, set, aLists,
|
|
||||||
nsRect(aBuilder->ToReferenceFrame(this), GetSize()));
|
|
||||||
}
|
|
||||||
|
|
|
@ -54,10 +54,6 @@ public:
|
||||||
const nsHTMLReflowState& aMaxSize,
|
const nsHTMLReflowState& aMaxSize,
|
||||||
nsReflowStatus& aStatus);
|
nsReflowStatus& aStatus);
|
||||||
|
|
||||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
||||||
const nsRect& aDirtyRect,
|
|
||||||
const nsDisplayListSet& aLists);
|
|
||||||
|
|
||||||
virtual PRBool IsContainingBlock() const;
|
virtual PRBool IsContainingBlock() const;
|
||||||
|
|
||||||
virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
|
virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
|
||||||
|
@ -74,7 +70,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Get the "type" of the frame
|
* Get the "type" of the frame
|
||||||
*
|
*
|
||||||
* @see nsGkAtoms::pageFrame
|
* @see nsGkAtoms::pageContentFrame
|
||||||
*/
|
*/
|
||||||
virtual nsIAtom* GetType() const;
|
virtual nsIAtom* GetType() const;
|
||||||
|
|
||||||
|
|
|
@ -537,18 +537,17 @@ nsPageFrame::PaintPageContent(nsIRenderingContext& aRenderingContext,
|
||||||
nsRect rect = aDirtyRect;
|
nsRect rect = aDirtyRect;
|
||||||
float scale = PresContext()->GetPageScale();
|
float scale = PresContext()->GetPageScale();
|
||||||
aRenderingContext.PushState();
|
aRenderingContext.PushState();
|
||||||
// Make sure we don't draw where we aren't supposed to draw, especially
|
|
||||||
// when printing selection
|
|
||||||
nsRect clipRect(nsPoint(0, 0), GetSize());
|
|
||||||
clipRect.Deflate(mPD->mReflowMargin);
|
|
||||||
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
|
|
||||||
// aPt translates to coords relative to this, then margins translate to
|
|
||||||
// pageContentFrame's coords
|
|
||||||
nsPoint framePos = aPt + pageContentFrame->GetOffsetTo(this);
|
nsPoint framePos = aPt + pageContentFrame->GetOffsetTo(this);
|
||||||
aRenderingContext.Translate(framePos.x, framePos.y);
|
aRenderingContext.Translate(framePos.x, framePos.y);
|
||||||
|
// aPt translates to coords relative to this, then margins translate to
|
||||||
|
// pageContentFrame's coords
|
||||||
rect -= framePos;
|
rect -= framePos;
|
||||||
aRenderingContext.Scale(scale, scale);
|
aRenderingContext.Scale(scale, scale);
|
||||||
rect.ScaleRoundOut(1.0f / scale);
|
rect.ScaleRoundOut(1.0f / scale);
|
||||||
|
// Make sure we don't draw where we aren't supposed to draw, especially
|
||||||
|
// when printing selection
|
||||||
|
nsRect clipRect(nsPoint(0, 0), pageContentFrame->GetSize());
|
||||||
|
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
|
||||||
|
|
||||||
const nsStyleBorder* border = GetStyleBorder();
|
const nsStyleBorder* border = GetStyleBorder();
|
||||||
const nsStylePadding* padding = GetStylePadding();
|
const nsStylePadding* padding = GetStylePadding();
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<body>
|
||||||
|
<div style="position:absolute; top:0; left:0;">This text should be visible in print preview</div>
|
||||||
|
<div style="height:800px;"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<body>
|
||||||
|
<div style="height:800px;"></div>
|
||||||
|
<div style="position:absolute; top:0; left:0;">This text should be visible in print preview</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<body>
|
||||||
|
<div style="position:absolute; top:0; left:0; width:100px; height:100px; background:black; opacity:0.5;">Hi</div>
|
||||||
|
<div style="height:800px;"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<body>
|
||||||
|
<div style="height:800px;"></div>
|
||||||
|
<div style="opacity:0.5;">
|
||||||
|
<div style="position:absolute; top:0; left:0; width:100px; height:100px; background:black;">Hi</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<body style="margin:0">
|
||||||
|
<div style="position:absolute; top:0; left:0; width:100px; height:100px; background:black;">Hi</div>
|
||||||
|
<div style="height:800px;"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<body style="margin:0">
|
||||||
|
<div style="height:800px;"></div>
|
||||||
|
<div style="position:absolute; clip:rect(-800px 200px 100px 0px);">
|
||||||
|
<div style="position:absolute; top:-800px; left:0; width:100px; height:100px; background:black;">Hi</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -727,6 +727,9 @@ random == 403134-1.html 403134-1-ref.html # bug 405377
|
||||||
!= 409659-1c.html 409659-1-ref.html
|
!= 409659-1c.html 409659-1-ref.html
|
||||||
== 409659-1d.html 409659-1-ref.html
|
== 409659-1d.html 409659-1-ref.html
|
||||||
== 411334-1.xml 411334-1-ref.xml
|
== 411334-1.xml 411334-1-ref.xml
|
||||||
|
== 411585-1.html 411585-1-ref.html
|
||||||
|
== 411585-2.html 411585-2-ref.html
|
||||||
|
fails == 411585-3.html 411585-3-ref.html # bug 426909
|
||||||
== 411792-1.html 411792-1-ref.html
|
== 411792-1.html 411792-1-ref.html
|
||||||
== 412093-1.html 412093-1-ref.html
|
== 412093-1.html 412093-1-ref.html
|
||||||
== 412607-1a.html 412607-1-ref.html
|
== 412607-1a.html 412607-1-ref.html
|
||||||
|
|
Загрузка…
Ссылка в новой задаче