diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 3025c09a7b3..25b81b0b121 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -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; diff --git a/layout/base/tests/scrolling_helper.html b/layout/base/tests/scrolling_helper.html index 33b5fb548f8..3b974ee2b44 100644 --- a/layout/base/tests/scrolling_helper.html +++ b/layout/base/tests/scrolling_helper.html @@ -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) { diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 294e119a467..e4b87e90450 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -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();