From aa0ed0c2edece61d1f4b2b39bdb110b8be97a409 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= <emilio@crisal.io>
Date: Fri, 7 Dec 2018 12:40:53 -0500
Subject: [PATCH 1/2] transform3d: Introduce Transform3D::project_to_2d to
 flatten a transform.

Need to use this for https://github.com/servo/webrender/issues/3394.

The normalization of perspective is not necessary but Gecko does it as a
performance optimization, and ScaleOffset in WR wouldn't handle this.

See: https://bugzilla.mozilla.org/show_bug.cgi?id=1241161

But in any case I'm happy to teach ScaleOffset about that case instead if you
think it's better.
---
 src/transform3d.rs | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/src/transform3d.rs b/src/transform3d.rs
index 94b2e458..224ae5fc 100644
--- a/src/transform3d.rs
+++ b/src/transform3d.rs
@@ -520,6 +520,42 @@ where T: Copy + Clone +
         self.post_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z))
     }
 
+    /// Returns a projection of this transform in 2d space.
+    pub fn project_to_2d(&self) -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+
+        let mut result = self.clone();
+
+        result.m31 = _0;
+        result.m32 = _0;
+        result.m13 = _0;
+        result.m23 = _0;
+        result.m33 = _1;
+        result.m43 = _0;
+        result.m34 = _0;
+
+        // Try to normalize perspective when possible to convert to a 2d matrix.
+        // Some matrices, such as those derived from perspective transforms, can
+        // modify m44 from 1, while leaving the rest of the fourth column
+        // (m14, m24) at 0. In this case, after resetting the third row and
+        // third column above, the value of m44 functions only to scale the
+        // coordinate transform divide by W. The matrix can be converted to
+        // a true 2D matrix by normalizing out the scaling effect of m44 on
+        // the remaining components ahead of time.
+        if self.m14 == _0 && self.m24 == _0 && self.m44 != _0 && self.m44 != _1 {
+           let scale = _1 / self.m44;
+           result.m11 = result.m11 * scale;
+           result.m12 = result.m12 * scale;
+           result.m21 = result.m21 * scale;
+           result.m22 = result.m22 * scale;
+           result.m41 = result.m41 * scale;
+           result.m42 = result.m42 * scale;
+           result.m44 = _1;
+        }
+
+        result
+    }
+
     /// Create a 3d scale transform
     pub fn create_scale(x: T, y: T, z: T) -> Self {
         let (_0, _1): (T, T) = (Zero::zero(), One::one());

From 1c620631be11331523aa62ff16038d43978f3654 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= <emilio@crisal.io>
Date: Fri, 7 Dec 2018 14:26:21 -0500
Subject: [PATCH 2/2] Minor version bump.

---
 Cargo.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Cargo.toml b/Cargo.toml
index 812672ed..bdbec9f0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "euclid"
-version = "0.19.3"
+version = "0.19.4"
 authors = ["The Servo Project Developers"]
 description = "Geometry primitives"
 documentation = "https://docs.rs/euclid/"