Back out Robert O'Callahan's patch from bug 421885 due to reftest failure.
authorreed@reedloden.com
Fri, 28 Mar 2008 02:32:03 -0700
changeset 13668 06020bb3c2ded43978d5241ede17ec1da7cfe088
parent 13667 7b31e4aa977d482a1891e1c407474b4b0f17c67e
child 13669 bfd50b69f632195b692f68161b0dcb04e715d1d4
push idunknown
push userunknown
push dateunknown
bugs421885
milestone1.9pre
Back out Robert O'Callahan's patch from bug 421885 due to reftest failure.
gfx/public/nsIRenderingContext.h
gfx/public/nsRect.h
gfx/src/nsRect.cpp
gfx/src/thebes/nsThebesImage.cpp
gfx/src/thebes/nsThebesImage.h
gfx/src/thebes/nsThebesRenderingContext.cpp
gfx/src/thebes/nsThebesRenderingContext.h
gfx/thebes/public/gfxPoint.h
layout/base/nsCSSRendering.cpp
layout/reftests/bugs/reftest.list
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
--- a/gfx/public/nsIRenderingContext.h
+++ b/gfx/public/nsIRenderingContext.h
@@ -593,24 +593,21 @@ public:
   virtual void SetTextRunRTL(PRBool aIsRTL) = 0;
 
   /*
    * Tiles an image over an area
    * @param aImage       Image to tile
    * @param aXImageStart x location where the origin (0,0) of the image starts
    * @param aYImageStart y location where the origin (0,0) of the image starts
    * @param aTargetRect  area to draw to
-   * @param aSubimageRect the subimage (in tile space) which we expect to
-   * sample from; may be null to indicate that the whole image is
-   * OK to sample from
    */
   NS_IMETHOD DrawTile(imgIContainer *aImage,
                       nscoord aXImageStart, nscoord aYImageStart,
-                      const nsRect * aTargetRect,
-                      const nsIntRect * aSubimageRect) = 0;
+                      const nsRect * aTargetRect) = 0;
+
 
   /**
    * Get cluster details for a chunk of text.
    *
    * This will fill in the aClusterStarts array with information about
    * what characters are the start of clusters for display.  The
    * information is just a bitfield that is set to 1 if the character
    * is the start of a cluster.  aClusterStarts must already be
--- a/gfx/public/nsRect.h
+++ b/gfx/public/nsRect.h
@@ -172,20 +172,16 @@ struct NS_GFX nsRect {
                                           y = NSToCoordRound(y * aScale); 
                                           width = NSToCoordRound(width * aScale); 
                                           height = NSToCoordRound(height * aScale); 
                                           return *this;}
 
   // 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 the inverse of aScale, converting coordinates to integers so that the result
-  // is the smallest integer-coordinate rectangle containing the unrounded result.
-  // More accurate than ScaleRoundOut(1.0/aScale).
-  nsRect& ScaleRoundOutInverse(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 the inverse of aScale, converting coordinates to integers so that
   // the result contains the same pixel centers as the unrounded result
   nsRect& ScaleRoundPreservingCentersInverse(float aScale);
 
   // Helpers for accessing the vertices
--- a/gfx/src/nsRect.cpp
+++ b/gfx/src/nsRect.cpp
@@ -180,27 +180,16 @@ nsRect& nsRect::ScaleRoundOut(float aSca
   nscoord bottom = NSToCoordCeil(float(YMost()) * aScale);
   x = NSToCoordFloor(float(x) * aScale);
   y = NSToCoordFloor(float(y) * aScale);
   width = (right - x);
   height = (bottom - y);
   return *this;
 }
 
-nsRect& nsRect::ScaleRoundOutInverse(float 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(float 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);
--- a/gfx/src/thebes/nsThebesImage.cpp
+++ b/gfx/src/thebes/nsThebesImage.cpp
@@ -615,34 +615,32 @@ nsThebesImage::Draw(nsIRenderingContext 
     return NS_OK;
 }
 
 nsresult
 nsThebesImage::ThebesDrawTile(gfxContext *thebesContext,
                               nsIDeviceContext* dx,
                               const gfxPoint& offset,
                               const gfxRect& targetRect,
-                              const nsIntRect& aSubimageRect,
                               const PRInt32 xPadding,
                               const PRInt32 yPadding)
 {
     NS_ASSERTION(xPadding >= 0 && yPadding >= 0, "negative padding");
 
     if (targetRect.size.width <= 0.0 || targetRect.size.height <= 0.0)
         return NS_OK;
 
     // don't do anything if we have a transparent pixel source
     if (mSinglePixel && mSinglePixelColor.a == 0.0)
         return NS_OK;
 
     PRBool doSnap = !(thebesContext->CurrentMatrix().HasNonTranslation());
     PRBool hasPadding = ((xPadding != 0) || (yPadding != 0));
-    gfxImageSurface::gfxImageFormat format = mFormat;
-    
-    gfxPoint tmpOffset = offset;
+
+    nsRefPtr<gfxASurface> tmpSurfaceGrip;
 
     if (mSinglePixel && !hasPadding) {
         thebesContext->SetColor(mSinglePixelColor);
     } else {
         nsRefPtr<gfxASurface> surface;
         PRInt32 width, height;
 
         if (hasPadding) {
@@ -650,136 +648,49 @@ nsThebesImage::ThebesDrawTile(gfxContext
              * and render the image into it first.  Then we'll tile that surface. */
             width = mWidth + xPadding;
             height = mHeight + yPadding;
 
             // Reject over-wide or over-tall images.
             if (!AllowedImageSize(width, height))
                 return NS_ERROR_FAILURE;
 
