Bug 1290782 Part 1 - When drawing a border-image using an SVG image, we should not take into account any transformation of currentMatrix when computing svg viewport size. r?dholbert,cjku draft
authorLouis Chang <lochang@mozilla.com>
Wed, 20 Sep 2017 10:05:42 +0800
changeset 667425 0da4d8c8c52389e2758d719e03c9b298ee556f5d
parent 667424 309140f65fc5820fa8ccab5f238d8d5c48283f82
child 667426 a1610a1265a10f0667028d14bd055666cf009205
push id80695
push userlochang@mozilla.com
push dateWed, 20 Sep 2017 02:48:08 +0000
reviewersdholbert, cjku
bugs1290782
milestone57.0a1
Bug 1290782 Part 1 - When drawing a border-image using an SVG image, we should not take into account any transformation of currentMatrix when computing svg viewport size. r?dholbert,cjku MozReview-Commit-ID: 8rkwQGKJOvo
layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6529,18 +6529,18 @@ ComputeSnappedImageDrawingParameters(gfx
     fill = devPixelFill;
     dest = devPixelDest;
   }
 
   // If we snapped above, |dest| already takes into account |currentMatrix|'s scale
   // and has integer coordinates. If not, we need these properties to compute
   // the optimal drawn image size, so compute |snappedDestSize| here.
   gfxSize snappedDestSize = dest.Size();
+  gfxSize scaleFactors = currentMatrix.ScaleFactors(true);
   if (!didSnap) {
-    gfxSize scaleFactors = currentMatrix.ScaleFactors(true);
     snappedDestSize.Scale(scaleFactors.width, scaleFactors.height);
     snappedDestSize.width = NS_round(snappedDestSize.width);
     snappedDestSize.height = NS_round(snappedDestSize.height);
   }
 
   // We need to be sure that this is at least one pixel in width and height,
   // or we'll end up drawing nothing even if we have a nonempty fill.
   snappedDestSize.width = std::max(snappedDestSize.width, 1.0);
@@ -6550,23 +6550,35 @@ ComputeSnappedImageDrawingParameters(gfx
   if (fill.IsEmpty() || snappedDestSize.IsEmpty()) {
     return SnappedImageDrawingParameters();
   }
 
   nsIntSize intImageSize =
     aImage->OptimalImageSizeForDest(snappedDestSize,
                                     imgIContainer::FRAME_CURRENT,
                                     aSamplingFilter, aImageFlags);
+
+  nsIntSize svgViewportSize;
+  if (scaleFactors.width == 1.0 && scaleFactors.height == 1.0) {
+    // intImageSize is scaled by currentMatrix. But since there are no scale
+    // factors in currentMatrix, it is safe to assign intImageSize to
+    // svgViewportSize directly.
+    svgViewportSize = intImageSize;
+  } else {
+    // We should not take into account any transformation of currentMatrix
+    // when computing svg viewport size. Since currentMatrix contains scale
+    // factors, we need to recompute SVG viewport by unscaled devPixelDest.
+    svgViewportSize = aImage->OptimalImageSizeForDest(devPixelDest.Size(),
+                                                      imgIContainer::FRAME_CURRENT,
+                                                      aSamplingFilter,
+                                                      aImageFlags);
+  }
+
   gfxSize imageSize(intImageSize.width, intImageSize.height);
 
-  // XXX(seth): May be buggy; see bug 1151016.
-  CSSIntSize svgViewportSize = currentMatrix.IsIdentity()
-    ? CSSIntSize(intImageSize.width, intImageSize.height)
-    : CSSIntSize::Truncate(devPixelDest.width, devPixelDest.height);
-
   // 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));
@@ -6672,17 +6684,19 @@ ComputeSnappedImageDrawingParameters(gfx
     MOZ_ASSERT(!(aImageFlags & imgIContainer::FLAG_CLAMP));
     extendMode = ExtendMode::REPEAT;
   }
 
   ImageRegion region =
     ImageRegion::CreateWithSamplingRestriction(imageSpaceFill, subimage, extendMode);
 
   return SnappedImageDrawingParameters(transform, intImageSize,
-                                       region, svgViewportSize);
+                                       region,
+                                       CSSIntSize(svgViewportSize.width,
+                                                  svgViewportSize.height));
 }
 
 static DrawResult
 DrawImageInternal(gfxContext&            aContext,
                   nsPresContext*         aPresContext,
                   imgIContainer*         aImage,
                   const SamplingFilter   aSamplingFilter,
                   const nsRect&          aDest,