Bug 504071. Allow image drawing to snap to pixel boundaries even if there's scaling, on all platforms. Not only is it faster, it avoids seaming. This is consistent with snapping behavior of other drawing operations. r=joe
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 05 Dec 2012 12:34:19 +1300
changeset 117856 546f9f3999d36b022e257f0bf760a3dc5a720b7b
parent 117855 965e97b75bfab0686ac6323a9815940fd4fd34d9
child 117857 d1905a0ba1ed9e56d737aaef4e62fa6b0b471aea
push id20716
push userrocallahan@mozilla.com
push dateMon, 07 Jan 2013 05:47:29 +0000
treeherdermozilla-inbound@546f9f3999d3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs504071
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 504071. Allow image drawing to snap to pixel boundaries even if there's scaling, on all platforms. Not only is it faster, it avoids seaming. This is consistent with snapping behavior of other drawing operations. r=joe
layout/base/nsLayoutUtils.cpp
layout/reftests/image/image-seam-1-ref.html
layout/reftests/image/image-seam-1a.html
layout/reftests/image/image-seam-1b.html
layout/reftests/image/image-seam-2-ref.html
layout/reftests/image/image-seam-2.html
layout/reftests/image/reftest.list
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3819,25 +3819,30 @@ ComputeSnappedImageDrawingParameters(gfx
 
   gfxRect devPixelDest =
     nsLayoutUtils::RectToGfxRect(aDest, aAppUnitsPerDevPixel);
   gfxRect devPixelFill =
     nsLayoutUtils::RectToGfxRect(aFill, aAppUnitsPerDevPixel);
   gfxRect devPixelDirty =
     nsLayoutUtils::RectToGfxRect(aDirty, aAppUnitsPerDevPixel);
 
-  bool ignoreScale = false;
-#ifdef MOZ_GFX_OPTIMIZE_MOBILE
-  ignoreScale = true;
-#endif
+  gfxMatrix currentMatrix = aCtx->CurrentMatrix();
   gfxRect fill = devPixelFill;
-  bool didSnap = aCtx->UserToDevicePixelSnapped(fill, ignoreScale);
-  gfxMatrix currentMatrix = aCtx->CurrentMatrix();
-  if (didSnap && currentMatrix.HasNonAxisAlignedTransform()) {
-    // currentMatrix must have some rotation by a multiple of 90 degrees.
+  bool didSnap;
+  // Snap even if we have a scale in the context. But don't snap if
+  // we have something that's not translation+scale, or if the scale flips in
+  // the X or Y direction, because snapped image drawing can't handle that yet.
+  if (!currentMatrix.HasNonAxisAlignedTransform() &&
+      currentMatrix.xx > 0.0 && currentMatrix.yy > 0.0 &&
+      aCtx->UserToDevicePixelSnapped(fill, true)) {
+    didSnap = true;
+    if (fill.IsEmpty()) {
+      return SnappedImageDrawingParameters();
+    }
+  } else {
     didSnap = false;
     fill = devPixelFill;
   }
 
   gfxSize imageSize(aImageSize.width, aImageSize.height);
 
   // Compute the set of pixels that would be sampled by an ideal rendering
   gfxPoint subimageTopLeft =
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-seam-1-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<style>
+body {
+  background-color:black;
+}
+div {
+  transform: scale(0.3);
+  transform-origin: 0 0;
+  width: 512px;
+  height: 256px;
+  background: white;
+}
+</style>
+<div></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-seam-1a.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<style>
+body {
+  background-color:black;
+}
+div {
+  transform: scale(0.3);
+  transform-origin: 0 0;
+}
+</style>
+<div>
+<!-- Test that drawing of (scaled) single pixel images is snapped -->
+<img style="width:256px; height:256px"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAxJREFUCNdj+P//PwAF/gL+3MxZ5wAAAABJRU5ErkJggg=="
+><img style="width:256px; height:256px"
+  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAxJREFUCNdj+P//PwAF/gL+3MxZ5wAAAABJRU5ErkJggg==">
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-seam-1b.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<style>
+body {
+  background-color:black;
+}
+div {
+  transform: scale(0.3);
+  transform-origin: 0 0;
+}
+</style>
+<div>
+<!-- Test that drawing of a 20x20 image with all pixels the same color is snapped -->
+<img style="width:256px; height:256px"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAG0lEQVQ4jWP4T2XAMGrgqIGjBo4aOGrgSDUQAOdROhuRCSeMAAAAAElFTkSuQmCC"
+><img style="width:256px; height:256px"
+  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAG0lEQVQ4jWP4T2XAMGrgqIGjBo4aOGrgSDUQAOdROhuRCSeMAAAAAElFTkSuQmCC">
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-seam-2-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<style>
+body {
+  background-color:black;
+}
+div {
+  transform: scale(0.3);
+  transform-origin: 0 0;
+}
+</style>
+<div>
+<img style="width:412px; height:256px"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAADklEQVQImWP4jwYY0AEAlpkP8c9bnjkAAAAASUVORK5CYII="
+><img style="width:100px; height:256px"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAADklEQVQImWP4jwYY0AEAlpkP8c9bnjkAAAAASUVORK5CYII="
+>
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-seam-2.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<style>
+body {
+  background-color:black;
+}
+div {
+  transform: scale(0.3);
+  transform-origin: 0 0;
+}
+</style>
+<div>
+<!-- Test that drawing of nonuniform images is snapped -->
+<!-- This is a 2x2 image where the top row is white and the bottom row is transpraent -->
+<img style="width:256px; height:256px"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAADklEQVQImWP4DwUMMAAAa6YH+b3nj3MAAAAASUVORK5CYII="
+><img style="width:256px; height:256px"
+  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAADklEQVQImWP4DwUMMAAAa6YH+b3nj3MAAAAASUVORK5CYII=">
+</div>
--- a/layout/reftests/image/reftest.list
+++ b/layout/reftests/image/reftest.list
@@ -1,9 +1,12 @@
 random-if(bug685516) fuzzy-if(Android,4,15) == background-image-zoom-1.html background-image-zoom-1-ref.html
 == background-image-zoom-2.html about:blank
+== image-seam-1a.html image-seam-1-ref.html
+== image-seam-1b.html image-seam-1-ref.html
+fails-if(cocoaWidget) == image-seam-2.html image-seam-2-ref.html # Quartz doesn't support EXTEND_PAD (bug 567370)
 == image-zoom-1.html image-zoom-1-ref.html
 == image-zoom-2.html image-zoom-1-ref.html
 == invalid-url-image-1.html invalid-url-image-1-ref.html
 == sync-image-switch-1a.html sync-image-switch-1-ref.html
 == sync-image-switch-1b.html sync-image-switch-1-ref.html
 == sync-image-switch-1c.html sync-image-switch-1-ref.html
 == sync-image-switch-1d.html sync-image-switch-1-ref.html