-            format = gfxASurface::ImageFormatARGB32;
-            surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
-                    gfxIntSize(width, height), format);
+            surface = new gfxImageSurface(gfxIntSize(width, height),
+                                          gfxASurface::ImageFormatARGB32);
             if (!surface || surface->CairoStatus()) {
                 return NS_ERROR_OUT_OF_MEMORY;
             }
 
+            tmpSurfaceGrip = surface;
+
             gfxContext tmpContext(surface);
             if (mSinglePixel) {
                 tmpContext.SetColor(mSinglePixelColor);
             } else {
                 tmpContext.SetSource(ThebesSurface());
             }
             tmpContext.SetOperator(gfxContext::OPERATOR_SOURCE);
             tmpContext.Rectangle(gfxRect(0, 0, mWidth, mHeight));
             tmpContext.Fill();
         } else {
             width = mWidth;
             height = mHeight;
             surface = ThebesSurface();
         }
-        
+
+        gfxMatrix patMat;
+        gfxPoint p0;
+
+        p0.x = - floor(offset.x + 0.5);
+        p0.y = - floor(offset.y + 0.5);
         // Scale factor to account for CSS pixels; note that the offset (and 
         // therefore p0) is in device pixels, while the width and height are in
         // CSS pixels.
         gfxFloat scale = gfxFloat(dx->AppUnitsPerDevPixel()) /
                          gfxFloat(nsIDeviceContext::AppUnitsPerCSSPixel());
