Bug 1217905 - Don't transform dest rects if destination context has a rotation with inset box shadows. r=mstange, a=ritu
authorMason Chang <mchang@mozilla.com>
Tue, 03 Nov 2015 07:38:34 -0800
changeset 305458 76459a3ecc841b7928939a51b9c9245e71e113b5
parent 305457 0b5bdeedf0f4a4a8c8d7e20f18b8e3d378f3e655
child 305459 3f5340e348d4523db26d5bb425cfa10556db8f1d
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, ritu
bugs1217905
milestone44.0a2
Bug 1217905 - Don't transform dest rects if destination context has a rotation with inset box shadows. r=mstange, a=ritu
layout/base/nsCSSRendering.cpp
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -5579,49 +5579,55 @@ nsContextBoxBlur::InsetBoxBlur(gfxContex
                                RectCornerRadii& aInnerClipRectRadii,
                                Rect aSkipRect, Point aShadowOffset)
 {
   if (aDestinationRect.IsEmpty()) {
     mContext = nullptr;
     return false;
   }
 
+  gfxContextAutoSaveRestore autoRestore(aDestinationCtx);
+
   IntSize blurRadius;
   IntSize spreadRadius;
   // Convert the blur and spread radius to device pixels
   bool constrainSpreadRadius = false;
   GetBlurAndSpreadRadius(aDestinationCtx, aAppUnitsPerDevPixel,
                          aBlurRadiusAppUnits, aSpreadDistanceAppUnits,
                          blurRadius, spreadRadius, constrainSpreadRadius);
 
   // The blur and spread radius are scaled already, so scale all
   // input data to the blur. This way, we don't have to scale the min
   // inset blur to the invert of the dest context, then rescale it back
   // when we draw to the destination surface.
   gfxSize scale = aDestinationCtx->CurrentMatrix().ScaleFactors(true);
-  Matrix currentMatrix = ToMatrix(aDestinationCtx->CurrentMatrix());
-
-  Rect transformedDestRect = currentMatrix.TransformBounds(aDestinationRect);
-  Rect transformedShadowClipRect = currentMatrix.TransformBounds(aShadowClipRect);
-  Rect transformedSkipRect = currentMatrix.TransformBounds(aSkipRect);
+  Matrix transform = ToMatrix(aDestinationCtx->CurrentMatrix());
+
+  // XXX: we could probably handle negative scales but for now it's easier just to fallback
+  if (!transform.HasNonAxisAlignedTransform() && transform._11 > 0.0 && transform._22 > 0.0) {
+    // If we don't have a rotation, we're pre-transforming all the rects.
+    aDestinationCtx->SetMatrix(gfxMatrix());
+  } else {
+    // Don't touch anything, we have a rotation.
+    transform = Matrix();
+  }
+
+  Rect transformedDestRect = transform.TransformBounds(aDestinationRect);
+  Rect transformedShadowClipRect = transform.TransformBounds(aShadowClipRect);
+  Rect transformedSkipRect = transform.TransformBounds(aSkipRect);
 
   transformedDestRect.Round();
   transformedShadowClipRect.Round();
   transformedSkipRect.RoundIn();
 
   for (size_t i = 0; i < 4; i++) {
     aInnerClipRectRadii[i].width = std::floor(scale.width * aInnerClipRectRadii[i].width);
     aInnerClipRectRadii[i].height = std::floor(scale.height * aInnerClipRectRadii[i].height);
   }
 
-  {
-    gfxContextAutoSaveRestore autoRestore(aDestinationCtx);
-    aDestinationCtx->SetMatrix(gfxMatrix());
-
-    mAlphaBoxBlur.BlurInsetBox(aDestinationCtx, transformedDestRect,
-                               transformedShadowClipRect,
-                               blurRadius, spreadRadius,
-                               aShadowColor, aHasBorderRadius,
-                               aInnerClipRectRadii, transformedSkipRect,
-                               aShadowOffset);
-  }
+  mAlphaBoxBlur.BlurInsetBox(aDestinationCtx, transformedDestRect,
+                             transformedShadowClipRect,
+                             blurRadius, spreadRadius,
+                             aShadowColor, aHasBorderRadius,
+                             aInnerClipRectRadii, transformedSkipRect,
+                             aShadowOffset);
   return true;
 }