diff --git a/gfx/public/nsRect.h b/gfx/public/nsRect.h index 281383ed03c..7f5c894b9ad 100644 --- a/gfx/public/nsRect.h +++ b/gfx/public/nsRect.h @@ -159,8 +159,15 @@ struct NS_GFX nsRect { height = NSToCoordRound(height * aScale); return *this;} - nsRect& ScaleRoundOut(const float aScale); - nsRect& ScaleRoundIn(const float aScale); + // Scale by aScale, converting coordinates to integers so that the result + // is the smallest integer-coordinate rectangle containing the unrounded result + nsRect& ScaleRoundOut(float aScale); + // Scale by aScale, converting coordinates to integers so that the result + // is the larges integer-coordinate rectangle contained in the unrounded result + nsRect& ScaleRoundIn(float aScale); + // Scale by aScale, converting coordinates to integers so that the result + // contains the same pixel centers as the unrounded result + nsRect& ScaleRoundPreservingCenters(float aScale); // Helpers for accessing the vertices nsPoint TopLeft() const { return nsPoint(x, y); } diff --git a/gfx/src/nsRect.cpp b/gfx/src/nsRect.cpp index 7eef03bbe1b..3a85303decc 100644 --- a/gfx/src/nsRect.cpp +++ b/gfx/src/nsRect.cpp @@ -181,10 +181,10 @@ void nsRect::Deflate(const nsMargin &aMargin) } // scale the rect but round to smallest containing rect -nsRect& nsRect::ScaleRoundOut(const float aScale) +nsRect& nsRect::ScaleRoundOut(float aScale) { - nscoord right = NSToCoordCeil(float(x + width) * aScale); - nscoord bottom = NSToCoordCeil(float(y + height) * aScale); + nscoord right = NSToCoordCeil(float(XMost()) * aScale); + nscoord bottom = NSToCoordCeil(float(YMost()) * aScale); x = NSToCoordFloor(float(x) * aScale); y = NSToCoordFloor(float(y) * aScale); width = (right - x); @@ -193,10 +193,10 @@ nsRect& nsRect::ScaleRoundOut(const float aScale) } // scale the rect but round to largest contained rect -nsRect& nsRect::ScaleRoundIn(const float aScale) +nsRect& nsRect::ScaleRoundIn(float aScale) { - nscoord right = NSToCoordFloor(float(x + width) * aScale); - nscoord bottom = NSToCoordFloor(float(y + height) * aScale); + nscoord right = NSToCoordFloor(float(XMost()) * aScale); + nscoord bottom = NSToCoordFloor(float(YMost()) * aScale); x = NSToCoordCeil(float(x) * aScale); y = NSToCoordCeil(float(y) * aScale); width = (right - x); @@ -204,6 +204,17 @@ nsRect& nsRect::ScaleRoundIn(const float aScale) return *this; } +nsRect& nsRect::ScaleRoundPreservingCenters(float aScale) +{ + nscoord right = NSToCoordRound(float(XMost()) * aScale); + nscoord bottom = NSToCoordRound(float(YMost()) * aScale); + x = NSToCoordRound(float(x) * aScale); + y = NSToCoordRound(float(y) * aScale); + width = (right - x); + height = (bottom - y); + return *this; +} + #ifdef DEBUG // Diagnostics diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 18ec1ac5a96..e4fe5cb0f21 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -386,11 +386,11 @@ void nsView::DoResetWidgetBounds(PRBool aMoveOnly, } } - nsRect newBounds(NSAppUnitsToIntPixels((mDimBounds.x + offset.x), p2a), - NSAppUnitsToIntPixels((mDimBounds.y + offset.y), p2a), - NSAppUnitsToIntPixels(mDimBounds.width, p2a), - NSAppUnitsToIntPixels(mDimBounds.height, p2a)); - + nsRect viewBounds(mDimBounds + offset); + + nsRect newBounds(viewBounds); + newBounds.ScaleRoundPreservingCenters(1.0f / p2a); + PRBool changedPos = PR_TRUE; PRBool changedSize = PR_TRUE; if (!(mVFlags & NS_VIEW_FLAG_HAS_POSITIONED_WIDGET)) { @@ -412,6 +412,10 @@ void nsView::DoResetWidgetBounds(PRBool aMoveOnly, mWindow->Resize(newBounds.width, newBounds.height, aInvalidateChangedSize); } // else do nothing! } + + nsPoint roundedOffset(NSIntPixelsToAppUnits(newBounds.x, p2a), + NSIntPixelsToAppUnits(newBounds.y, p2a)); + mViewToWidgetOffset = viewBounds.TopLeft() - roundedOffset; } void nsView::SetDimensions(const nsRect& aRect, PRBool aPaint, PRBool aResizeWidget) @@ -858,7 +862,8 @@ nsIWidget* nsIView::GetNearestWidget(nsPoint* aOffset) const // not coincide with v's origin if (aOffset) { nsRect vBounds = v->GetBounds(); - *aOffset = pt + v->GetPosition() - nsPoint(vBounds.x, vBounds.y); + *aOffset = pt + v->GetPosition() - nsPoint(vBounds.x, vBounds.y) - + v->ViewToWidgetOffset(); } return v->GetWidget(); } diff --git a/view/src/nsView.h b/view/src/nsView.h index dcc0823df7a..8d90fafa191 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -218,6 +218,10 @@ public: virtual ~nsView(); + nsPoint ViewToWidgetOffset() const { + return mViewToWidgetOffset; + } + protected: // Do the actual work of ResetWidgetBounds, unconditionally. Don't // call this method if we have no widget. @@ -228,6 +232,7 @@ protected: // mClipRect is relative to the view's origin. nsRect* mClipRect; nsRegion* mDirtyRegion; + nsPoint mViewToWidgetOffset; PRPackedBool mChildRemoved; }; diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index a6d58729c7b..807a52d3415 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -483,8 +483,13 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, ctx->Save(); - ctx->Translate(gfxPoint(NSAppUnitsToIntPixels(viewRect.x, p2a), - NSAppUnitsToIntPixels(viewRect.y, p2a))); + nsPoint vtowoffset = aView->ViewToWidgetOffset(); + ctx->Translate(gfxPoint(gfxFloat(vtowoffset.x) / p2a, + gfxFloat(vtowoffset.y) / p2a)); + + NS_ASSERTION(!viewRect.x && !viewRect.y, "When exactly is this supposed to be non-zero?"); + ctx->Translate(gfxPoint(gfxFloat(viewRect.x) / p2a, + gfxFloat(viewRect.y) / p2a)); nsRegion opaqueRegion; AddCoveringWidgetsToOpaqueRegion(opaqueRegion, mContext, aView);