-
-        if ((aSubimageRect.width < width || aSubimageRect.height < height) &&
-            (thebesContext->CurrentMatrix().HasNonTranslation() || scale != 1.0)) {
-            // Some of the source image should not be drawn, and we're going
-            // to be doing more than just translation, so we might accidentally
-            // sample the non-drawn pixels. Avoid that by creating a
-            // temporary image representing the portion that will be drawn,
-            // with built-in padding since we can't use EXTEND_PAD and
-            // EXTEND_REPEAT at the same time for different axes.
-            PRInt32 padX = aSubimageRect.width < width ? 1 : 0;
-            PRInt32 padY = aSubimageRect.height < height ? 1 : 0;
-            PRInt32 tileWidth = PR_MIN(aSubimageRect.width, width);
-            PRInt32 tileHeight = PR_MIN(aSubimageRect.height, height);
-            
-            // This tmpSurface will contain a snapshot of the repeated
-            // tile image at (aSubimageRect.x, aSubimageRect.y,
-            // tileWidth, tileHeight), with padX padding added to the left
-            // and right sides and padY padding added to the top and bottom
-            // sides.
-            nsRefPtr<gfxASurface> tmpSurface;
-            tmpSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
-                    gfxIntSize(tileWidth + 2*padX, tileHeight + 2*padY), format);
-            if (!tmpSurface || tmpSurface->CairoStatus()) {
-                return NS_ERROR_OUT_OF_MEMORY;
-            }
-
-            gfxContext tmpContext(tmpSurface);
-            tmpContext.SetOperator(gfxContext::OPERATOR_SOURCE);
-            gfxPattern pat(surface);
-            pat.SetExtend(gfxPattern::EXTEND_REPEAT);
-            
-            // Copy the needed portion of the source image to the temporary
-            // surface. We also copy over horizontal and/or vertical padding
-            // strips one pixel wide, plus the corner pixels if necessary.
-            // So in the most general case the temporary surface ends up
-            // looking like
-            //     P P P ... P P P
-            //     P X X ... X X P
-            //     P X X ... X X P
-            //     ...............
-            //     P X X ... X X P
-            //     P X X ... X X P
-            //     P P P ... P P P
-            // Where each P pixel has the color of its nearest source X
-            // pixel. We implement this as a loop over all nine possible
-            // areas, [padding, body, padding] x [padding, body, padding].
-            // Note that we will not need padding on both axes unless
-            // we are painting just a single tile, in which case this
-            // will hardly ever get called since nsCSSRendering converts
-            // the single-tile case to nsLayoutUtils::DrawImage. But this
-            // could be called on other paths (XUL trees?) and it's simpler
-            // and clearer to do it the general way.
-            PRInt32 destY = 0;
-            for (PRInt32 y = -1; y <= 1; ++y) {
-                PRInt32 stripHeight = y == 0 ? tileHeight : padY;
-                if (stripHeight == 0)
-                    continue;
-                PRInt32 srcY = y == 1 ? aSubimageRect.YMost() - padY : aSubimageRect.y;
-                
-                PRInt32 destX = 0;
-                for (PRInt32 x = -1; x <= 1; ++x) {
-                    PRInt32 stripWidth = x == 0 ? tileWidth : padX;
-                    if (stripWidth == 0)
-                        continue;
-                    PRInt32 srcX = x == 1 ? aSubimageRect.XMost() - padX : aSubimageRect.x;
-
-                    gfxMatrix patMat;
-                    patMat.Translate(gfxPoint(srcX - destX, srcY - destY));
-                    pat.SetMatrix(patMat);
-                    tmpContext.SetPattern(&pat);
-                    tmpContext.Rectangle(gfxRect(destX, destY, stripWidth, stripHeight));
-                    tmpContext.Fill();
-                    tmpContext.NewPath();
-                    
-                    destX += stripWidth;
-                }
-                destY += stripHeight;
-            }
-
-            // tmpOffset was the top-left of the old tile image. Make it
-            // the top-left of the new tile image. Note that tmpOffset is
-            // in destination coordinate space so we have to scale our
-            // CSS pixels.
-            tmpOffset += gfxPoint(aSubimageRect.x - padX, aSubimageRect.y - padY)/scale;
-            
-            surface = tmpSurface;
-        }
-
-        gfxMatrix patMat;
-        gfxPoint p0;
-
-        p0.x = - floor(tmpOffset.x + 0.5);
-        p0.y = - floor(tmpOffset.y + 0.5);
         patMat.Scale(scale, scale);
         patMat.Translate(p0);
 
         gfxPattern pat(surface);
         pat.SetExtend(gfxPattern::EXTEND_REPEAT);
         pat.SetMatrix(patMat);
 
 #ifndef XP_MACOSX
@@ -789,17 +700,17 @@ nsThebesImage::ThebesDrawTile(gfxContext
             pat.SetFilter(0);
         }
 #endif
 
         thebesContext->SetPattern(&pat);
     }
 
     gfxContext::GraphicsOperator op = thebesContext->CurrentOperator();
-    if (op == gfxContext::OPERATOR_OVER && format == gfxASurface::ImageFormatRGB24)
+    if (op == gfxContext::OPERATOR_OVER && mFormat == gfxASurface::ImageFormatRGB24)
         thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE);
 
     thebesContext->NewPath();
     thebesContext->Rectangle(targetRect, doSnap);
     thebesContext->Fill();
 
     thebesContext->SetOperator(op);
     thebesContext->SetColor(gfxRGBA(0,0,0,0));
--- a/gfx/src/thebes/nsThebesImage.h
+++ b/gfx/src/thebes/nsThebesImage.h
@@ -79,17 +79,16 @@ public:
                     const gfxRect &aSourceRect,
                     const gfxRect &aSubimageRect,
                     const gfxRect &aDestRect);
 
     nsresult ThebesDrawTile(gfxContext *thebesContext,
                             nsIDeviceContext* dx,
                             const gfxPoint& aOffset,
                             const gfxRect& aTileRect,
-                            const nsIntRect& aSubimageRect,
                             const PRInt32 aXPadding,
                             const PRInt32 aYPadding);
 
     virtual PRInt8 GetAlphaDepth();
     virtual void* GetBitInfo();
     NS_IMETHOD LockImagePixels(PRBool aMaskPixels);
     NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
 
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -773,18 +773,17 @@ nsThebesRenderingContext::PopFilter()
 
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesRenderingContext::DrawTile(imgIContainer *aImage,
                                    nscoord twXOffset, nscoord twYOffset,
-                                   const nsRect *twTargetRect,
-                                   const nsIntRect *subimageRect)
+                                   const nsRect *twTargetRect)
 {
     PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::DrawTile %p %f %f [%f,%f,%f,%f]\n",
                                          this, aImage, FROM_TWIPS(twXOffset), FROM_TWIPS(twYOffset),
                                          FROM_TWIPS(twTargetRect->x), FROM_TWIPS(twTargetRect->y),
                                          FROM_TWIPS(twTargetRect->width), FROM_TWIPS(twTargetRect->height)));
 
     nscoord containerWidth, containerHeight;
     aImage->GetWidth(&containerWidth);
