Bug 513082. Take advantage of our knowledge that nsDisplayClip, when used in a blitting scrolling frame, must snap to device pixels, to get more accurate blit regions. r=dbaron

This commit is contained in:
Robert O'Callahan 2009-11-04 07:39:42 +13:00
parent b29ea58b95
commit 7e04a64cff
3 changed files with 21 additions and 6 deletions

View File

@ -1180,8 +1180,16 @@ AddItemsToRegion(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
// If the clipping frame is moving, then it isn't clipping any
// non-moving content (see ApplyAbsPosClipping), so we don't need
// to do anything special, but we should not restrict aClipRect.
if (!aBuilder->IsMovingFrame(clipItem->GetClippingFrame())) {
clip.IntersectRect(clip, clipItem->GetClipRect());
nsIFrame* clipFrame = clipItem->GetClippingFrame();
if (!aBuilder->IsMovingFrame(clipFrame)) {
nscoord appUnitsPerDevPixel = clipFrame->PresContext()->AppUnitsPerDevPixel();
// We know the nsDisplayClip will snap because we're in a context
// where pixels can be blitted and we don't traverse down through
// an nsDisplayTransform.
nsRect snappedClip =
clipItem->GetClipRect().ToNearestPixels(appUnitsPerDevPixel).
ToAppUnits(appUnitsPerDevPixel);
clip.IntersectRect(clip, snappedClip);
// Invalidate the translation of the source area that was clipped out
nsRegion clippedOutSource;

View File

@ -197,8 +197,8 @@ function testSimpleScrollWithSubpixelOffset2(blitRegion, paintRegion) {
ok(paintRegion.containsRegion(new Region([[0,181,200,200]])),
"Should repaint area that was scrolled into view: " + paintRegion.toString());
// Check that we're not repainting anything in the area that's blitted
todo(!paintRegion.intersectsRect([0,0,200,180]),
"Should not repaint area that was blitted: " + paintRegion.toString());
ok(!paintRegion.intersectsRect([0,0,200,180]),
"Should not repaint area that was blitted: " + paintRegion.toString());
}
function testSimpleScrollWithSubpixelOffset3(blitRegion, paintRegion) {
@ -221,8 +221,8 @@ function testSimpleScrollWithSubpixelOffset4(blitRegion, paintRegion) {
ok(paintRegion.containsRegion(new Region([[181,0,200,200]])),
"Should repaint area that was scrolled into view: " + paintRegion.toString());
// Check that we're not repainting anything in the area that's blitted
todo(!paintRegion.intersectsRect([0,0,180,200]),
"Should not repaint area that was blitted: " + paintRegion.toString());
ok(!paintRegion.intersectsRect([0,0,180,200]),
"Should not repaint area that was blitted: " + paintRegion.toString());
}
function testMovingClipArea(blitRegion, paintRegion) {

View File

@ -1480,6 +1480,13 @@ void nsViewManager::GetRegionsForBlit(nsView* aView, nsPoint aDelta,
nsView* displayRoot = GetDisplayRootFor(aView);
nsPoint displayOffset = aView->GetParent()->GetOffsetTo(displayRoot);
nsRect parentBounds = aView->GetParent()->GetDimensions() + displayOffset;
// The area clipped by the scrolling view is snapped to device pixels
// (in nsThebesRenderingContext::SetClipRect), so snap the bound here
// that we use to compute the blit and repaint regions
PRInt32 p2a = mContext->AppUnitsPerDevPixel();
parentBounds = parentBounds.ToNearestPixels(p2a).ToAppUnits(p2a);
if (IsPainting() || !mObserver) {
// Be simple and safe
aBlitRegion->SetEmpty();