Bug 791675 - Scaled shapes fail to draw sometimes r=jwatt.
authorRobert Longson <longsonr@gmail.com>
Thu, 20 Dec 2012 13:49:54 +0000 (2012-12-20)
changeset 116627 022244d0ca81eb5bce06082cc8ba2aa7b575cfb3
parent 116626 23da80538e24a7d0a351c3ef2ca042fc1468f2be
child 116628 3b9ab5404a25d694034109b6f40c4da9b6f5e933
push id24058
push useremorley@mozilla.com
push dateThu, 20 Dec 2012 21:06:10 +0000 (2012-12-20)
treeherdermozilla-central@868b21bed3eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs791675
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 791675 - Scaled shapes fail to draw sometimes r=jwatt.
layout/svg/nsSVGImageFrame.cpp
layout/svg/nsSVGPathGeometryFrame.cpp
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -464,20 +464,38 @@ nsSVGImageFrame::ReflowSVG()
                     "ReflowSVG mechanism not designed for this");
 
   if (!nsSVGUtils::NeedsReflowSVG(this)) {
     return;
   }
 
   gfxContext tmpCtx(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
-  gfxMatrix identity;
-  GeneratePath(&tmpCtx, identity);
-
+  // We'd like to just pass the identity matrix to GeneratePath, but if
+  // this frame's user space size is _very_ large/small then the extents we
+  // obtain below might have overflowed or otherwise be broken. This would
+  // cause us to end up with a broken mRect and visual overflow rect and break
+  // painting of this frame. This is particularly noticeable if the transforms
+  // between us and our nsSVGOuterSVGFrame scale this frame to a reasonable
+  // size. To avoid this we sadly have to do extra work to account for the
+  // transforms between us and our nsSVGOuterSVGFrame, even though the
+  // overwhelming number of SVGs will never have this problem.
+  // XXX Will Azure eventually save us from having to do this?
+  gfxSize scaleFactors = GetCanvasTM(FOR_OUTERSVG_TM).ScaleFactors(true);
+  bool applyScaling = fabs(scaleFactors.width) >= 1e-6 &&
+                      fabs(scaleFactors.height) >= 1e-6;
+  gfxMatrix scaling;
+  if (applyScaling) {
+    scaling.Scale(scaleFactors.width, scaleFactors.height);
+  } 
+  GeneratePath(&tmpCtx, scaling);
   gfxRect extent = tmpCtx.GetUserPathExtent();
+  if (applyScaling) {
+    extent.Scale(1 / scaleFactors.width, 1 / scaleFactors.height);
+  }
 
   if (!extent.IsEmpty()) {
     mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent, 
               PresContext()->AppUnitsPerCSSPixel());
   } else {
     mRect.SetEmpty();
   }
 
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -304,17 +304,38 @@ nsSVGPathGeometryFrame::ReflowSVG()
   // stroke-opacity="0"). GetHitTestFlags() accounts for 'pointer-events'.
   uint16_t hitTestFlags = GetHitTestFlags();
   if ((hitTestFlags & SVG_HIT_TEST_FILL)) {
    flags |= nsSVGUtils::eBBoxIncludeFillGeometry;
   }
   if ((hitTestFlags & SVG_HIT_TEST_STROKE)) {
    flags |= nsSVGUtils::eBBoxIncludeStrokeGeometry;
   }
-  gfxRect extent = GetBBoxContribution(gfxMatrix(), flags);
+ 
+  // We'd like to just pass the identity matrix to GetBBoxContribution, but if
+  // this frame's user space size is _very_ large/small then the extents we
+  // obtain below might have overflowed or otherwise be broken. This would
+  // cause us to end up with a broken mRect and visual overflow rect and break
+  // painting of this frame. This is particularly noticeable if the transforms
+  // between us and our nsSVGOuterSVGFrame scale this frame to a reasonable
+  // size. To avoid this we sadly have to do extra work to account for the
+  // transforms between us and our nsSVGOuterSVGFrame, even though the
+  // overwhelming number of SVGs will never have this problem.
+  // XXX Will Azure eventually save us from having to do this?
+  gfxSize scaleFactors = GetCanvasTM(FOR_OUTERSVG_TM).ScaleFactors(true);
+  bool applyScaling = fabs(scaleFactors.width) >= 1e-6 &&
+                      fabs(scaleFactors.height) >= 1e-6;
+  gfxMatrix scaling;
+  if (applyScaling) {
+    scaling.Scale(scaleFactors.width, scaleFactors.height);
+  }
+  gfxRect extent = GetBBoxContribution(scaling, flags);
+  if (applyScaling) {
+    extent.Scale(1 / scaleFactors.width, 1 / scaleFactors.height);
+  }
   mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent,
             PresContext()->AppUnitsPerCSSPixel());
 
   if (mState & NS_FRAME_FIRST_REFLOW) {
     // Make sure we have our filter property (if any) before calling
     // FinishAndStoreOverflow (subsequent filter changes are handled off
     // nsChangeHint_UpdateEffects):
     nsSVGEffects::UpdateEffects(this);