Bug 885939 - Part 1: Scale SVG images using the graphics context matrix instead of the viewport. r=dholbert, a=bajaj
authorSeth Fowler <seth@mozilla.com>
Tue, 16 Jul 2013 15:41:30 -0400
changeset 148016 fc9b10335396c9df5789eee234deeb1d19c85fca
parent 148015 6e41eabc11332b3cbadefca63f8c0fe60b1e5b44
child 148017 44c000c77e9da69318c0b84af5ff23496b2d7e62
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, bajaj
bugs885939
milestone24.0a2
Bug 885939 - Part 1: Scale SVG images using the graphics context matrix instead of the viewport. r=dholbert, a=bajaj
image/src/VectorImage.cpp
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -224,28 +224,31 @@ private:
 
 NS_IMPL_ISUPPORTS1(SVGLoadEventListener, nsIDOMEventListener)
 
 // Helper-class: SVGDrawingCallback
 class SVGDrawingCallback : public gfxDrawingCallback {
 public:
   SVGDrawingCallback(SVGDocumentWrapper* aSVGDocumentWrapper,
                      const nsIntRect& aViewport,
+                     const gfxSize& aScale,
                      uint32_t aImageFlags) :
     mSVGDocumentWrapper(aSVGDocumentWrapper),
     mViewport(aViewport),
+    mScale(aScale),
     mImageFlags(aImageFlags)
   {}
   virtual bool operator()(gfxContext* aContext,
                             const gfxRect& aFillRect,
                             const gfxPattern::GraphicsFilter& aFilter,
                             const gfxMatrix& aTransform);
 private:
   nsRefPtr<SVGDocumentWrapper> mSVGDocumentWrapper;
   const nsIntRect mViewport;
+  const gfxSize   mScale;
   uint32_t        mImageFlags;
 };
 
 // Based loosely on nsSVGIntegrationUtils' PaintFrameCallback::operator()
 bool
 SVGDrawingCallback::operator()(gfxContext* aContext,
                                const gfxRect& aFillRect,
                                const gfxPattern::GraphicsFilter& aFilter,
@@ -265,16 +268,17 @@ SVGDrawingCallback::operator()(gfxContex
 
   // Clip to aFillRect so that we don't paint outside.
   aContext->NewPath();
   aContext->Rectangle(aFillRect);
   aContext->Clip();
 
   gfxContextMatrixAutoSaveRestore contextMatrixRestorer(aContext);
   aContext->Multiply(gfxMatrix(aTransform).Invert());
+  aContext->Scale(1.0 / mScale.width, 1.0 / mScale.height);
 
   nsPresContext* presContext = presShell->GetPresContext();
   MOZ_ASSERT(presContext, "pres shell w/out pres context");
 
   nsRect svgRect(presContext->DevPixelsToAppUnits(mViewport.x),
                  presContext->DevPixelsToAppUnits(mViewport.y),
                  presContext->DevPixelsToAppUnits(mViewport.width),
                  presContext->DevPixelsToAppUnits(mViewport.height));
@@ -692,58 +696,53 @@ VectorImage::Draw(gfxContext* aContext,
   AutoSVGRenderingState autoSVGState(aSVGContext,
                                      time,
                                      mSVGDocumentWrapper->GetRootSVGElem());
 
   // gfxUtils::DrawPixelSnapped may rasterize this image to a temporary surface
   // if we hit the tiling path. Unfortunately, the temporary surface isn't
   // created at the size at which we'll ultimately draw, causing fuzzy output.
   // To fix this we pre-apply the transform's scaling to the drawing parameters
-  // and then remove the scaling from the transform, so the fact that temporary
+  // and remove the scaling from the transform, so the fact that temporary
   // surfaces won't take the scaling into account doesn't matter. (Bug 600207.)
   gfxSize scale(aUserSpaceToImageSpace.ScaleFactors(true));
   gfxPoint translation(aUserSpaceToImageSpace.GetTranslation());
 
-  // Rescale everything.
-  nsIntSize scaledViewport(aViewportSize.width / scale.width,
-                           aViewportSize.height / scale.height);
-  gfxIntSize scaledViewportGfx(scaledViewport.width, scaledViewport.height);
-  nsIntRect scaledSubimage(aSubimage);
-  scaledSubimage.ScaleRoundOut(1.0 / scale.width, 1.0 / scale.height);
-
   // Remove the scaling from the transform.
   gfxMatrix unscale;
   unscale.Translate(gfxPoint(translation.x / scale.width,
                              translation.y / scale.height));
   unscale.Scale(1.0 / scale.width, 1.0 / scale.height);
   unscale.Translate(-translation);
   gfxMatrix unscaledTransform(aUserSpaceToImageSpace * unscale);
 
-  mSVGDocumentWrapper->UpdateViewportBounds(scaledViewport);
+  mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize);
   mSVGDocumentWrapper->FlushImageTransformInvalidation();
 
-  // Based on imgFrame::Draw
-  gfxRect sourceRect = unscaledTransform.Transform(aFill);
-  gfxRect imageRect(0, 0, scaledViewport.width, scaledViewport.height);
-  gfxRect subimage(scaledSubimage.x, scaledSubimage.y,
-                   scaledSubimage.width, scaledSubimage.height);
-
+  // Rescale drawing parameters.
+  gfxIntSize drawableSize(aViewportSize.width / scale.width,
+                          aViewportSize.height / scale.height);
+  gfxRect drawableSourceRect = unscaledTransform.Transform(aFill);
+  gfxRect drawableImageRect(0, 0, drawableSize.width, drawableSize.height);
+  gfxRect drawableSubimage(aSubimage.x, aSubimage.y,
+                           aSubimage.width, aSubimage.height);
+  drawableSubimage.ScaleRoundOut(1.0 / scale.width, 1.0 / scale.height);
 
   nsRefPtr<gfxDrawingCallback> cb =
     new SVGDrawingCallback(mSVGDocumentWrapper,
-                           nsIntRect(nsIntPoint(0, 0), scaledViewport),
+                           nsIntRect(nsIntPoint(0, 0), aViewportSize),
+                           scale,
                            aFlags);
 
-  nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, scaledViewportGfx);
+  nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, drawableSize);
 
-  gfxUtils::DrawPixelSnapped(aContext, drawable,
-                             unscaledTransform,
-                             subimage, sourceRect, imageRect, aFill,
-                             gfxASurface::ImageFormatARGB32, aFilter,
-                             aFlags);
+  gfxUtils::DrawPixelSnapped(aContext, drawable, unscaledTransform,
+                             drawableSubimage, drawableSourceRect,
+                             drawableImageRect, aFill,
+                             gfxASurface::ImageFormatARGB32, aFilter, aFlags);
 
   MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now");
   mRenderingObserver->ResumeHonoringInvalidations();
 
   return NS_OK;
 }
 
 //******************************************************************************