Relanding bug 380438: Black lines appearing on the Opera Desktop Team Blog comments. r+sr=roc.
authorsharparrow1@yahoo.com
Tue, 22 May 2007 20:45:59 -0700
changeset 1747 106bfb50b016261b986df98c9ba5f192968c0ea3
parent 1746 65e6f70894ebf2f704be3ccdeba095e21cbbd00c
child 1748 0e5bf4fb6cc9c4818c00a15a7c924f152f10867b
push idunknown
push userunknown
push dateunknown
bugs380438
milestone1.9a5pre
Relanding bug 380438: Black lines appearing on the Opera Desktop Team Blog comments. r+sr=roc.
gfx/public/nsRect.h
gfx/src/nsRect.cpp
view/src/nsView.cpp
view/src/nsView.h
view/src/nsViewManager.cpp
--- a/gfx/public/nsRect.h
+++ b/gfx/public/nsRect.h
@@ -154,18 +154,25 @@ struct NS_GFX nsRect {
   nsRect& operator-=(const nsPoint& aPoint) {x -= aPoint.x; y -= aPoint.y; return *this;}
 
   nsRect& operator*=(const float aScale) {x = NSToCoordRound(x * aScale); 
                                           y = NSToCoordRound(y * aScale); 
                                           width = NSToCoordRound(width * aScale); 
                                           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); }
   nsPoint TopRight() const { return nsPoint(XMost(), y); }
   nsPoint BottomLeft() const { return nsPoint(x, YMost()); }
   nsPoint BottomRight() const { return nsPoint(XMost(), YMost()); }
 
   nsSize Size() const { return nsSize(width, height); }
--- a/gfx/src/nsRect.cpp
+++ b/gfx/src/nsRect.cpp
@@ -176,39 +176,50 @@ void nsRect::Deflate(const nsMargin &aMa
 {
   x += aMargin.left;
   y += aMargin.top;
   width -= aMargin.left + aMargin.right;
   height -= aMargin.top + aMargin.bottom;
 }
 
 // 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);
   height = (bottom - y);
   return *this;
 }
 
 // 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);
   height = (bottom - y);
   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
 
 FILE* operator<<(FILE* out, const nsRect& rect)
 {
   nsAutoString tmp;
 
   // Output the coordinates in fractional pixels so they're easier to read
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -381,21 +381,21 @@ void nsView::DoResetWidgetBounds(PRBool 
       // put offset into screen coordinates
       nsRect screenRect(0,0,1,1);
       parentWidget->WidgetToScreen(screenRect, screenRect);
       offset += nsPoint(NSIntPixelsToAppUnits(screenRect.x, p2a),
                         NSIntPixelsToAppUnits(screenRect.y, p2a));
     }
   }
 
-  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)) {
     mVFlags |= NS_VIEW_FLAG_HAS_POSITIONED_WIDGET;
   } else {
     changedPos = curBounds.TopLeft() != newBounds.TopLeft();
     changedSize = curBounds.Size() != newBounds.Size();
   }
@@ -407,16 +407,20 @@ void nsView::DoResetWidgetBounds(PRBool 
     } else {
       mWindow->Move(newBounds.x, newBounds.y);
     }
   } else {
     if (changedSize && !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)
 {
   nsRect dims = aRect;
   dims.MoveBy(mPosX, mPosY);
 
   // Don't use nsRect's operator== here, since it returns true when
@@ -853,17 +857,18 @@ nsIWidget* nsIView::GetNearestWidget(nsP
     return NS_STATIC_CAST(const nsView*, this)->GetViewManager()->GetWidget();
   }
 
   // pt is now the offset from v's origin to this's origin
   // The widget's origin is the top left corner of v's bounds, which may
   // 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();
 }
 
 PRBool nsIView::IsRoot() const
 {
   NS_ASSERTION(mViewManager != nsnull," View manager is null in nsView::IsRoot()");
   return mViewManager->GetRootView() == this;
--- a/view/src/nsView.h
+++ b/view/src/nsView.h
@@ -213,22 +213,27 @@ public:
   // Update the cached RootViewManager for all view manager descendents,
   // If the hierarchy is being removed, aViewManagerParent points to the view
   // manager for the hierarchy's old parent, and will have its mouse grab
   // released if it points to any view in this view hierarchy.
   void InvalidateHierarchy(nsViewManager *aViewManagerParent);
 
   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.
   void DoResetWidgetBounds(PRBool aMoveOnly, PRBool aInvalidateChangedSize);
   
   nsZPlaceholderView* mZParent;
 
   // mClipRect is relative to the view's origin.
   nsRect*      mClipRect;
   nsRegion*    mDirtyRegion;
+  nsPoint      mViewToWidgetOffset;
   PRPackedBool mChildRemoved;
 };
 
 #endif
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -478,18 +478,23 @@ void nsViewManager::Refresh(nsView *aVie
   nsRect damageRect = damageRegion.GetBounds();
   PRInt32 p2a = mContext->AppUnitsPerDevPixel();
 
   nsRefPtr<gfxContext> ctx =
     (gfxContext*) localcx->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
 
   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);
   damageRegion.Sub(damageRegion, opaqueRegion);
 
   RenderViews(aView, *localcx, damageRegion);
 
   ctx->Restore();