diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index b370a3f4ebd..5f3a100cdc6 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -658,9 +658,10 @@ public: void OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion); /** * Paint the list to the rendering context. We assume that (0,0) in aCtx - * corresponds to the origin of the reference frame. The rectangle in - * aDirtyRect is painted, which *must* be contained in the dirty rect - * used to construct the display list. + * corresponds to the origin of the reference frame. For best results, + * aCtx's current transform should make (0,0) pixel-aligned. The + * rectangle in aDirtyRect is painted, which *must* be contained in the + * dirty rect used to construct the display list. */ void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect) const; diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 26d4e36270e..aadd7c88d3b 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -394,7 +394,8 @@ public: * Given aFrame, the root frame of a stacking context, paint it and its * descendants to aRenderingContext. * @param aRenderingContext a rendering context translated so that (0,0) - * is the origin of aFrame + * is the origin of aFrame; for best results, (0,0) should transform + * to pixel-aligned coordinates * @param aDirtyRegion the region that must be painted, in the coordinates * of aFrame * @param aBackground paint the dirty area with this color before drawing diff --git a/view/public/nsIViewObserver.h b/view/public/nsIViewObserver.h index 224379cab33..4093de262fc 100644 --- a/view/public/nsIViewObserver.h +++ b/view/public/nsIViewObserver.h @@ -59,7 +59,10 @@ public: /* called when the observer needs to paint. This paints the entire * frame subtree rooted at the view, including frame subtrees from * subdocuments. - * @param aRenderingContext rendering context to paint to + * @param aRenderingContext rendering context to paint to; the origin + * of the view is painted at (0,0) in the rendering context's current + * transform. For best results this should transform to pixel-aligned + * coordinates. * @param aDirtyRegion the region to be painted, in the coordinates of aRootView * @return error status */ diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 5b9845281f7..b1cf8a4cf80 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -596,9 +596,25 @@ void nsViewManager::RenderViews(nsView *aView, nsIRenderingContext& aRC, nsPoint offsetToRoot = aView->GetOffsetTo(displayRoot); nsRegion damageRegion(aRegion); damageRegion.MoveBy(offsetToRoot); - + + gfxContext* ctx = aRC.ThebesContext(); + nsCOMPtr dc; + aRC.GetDeviceContext(*getter_AddRefs(dc)); + double appPerDev = dc->AppUnitsPerDevPixel(); + gfxRect r(-offsetToRoot.x/appPerDev, -offsetToRoot.y/appPerDev, 1.0, 1.0); + aRC.PushState(); - aRC.Translate(-offsetToRoot.x, -offsetToRoot.y); + // Translate by the pixel-snapped offsetToRoot so that aRC's (0,0) will + // be aligned to pixel boundaries. We use gfx pixel-snapping here to + // ensure that the snapping we do here is consistent with other gfx + // snapping. For example if someone drew a border around the outside + // of aView, we want our (0,0) to be the inside top-left of that + // border. + if (ctx->UserToDevicePixelSnapped(r)) { + ctx->Translate(ctx->DeviceToUser(r).pos); + } else { + aRC.Translate(-offsetToRoot.x, -offsetToRoot.y); + } mObserver->Paint(displayRoot, &aRC, damageRegion); aRC.PopState(); }