@@ -809,44 +808,28 @@ nsThebesRenderingContext::DrawTile(imgIC
      * so we need to make sure that there is the right amount of padding
      * in between each tile of the nsIImage.  This problem goes away
      * when we change the way the GIF decoder works to have it store
      * full frames that are ready to be composited.
      */
     PRInt32 xPadding = 0;
     PRInt32 yPadding = 0;
 
-    nsIntRect tmpSubimageRect;
-    if (subimageRect) {
-        tmpSubimageRect = *subimageRect;
-    } else {
-        tmpSubimageRect = nsIntRect(0, 0, containerWidth, containerHeight);
-    }
-
     if (imgFrameRect.width != containerWidth ||
         imgFrameRect.height != containerHeight)
     {
         xPadding = containerWidth - imgFrameRect.width;
         yPadding = containerHeight - imgFrameRect.height;
 
-        // XXXroc shouldn't we be adding to 'phase' here? it's tbe origin
-        // at which the image origin should be drawn, and ThebesDrawTile
-        // just draws the origin of its "frame" there, so we should be
-        // adding imgFrameRect.x/y. so that the imgFrame draws in the
-        // right place.
         phase.x -= imgFrameRect.x;
         phase.y -= imgFrameRect.y;
-
-        tmpSubimageRect.x -= imgFrameRect.x;
-        tmpSubimageRect.y -= imgFrameRect.y;
     }
 
     return thebesImage->ThebesDrawTile (mThebes, mDeviceContext, phase,
                                         GFX_RECT_FROM_TWIPS_RECT(*twTargetRect),
-                                        tmpSubimageRect,
                                         xPadding, yPadding);
 }
 
 //
 // text junk
 //
 NS_IMETHODIMP
 nsThebesRenderingContext::SetRightToLeftText(PRBool aIsRTL)
