зеркало из 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")
|
||||
|
||||
nsRect GetClipRect() { return mClip; }
|
||||
void SetClipRect(const nsRect& aRect) { mClip = aRect; }
|
||||
|
||||
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem);
|
||||
|
|
|
@ -824,6 +824,101 @@ void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
|
|||
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
|
||||
nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame,
|
||||
const nsRegion& aDirtyRegion, nscolor aBackground)
|
||||
|
@ -839,6 +934,24 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
|
|||
nsAutoDisableGetUsedXAssertions disableAssert;
|
||||
rv =
|
||||
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);
|
||||
|
|
|
@ -252,18 +252,3 @@ nsPageContentFrame::IsContainingBlock() const
|
|||
{
|
||||
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,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
virtual PRBool IsContainingBlock() const;
|
||||
|
||||
virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
|
||||
|
@ -74,7 +70,7 @@ public:
|
|||
/**
|
||||
* Get the "type" of the frame
|
||||
*
|
||||
* @see nsGkAtoms::pageFrame
|
||||
* @see nsGkAtoms::pageContentFrame
|
||||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
|
|
|
@ -537,18 +537,17 @@ nsPageFrame::PaintPageContent(nsIRenderingContext& aRenderingContext,
|
|||
nsRect rect = aDirtyRect;
|
||||
float scale = PresContext()->GetPageScale();
|
||||
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);
|
||||
aRenderingContext.Translate(framePos.x, framePos.y);
|
||||
// aPt translates to coords relative to this, then margins translate to
|
||||
// pageContentFrame's coords
|
||||
rect -= framePos;
|
||||
aRenderingContext.Scale(scale, 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 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-1d.html 409659-1-ref.html
|
||||
== 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
|
||||
== 412093-1.html 412093-1-ref.html
|
||||
== 412607-1a.html 412607-1-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче