Bug 1091709 - Make Transform() do calculations using gfxFloat (double) to avoid losing precision. r=mattwoodrow, a=sledru
authorMats Palmgren <mats@mozilla.com>
Tue, 20 Jan 2015 18:20:04 +0000
changeset 242972 0b22d12d0736
parent 242971 7850d99485e6
child 242973 4501fcac9e0b
push id4350
push userryanvm@gmail.com
push date2015-01-21 19:56 +0000
treeherdermozilla-beta@4501fcac9e0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, sledru
bugs1091709
milestone36.0
Bug 1091709 - Make Transform() do calculations using gfxFloat (double) to avoid losing precision. r=mattwoodrow, a=sledru
gfx/thebes/gfx3DMatrix.cpp
--- a/gfx/thebes/gfx3DMatrix.cpp
+++ b/gfx/thebes/gfx3DMatrix.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gfxMatrix.h"
 #include "gfx3DMatrix.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/Tools.h"
@@ -568,19 +568,29 @@ gfx3DMatrix::Inverse() const
 
   temp /= det;
   return temp;
 }
 
 gfxPoint
 gfx3DMatrix::Transform(const gfxPoint& point) const
 {
-  Point3D vec3d(point.x, point.y, 0);
-  vec3d = Transform3D(vec3d);
-  return gfxPoint(vec3d.x, vec3d.y);
+  // Note: we don't use Transform3D here because passing point.x/y via
+  // a Point3D would lose precision and cause bugs, e.g. bug 1091709.
+  gfxFloat px = point.x;
+  gfxFloat py = point.y;
+
+  gfxFloat x = px * _11 + py * _21 + _41;
+  gfxFloat y = px * _12 + py * _22 + _42;
+  gfxFloat w = px * _14 + py * _24 + _44;
+
+  x /= w;
+  y /= w;
+
+  return gfxPoint(x, y);
 }
 
 Point3D
 gfx3DMatrix::Transform3D(const Point3D& point) const
 {
   gfxFloat x = point.x * _11 + point.y * _21 + point.z * _31 + _41;
   gfxFloat y = point.x * _12 + point.y * _22 + point.z * _32 + _42;
   gfxFloat z = point.x * _13 + point.y * _23 + point.z * _33 + _43;