--- a/gfx/src/thebes/nsThebesRenderingContext.h
+++ b/gfx/src/thebes/nsThebesRenderingContext.h
@@ -180,17 +180,17 @@ public:
 
     virtual void* GetNativeGraphicData(GraphicDataType aType);
 
     NS_IMETHOD PushTranslation(PushedTranslation* aState);
     NS_IMETHOD PopTranslation(PushedTranslation* aState);
     NS_IMETHOD SetTranslation(nscoord aX, nscoord aY);
 
     NS_IMETHOD DrawTile(imgIContainer *aImage, nscoord aXOffset, nscoord aYOffset,
-                        const nsRect * aTargetRect, const nsIntRect * aSubimageRect);
+                        const nsRect * aTargetRect);
     NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
     NS_IMETHOD GetRightToLeftText(PRBool* aIsRTL);
     virtual void SetTextRunRTL(PRBool aIsRTL);
 
     NS_IMETHOD GetClusterInfo(const PRUnichar *aText,
                               PRUint32 aLength,
                               PRUint8 *aClusterStarts);
     virtual PRInt32 GetPosition(const PRUnichar *aText,
--- a/gfx/thebes/public/gfxPoint.h
+++ b/gfx/thebes/public/gfxPoint.h
@@ -115,21 +115,16 @@ struct THEBES_API gfxPoint {
     void MoveTo(gfxFloat aX, gfxFloat aY) { x = aX; y = aY; }
 
     int operator==(const gfxPoint& p) const {
         return ((x == p.x) && (y == p.y));
     }
     int operator!=(const gfxPoint& p) const {
         return ((x != p.x) || (y != p.y));
     }
-    const gfxPoint& operator+=(const gfxPoint& p) {
-        x += p.x;
-        y += p.y;
-        return *this;
-    }
     gfxPoint operator+(const gfxPoint& p) const {
         return gfxPoint(x + p.x, y + p.y);
     }
     gfxPoint operator+(const gfxSize& s) const {
         return gfxPoint(x + s.width, y + s.height);
     }
     gfxPoint operator-(const gfxPoint& p) const {
         return gfxPoint(x - p.x, y - p.y);
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -3899,33 +3899,29 @@ nsCSSRendering::PaintBackgroundWithSC(ns
     NS_ASSERTION(drawRect.x >= absTileRect.x && drawRect.y >= absTileRect.y,
                  "Bogus intersection");
     NS_ASSERTION(drawRect.x < absTileRect.x + tileWidth,
                  "Bogus x coord for draw rect");
     NS_ASSERTION(drawRect.y < absTileRect.y + tileHeight,
                  "Bogus y coord for draw rect");
     // Figure out whether we can get away with not tiling at all.
     nsRect sourceRect = drawRect - absTileRect.TopLeft();
-    // Compute the subimage rectangle that we expect to be sampled.
-    // This is the tile rectangle, clipped to the bgClipArea, and then
-    // passed in relative to the image top-left.
-    nsRect destRect; // The rectangle we would draw ignoring dirty-rect
-    destRect.IntersectRect(absTileRect, bgClipArea);
-    nsRect subimageRect = destRect - aBorderArea.TopLeft() - tileRect.TopLeft();
     if (sourceRect.XMost() <= tileWidth && sourceRect.YMost() <= tileHeight) {
       // The entire drawRect is contained inside a single tile; just
       // draw the corresponding part of the image once.
+      // Pass in the subimage rectangle that we expect to be sampled.
+      // This is the tile rectangle, clipped to the bgClipArea, and then
+      // passed in relative to the image top-left.
+      nsRect destRect; // The rectangle we would draw ignoring dirty-rect
+      destRect.IntersectRect(absTileRect, bgClipArea);
+      nsRect subimageRect = destRect - aBorderArea.TopLeft() - tileRect.TopLeft();
       nsLayoutUtils::DrawImage(&aRenderingContext, image,
               destRect, drawRect, &subimageRect);
     } else {
-      // Note that the subimage is in tile space so it may cover
-      // multiple tiles of the image.
-      subimageRect.ScaleRoundOutInverse(nsIDeviceContext::AppUnitsPerCSSPixel());
-      aRenderingContext.DrawTile(image, absTileRect.x, absTileRect.y,
-              &drawRect, &subimageRect);
+      aRenderingContext.DrawTile(image, absTileRect.x, absTileRect.y, &drawRect);
     }
   }
 
   ctx->Restore();
 
 }
 
 void
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -768,17 +768,16 @@ fails == 413027-3.html 413027-3-ref.html
 == 420069-1.html 420069-1-ref.html
 == 420069-2.html 420069-2-ref.html
 == 420351-1.html 420351-1-ref.html
 == 421069.html 421069-ref.html
 == 421069.html 421069-ref2.html
 == 421069-ref.html 421069-ref2.html
 == 421234-1.html 421234-1-ref.html
 == 421419-1.html 421419-1-ref.html
-== 421885-1.xml 421885-1-ref.xml
 == 421955-1.html 421955-1-ref.html
 == 422394-1.html 422394-1-ref.html
 == 423130-1.html 423130-1-ref.html
 == 423385-1.html 423385-1-ref.html
 == 423599-1.html 423599-1-ref.html
 == 423676-1.html 423676-1-ref.html
 == 424074-1.xul 424074-1-ref.xul
 != 424074-1.xul 424074-1-ref2.xul
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -3652,29 +3652,29 @@ nsTreeBodyFrame::PaintProgressMeter(PRIn
     else if (intValue > 100)
       intValue = 100;
 
     meterRect.width = NSToCoordRound((float)intValue / 100 * meterRect.width);
     PRBool useImageRegion = PR_TRUE;
     nsCOMPtr<imgIContainer> image;
     GetImage(aRowIndex, aColumn, PR_TRUE, meterContext, useImageRegion, getter_AddRefs(image));
     if (image)
-      aRenderingContext.DrawTile(image, 0, 0, &meterRect, nsnull);
+      aRenderingContext.DrawTile(image, 0, 0, &meterRect);
     else
       aRenderingContext.FillRect(meterRect);
   }
   else if (state == nsITreeView::PROGRESS_UNDETERMINED) {
     // Adjust the rect for its border and padding.
     AdjustForBorderPadding(meterContext, meterRect);
 
     PRBool useImageRegion = PR_TRUE;
     nsCOMPtr<imgIContainer> image;
     GetImage(aRowIndex, aColumn, PR_TRUE, meterContext, useImageRegion, getter_AddRefs(image));
     if (image)
-      aRenderingContext.DrawTile(image, 0, 0, &meterRect, nsnull);
+      aRenderingContext.DrawTile(image, 0, 0, &meterRect);
   }
 }
 
 
 void
 nsTreeBodyFrame::PaintDropFeedback(const nsRect&        aDropFeedbackRect,
                                    nsPresContext*      aPresContext,
                                    nsIRenderingContext& aRenderingContext,