Bug 1106602 - Part 1: Use pretransform dest rect as default SVG-as-image viewport. r=dholbert, a=sledru
authorSeth Fowler <seth@mozilla.com>
Mon, 15 Dec 2014 15:44:13 -0800
changeset 242470 83bac3bdc5e36036e715c2561ef8d4f6e856427c
parent 242469 0f00bfa7e7ecbdd46d6e5e4645aa4c4d50714380
child 242471 823d8397f3fecb9a8e230bb1510de8e5f06d5506
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, sledru
bugs1106602
milestone36.0a2
Bug 1106602 - Part 1: Use pretransform dest rect as default SVG-as-image viewport. r=dholbert, a=sledru
layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5439,30 +5439,37 @@ struct SnappedImageDrawingParameters {
   // A transform from image space to device space.
   gfxMatrix imageSpaceToDeviceSpace;
   // The size at which the image should be drawn (which may not be its
   // intrinsic size due to, for example, HQ scaling).
   nsIntSize size;
   // The region in tiled image space which will be drawn, with an associated
   // region to which sampling should be restricted.
   ImageRegion region;
+  // The default viewport size for SVG images, which we use unless a different
+  // one has been explicitly specified. This is the same as |size| except that
+  // it does not take into account any transformation on the gfxContext we're
+  // drawing to - for example, CSS transforms are not taken into account.
+  nsIntSize svgViewportSize;
   // Whether there's anything to draw at all.
   bool shouldDraw;
 
   SnappedImageDrawingParameters()
    : region(ImageRegion::Empty())
    , shouldDraw(false)
   {}
 
   SnappedImageDrawingParameters(const gfxMatrix&   aImageSpaceToDeviceSpace,
                                 const nsIntSize&   aSize,
-                                const ImageRegion& aRegion)
+                                const ImageRegion& aRegion,
+                                const nsIntSize&   aSVGViewportSize)
    : imageSpaceToDeviceSpace(aImageSpaceToDeviceSpace)
    , size(aSize)
    , region(aRegion)
+   , svgViewportSize(aSVGViewportSize)
    , shouldDraw(true)
   {}
 };
 
 /**
  * Given two axis-aligned rectangles, returns the transformation that maps the
  * first onto the second.
  *
@@ -5567,16 +5574,21 @@ ComputeSnappedImageDrawingParameters(gfx
   }
 
   nsIntSize intImageSize =
     aImage->OptimalImageSizeForDest(snappedScaledDest,
                                     imgIContainer::FRAME_CURRENT,
                                     aGraphicsFilter, aImageFlags);
   gfxSize imageSize(intImageSize.width, intImageSize.height);
 
+  nsIntSize svgViewportSize = currentMatrix.IsIdentity()
+      ? intImageSize
+      : nsIntSize(NSAppUnitsToIntPixels(dest.width, aAppUnitsPerDevPixel),
+                  NSAppUnitsToIntPixels(dest.height, aAppUnitsPerDevPixel));
+
   // Compute the set of pixels that would be sampled by an ideal rendering
   gfxPoint subimageTopLeft =
     MapToFloatImagePixels(imageSize, devPixelDest, devPixelFill.TopLeft());
   gfxPoint subimageBottomRight =
     MapToFloatImagePixels(imageSize, devPixelDest, devPixelFill.BottomRight());
   gfxRect subimage;
   subimage.MoveTo(NSToIntFloor(subimageTopLeft.x),
                   NSToIntFloor(subimageTopLeft.y));
@@ -5644,17 +5656,19 @@ ComputeSnappedImageDrawingParameters(gfx
   // get the final matrix we'll draw with, because we didn't take it into
   // account when computing the matrices above.
   if (!didSnap) {
     transform = transform * currentMatrix;
   }
 
   ImageRegion region =
     ImageRegion::CreateWithSamplingRestriction(imageSpaceFill, subimage);
-  return SnappedImageDrawingParameters(transform, intImageSize, region);
+
+  return SnappedImageDrawingParameters(transform, intImageSize,
+                                       region, svgViewportSize);
 }
 
 
 static nsresult
 DrawImageInternal(gfxContext&            aContext,
                   nsPresContext*         aPresContext,
                   imgIContainer*         aImage,
                   GraphicsFilter         aGraphicsFilter,
@@ -5682,18 +5696,24 @@ DrawImageInternal(gfxContext&           
                                          aGraphicsFilter, aImageFlags);
 
   if (!params.shouldDraw)
     return NS_OK;
 
   gfxContextMatrixAutoSaveRestore contextMatrixRestorer(&aContext);
   aContext.SetMatrix(params.imageSpaceToDeviceSpace);
 
+  Maybe<SVGImageContext> svgContext = ToMaybe(aSVGContext);
+  if (!svgContext) {
+    // Use the default viewport.
+    svgContext = Some(SVGImageContext(params.svgViewportSize, Nothing()));
+  }
+
   aImage->Draw(&aContext, params.size, params.region, imgIContainer::FRAME_CURRENT,
-               aGraphicsFilter, ToMaybe(aSVGContext), aImageFlags);
+               aGraphicsFilter, svgContext, aImageFlags);
 
   return NS_OK;
 }
 
 /* static */ nsresult
 nsLayoutUtils::DrawSingleUnscaledImage(gfxContext&          aContext,
                                        nsPresContext*       aPresContext,
                                        imgIContainer*       aImage,