Bug 1274158 part 1 - Handle zero perspective gracefully. r?mattwoodrow draft
authorXidorn Quan <me@upsuper.org>
Fri, 12 Aug 2016 14:51:10 +1000
changeset 399798 645b642f822f5abfcaadcb8ecbef6edebbefaf26
parent 398604 6cf0089510fad8deb866136f5b92bbced9498447
child 399799 80ad7461c0ad7e685708c29870f9c662d2c55187
child 399886 6133cbe45da7d32d917ff81b4443c871fb6585b1
push id25996
push userquanxunzhen@gmail.com
push dateFri, 12 Aug 2016 04:53:40 +0000
reviewersmattwoodrow
bugs1274158
milestone51.0a1
Bug 1274158 part 1 - Handle zero perspective gracefully. r?mattwoodrow MozReview-Commit-ID: CEX39wo6oX8
layout/base/nsDisplayList.cpp
layout/style/nsStyleTransformMatrix.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -9,16 +9,17 @@
  * structures that represent things to be painted (ordered in z-order),
  * used during painting and hit testing
  */
 
 #include "nsDisplayList.h"
 
 #include <stdint.h>
 #include <algorithm>
+#include <limits>
 
 #include "gfxUtils.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/KeyframeEffect.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/layers/PLayerTransaction.h"
 #include "nsCSSRendering.h"
 #include "nsRenderingContext.h"
@@ -5632,17 +5633,17 @@ nsDisplayTransform::ComputePerspectiveMa
 
   /* Grab the values for perspective and perspective-origin (if present) */
 
   const nsStyleDisplay* cbDisplay = cbFrame->StyleDisplay();
   if (cbDisplay->mChildPerspective.GetUnit() != eStyleUnit_Coord) {
     return false;
   }
   nscoord perspective = cbDisplay->mChildPerspective.GetCoordValue();
-  if (perspective <= 0) {
+  if (perspective < 0) {
     return true;
   }
 
   TransformReferenceBox refBox(cbFrame);
 
   /* Allows us to access named variables by index. */
   Point3D perspectiveOrigin;
   gfx::Float* coords[2] = {&perspectiveOrigin.x, &perspectiveOrigin.y};
@@ -5685,18 +5686,20 @@ nsDisplayTransform::ComputePerspectiveMa
             NSAppUnitsToFloatPixels(frameToCbOffset.y, aAppUnitsPerPixel),
             0.0f);
 
   /* Move the perspective origin to be relative to aFrame, instead of relative
    * to the containing block which is how it was specified in the style system.
    */
   perspectiveOrigin += frameToCbGfxOffset;
 
-  aOutMatrix._34 =
-    -1.0 / NSAppUnitsToFloatPixels(perspective, aAppUnitsPerPixel);
+  Float perspectivePx = std::max(NSAppUnitsToFloatPixels(perspective,
+                                                         aAppUnitsPerPixel),
+                                 std::numeric_limits<Float>::epsilon());
+  aOutMatrix._34 = -1.0 / perspectivePx;
   aOutMatrix.ChangeBasis(perspectiveOrigin);
   return true;
 }
 
 nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame,
                                                                        float aAppUnitsPerPixel,
                                                                        const nsRect* aBoundsOverride)
   : mFrame(aFrame)
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -12,16 +12,18 @@
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsRuleNode.h"
 #include "nsSVGUtils.h"
 #include "nsCSSKeywords.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "gfxMatrix.h"
 
+#include <limits>
+
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 namespace nsStyleTransformMatrix {
 
 /* Note on floating point precision: The transform matrix is an array
  * of single precision 'float's, and so are most of the input values
  * we get from the style system, but intermediate calculations
@@ -547,19 +549,20 @@ static void
 ProcessPerspective(Matrix4x4& aMatrix,
                    const nsCSSValue::Array* aData,
                    nsStyleContext *aContext,
                    nsPresContext *aPresContext,
                    RuleNodeCacheConditions& aConditions)
 {
   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
 
-  float depth = ProcessTranslatePart(aData->Item(1), aContext,
-                                     aPresContext, aConditions,
-                                     nullptr);
+  float depth = std::max(ProcessTranslatePart(aData->Item(1), aContext,
+                                              aPresContext, aConditions,
+                                              nullptr),
+                         std::numeric_limits<float>::epsilon());
   aMatrix.Perspective(depth);
 }
 
 
 /**
  * SetToTransformFunction is essentially a giant switch statement that fans
  * out to many smaller helper functions.
  */