[rust] add euclid

The euclid crate provides geometry primitives (basic linear algebra) for Rust.

Euclid will be used by Ermine and other mods written in Rust.

OSRB: https://fuchsia.atlassian.net/browse/OSRB-74

Testing: Built Fuchsia with this crate added.
Change-Id: I7149572377bf1b1e60372ea3139f0200578efc75
diff --git a/rustc_deps/Cargo.lock b/rustc_deps/Cargo.lock
index 3cc5d0a..3404a3c 100644
--- a/rustc_deps/Cargo.lock
+++ b/rustc_deps/Cargo.lock
@@ -309,6 +309,14 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "euclid"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "failure"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -375,6 +383,7 @@
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "encode_unicode 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "font-rs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures-preview 0.3.0-alpha.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1495,6 +1504,7 @@
 "checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
 "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
 "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
+"checksum euclid 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4019b11e3498dd84d8893848c3d70e40c6dc71bb277ae5252cc16af006d06872"
 "checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
 "checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
diff --git a/rustc_deps/Cargo.toml b/rustc_deps/Cargo.toml
index 6188da9..ddf71d7 100644
--- a/rustc_deps/Cargo.toml
+++ b/rustc_deps/Cargo.toml
@@ -19,6 +19,7 @@
 clap = "2.29"
 crossbeam = "0.3.2"
 encode_unicode = "0.1.3"
+euclid = "0.19"
 failure = "0.1.1"
 font-rs = "0.1.3"
 futures-preview = "=0.3.0-alpha.7"
diff --git a/rustc_deps/vendor/euclid/.cargo-checksum.json b/rustc_deps/vendor/euclid/.cargo-checksum.json
new file mode 100644
index 0000000..464bc52
--- /dev/null
+++ b/rustc_deps/vendor/euclid/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".travis.yml":"6023213d4635e7e0eebdf63ccac18b31765bda424289f3f7f61bb0a6ff919e1e","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"9b98c53a1f751f2cec009e89077939be7af2070a8fe36d9e458ddbe2db6d8ecf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/homogen.rs":"cb26346ad1ea2797bdc1cac7f532872becabf28a1f9c60792f86ad4a655582f9","src/length.rs":"3171315822707728b1bfbdd04a4190ffb7206b4bfc59e9dd072bb2caa05ff292","src/lib.rs":"2c1e367c85da913d8980821632a3024a21706e4908b003b4c37ffcae49efce7e","src/macros.rs":"d2b7b391f58fe9cedb426780cfa1d2771f9ac786a6237b0f89d3e5788f5ec1b7","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"2c399e282c2e81528775a1fc6ee1a0f2f6f71ed4a14bbe426115ae78b4cf2149","src/rect.rs":"dc7131fe3884803d549fb66dec589ad671790451dbb3770d360509fbfabcf6ec","src/rotation.rs":"982aaca640215bacc5d2dc60a8949bb2510d5b6d492975b8b6946a7c8f69b496","src/scale.rs":"fc07bcf47f3a1215023c830059f0d270e570cbd37fe8c367ef4a47b191f4ae3e","src/side_offsets.rs":"f114cb881256bbeff2ee2aa305d363e2dea65aa8535140f104f6fa9364bd02f5","src/size.rs":"1fe99377bee13835ca416adbccdb0d163091a3dcf2977c3222da2d6b22d70621","src/transform2d.rs":"2f9bafe40b9a6dd9c41747aabfdefbfc9ee48daf4f4297d2320ccbdac185a30d","src/transform3d.rs":"6af722a693e6cd041440871be47069bad3392d670155ba05f9abbc11d9534b4c","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"b0b41eac9c823e05bf6357e69c71dac977db2d8ab27b25f80f1f44b056d15f6d"},"package":"4019b11e3498dd84d8893848c3d70e40c6dc71bb277ae5252cc16af006d06872"}
\ No newline at end of file
diff --git a/rustc_deps/vendor/euclid/.travis.yml b/rustc_deps/vendor/euclid/.travis.yml
new file mode 100644
index 0000000..6b08dad
--- /dev/null
+++ b/rustc_deps/vendor/euclid/.travis.yml
@@ -0,0 +1,31 @@
+language: rust
+
+notifications:
+  webhooks: http://build.servo.org:54856/travis
+
+rust:
+  - 1.23.0
+  - stable
+  - beta
+  - nightly
+
+env:
+  - FEATURES=""
+  - FEATURES="--features serde"
+
+matrix:
+  include:
+    - rust: stable
+      env: FEATURES=""
+    - rust: stable
+      env: FEATURES="--features mint"
+    - rust: beta
+      env: FEATURES=""
+    - rust: nightly
+      env: FEATURES="--features unstable"
+    - rust: nightly
+      env: FEATURES="--features unstable,serde"
+
+script:
+  - cargo build $FEATURES
+  - cargo test --verbose $FEATURES
diff --git a/rustc_deps/vendor/euclid/COPYRIGHT b/rustc_deps/vendor/euclid/COPYRIGHT
new file mode 100644
index 0000000..8b7291a
--- /dev/null
+++ b/rustc_deps/vendor/euclid/COPYRIGHT
@@ -0,0 +1,5 @@
+Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+option. All files in the project carrying such notice may not be
+copied, modified, or distributed except according to those terms.
diff --git a/rustc_deps/vendor/euclid/Cargo.toml b/rustc_deps/vendor/euclid/Cargo.toml
new file mode 100644
index 0000000..4b74c49
--- /dev/null
+++ b/rustc_deps/vendor/euclid/Cargo.toml
@@ -0,0 +1,41 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "euclid"
+version = "0.19.2"
+authors = ["The Servo Project Developers"]
+description = "Geometry primitives"
+documentation = "https://docs.rs/euclid/"
+keywords = ["matrix", "vector", "linear-algebra", "geometry"]
+categories = ["science"]
+license = "MIT / Apache-2.0"
+repository = "https://github.com/servo/euclid"
+[dependencies.mint]
+version = "0.5.1"
+optional = true
+
+[dependencies.num-traits]
+version = "0.2"
+
+[dependencies.serde]
+version = "1.0"
+features = ["serde_derive"]
+optional = true
+[dev-dependencies.rand]
+version = "0.4"
+
+[dev-dependencies.serde_test]
+version = "1.0"
+
+[features]
+unstable = []
diff --git a/rustc_deps/vendor/void/LICENSE b/rustc_deps/vendor/euclid/LICENSE-APACHE
similarity index 89%
rename from rustc_deps/vendor/void/LICENSE
rename to rustc_deps/vendor/euclid/LICENSE-APACHE
index 33c7319..16fe87b 100644
--- a/rustc_deps/vendor/void/LICENSE
+++ b/rustc_deps/vendor/euclid/LICENSE-APACHE
@@ -1,5 +1,3 @@
-https://raw.githubusercontent.com/reem/rust/master/LICENSE-APACHE:
-
                               Apache License
                         Version 2.0, January 2004
                      http://www.apache.org/licenses/
@@ -201,31 +199,3 @@
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-========================================
-https://raw.githubusercontent.com/reem/rust/master/LICENSE-MIT:
-
-Copyright (c) 2015 The Rust Project Developers
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/rustc_deps/vendor/euclid/LICENSE-MIT b/rustc_deps/vendor/euclid/LICENSE-MIT
new file mode 100644
index 0000000..807526f
--- /dev/null
+++ b/rustc_deps/vendor/euclid/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2012-2013 Mozilla Foundation
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/rustc_deps/vendor/euclid/README.md b/rustc_deps/vendor/euclid/README.md
new file mode 100644
index 0000000..13b488d
--- /dev/null
+++ b/rustc_deps/vendor/euclid/README.md
@@ -0,0 +1,8 @@
+# euclid
+
+This is a small library for geometric types with a focus on 2d graphics and
+layout.
+
+* [Documentation](https://docs.rs/euclid/)
+* [Release notes](https://github.com/servo/euclid/releases)
+* [crates.io](https://crates.io/crates/euclid)
diff --git a/rustc_deps/vendor/euclid/src/approxeq.rs b/rustc_deps/vendor/euclid/src/approxeq.rs
new file mode 100644
index 0000000..9fb11cc
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/approxeq.rs
@@ -0,0 +1,35 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Trait for testing approximate equality
+pub trait ApproxEq<Eps> {
+    fn approx_epsilon() -> Eps;
+    fn approx_eq(&self, other: &Self) -> bool;
+    fn approx_eq_eps(&self, other: &Self, approx_epsilon: &Eps) -> bool;
+}
+
+macro_rules! approx_eq {
+    ($ty:ty, $eps:expr) => (
+        impl ApproxEq<$ty> for $ty {
+            #[inline]
+            fn approx_epsilon() -> $ty { $eps }
+            #[inline]
+            fn approx_eq(&self, other: &$ty) -> bool {
+                self.approx_eq_eps(other, &$eps)
+            }
+            #[inline]
+            fn approx_eq_eps(&self, other: &$ty, approx_epsilon: &$ty) -> bool {
+                (*self - *other).abs() < *approx_epsilon
+            }
+        }
+    )
+}
+
+approx_eq!(f32, 1.0e-6);
+approx_eq!(f64, 1.0e-6);
diff --git a/rustc_deps/vendor/euclid/src/homogen.rs b/rustc_deps/vendor/euclid/src/homogen.rs
new file mode 100644
index 0000000..b8448a9
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/homogen.rs
@@ -0,0 +1,123 @@
+// Copyright 2018 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use point::{TypedPoint2D, TypedPoint3D};
+use vector::{TypedVector2D, TypedVector3D};
+
+use num::{One, Zero};
+
+use core::fmt;
+use core::marker::PhantomData;
+use core::ops::Div;
+
+
+define_matrix! {
+    /// Homogeneous vector in 3D space.
+    pub struct HomogeneousVector<T, U> {
+        pub x: T,
+        pub y: T,
+        pub z: T,
+        pub w: T,
+    }
+}
+
+
+impl<T, U> HomogeneousVector<T, U> {
+    /// Constructor taking scalar values directly.
+    #[inline]
+    pub fn new(x: T, y: T, z: T, w: T) -> Self {
+        HomogeneousVector { x, y, z, w, _unit: PhantomData }
+    }
+}
+
+
+impl<T: Copy + Div<T, Output=T> + Zero + PartialOrd, U> HomogeneousVector<T, U> {
+    /// Convert into Cartesian 2D point.
+    ///
+    /// Returns None if the point is on or behind the W=0 hemisphere.
+    #[inline]
+    pub fn to_point2d(&self) -> Option<TypedPoint2D<T, U>> {
+        if self.w > T::zero() {
+            Some(TypedPoint2D::new(self.x / self.w, self.y / self.w))
+        } else {
+            None
+        }
+    }
+
+    /// Convert into Cartesian 3D point.
+    ///
+    /// Returns None if the point is on or behind the W=0 hemisphere.
+    #[inline]
+    pub fn to_point3d(&self) -> Option<TypedPoint3D<T, U>> {
+        if self.w > T::zero() {
+            Some(TypedPoint3D::new(self.x / self.w, self.y / self.w, self.z / self.w))
+        } else {
+            None
+        }
+    }
+}
+
+impl<T: Zero, U> From<TypedVector2D<T, U>> for HomogeneousVector<T, U> {
+    #[inline]
+    fn from(v: TypedVector2D<T, U>) -> Self {
+        HomogeneousVector::new(v.x, v.y, T::zero(), T::zero())
+    }
+}
+
+impl<T: Zero, U> From<TypedVector3D<T, U>> for HomogeneousVector<T, U> {
+    #[inline]
+    fn from(v: TypedVector3D<T, U>) -> Self {
+        HomogeneousVector::new(v.x, v.y, v.z, T::zero())
+    }
+}
+
+impl<T: Zero + One, U> From<TypedPoint2D<T, U>> for HomogeneousVector<T, U> {
+    #[inline]
+    fn from(p: TypedPoint2D<T, U>) -> Self {
+        HomogeneousVector::new(p.x, p.y, T::zero(), T::one())
+    }
+}
+
+impl<T: One, U> From<TypedPoint3D<T, U>> for HomogeneousVector<T, U> {
+    #[inline]
+    fn from(p: TypedPoint3D<T, U>) -> Self {
+        HomogeneousVector::new(p.x, p.y, p.z, T::one())
+    }
+}
+
+impl<T: fmt::Debug, U> fmt::Debug for HomogeneousVector<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({:?},{:?},{:?},{:?})", self.x, self.y, self.z, self.w)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for HomogeneousVector<T, U> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "({},{},{},{})", self.x, self.y, self.z, self.w)
+    }
+}
+
+
+#[cfg(test)]
+mod homogeneous {
+    use super::HomogeneousVector;
+    use point::{Point2D, Point3D};
+
+    #[test]
+    fn roundtrip() {
+        assert_eq!(Some(Point2D::new(1.0, 2.0)), HomogeneousVector::from(Point2D::new(1.0, 2.0)).to_point2d());
+        assert_eq!(Some(Point3D::new(1.0, -2.0, 0.1)), HomogeneousVector::from(Point3D::new(1.0, -2.0, 0.1)).to_point3d());
+    }
+
+    #[test]
+    fn negative() {
+        assert_eq!(None, HomogeneousVector::<f32, ()>::new(1.0, 2.0, 3.0, 0.0).to_point2d());
+        assert_eq!(None, HomogeneousVector::<f32, ()>::new(1.0, -2.0, -3.0, -2.0).to_point3d());
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/length.rs b/rustc_deps/vendor/euclid/src/length.rs
new file mode 100644
index 0000000..d96fed4
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/length.rs
@@ -0,0 +1,520 @@
+// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//! A one-dimensional length, tagged with its units.
+
+use scale::TypedScale;
+use num::Zero;
+
+use num_traits::{NumCast, Saturating};
+use num::One;
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use core::cmp::Ordering;
+use core::ops::{Add, Div, Mul, Neg, Sub};
+use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
+use core::marker::PhantomData;
+use core::fmt;
+
+/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
+///
+/// `T` can be any numeric type, for example a primitive type like `u64` or `f32`.
+///
+/// `Unit` is not used in the representation of a `Length` value. It is used only at compile time
+/// to ensure that a `Length` stored with one unit is converted explicitly before being used in an
+/// expression that requires a different unit.  It may be a type without values, such as an empty
+/// enum.
+///
+/// You can multiply a `Length` by a `scale::TypedScale` to convert it from one unit to
+/// another. See the [`TypedScale`] docs for an example.
+///
+/// [`TypedScale`]: struct.TypedScale.html
+#[repr(C)]
+pub struct Length<T, Unit>(pub T, #[doc(hidden)] pub PhantomData<Unit>);
+
+impl<T: Clone, Unit> Clone for Length<T, Unit> {
+    fn clone(&self) -> Self {
+        Length(self.0.clone(), PhantomData)
+    }
+}
+
+impl<T: Copy, Unit> Copy for Length<T, Unit> {}
+
+#[cfg(feature = "serde")]
+impl<'de, Unit, T> Deserialize<'de> for Length<T, Unit>
+where
+    T: Deserialize<'de>,
+{
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        Ok(Length(
+            try!(Deserialize::deserialize(deserializer)),
+            PhantomData,
+        ))
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<T, Unit> Serialize for Length<T, Unit>
+where
+    T: Serialize,
+{
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.0.serialize(serializer)
+    }
+}
+
+impl<T, Unit> Length<T, Unit> {
+    pub fn new(x: T) -> Self {
+        Length(x, PhantomData)
+    }
+}
+
+impl<Unit, T: Clone> Length<T, Unit> {
+    pub fn get(&self) -> T {
+        self.0.clone()
+    }
+}
+
+impl<T: fmt::Debug + Clone, U> fmt::Debug for Length<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.get().fmt(f)
+    }
+}
+
+impl<T: fmt::Display + Clone, U> fmt::Display for Length<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.get().fmt(f)
+    }
+}
+
+// length + length
+impl<U, T: Clone + Add<T, Output = T>> Add for Length<T, U> {
+    type Output = Length<T, U>;
+    fn add(self, other: Length<T, U>) -> Length<T, U> {
+        Length::new(self.get() + other.get())
+    }
+}
+
+// length += length
+impl<U, T: Clone + AddAssign<T>> AddAssign for Length<T, U> {
+    fn add_assign(&mut self, other: Length<T, U>) {
+        self.0 += other.get();
+    }
+}
+
+// length - length
+impl<U, T: Clone + Sub<T, Output = T>> Sub<Length<T, U>> for Length<T, U> {
+    type Output = Length<T, U>;
+    fn sub(self, other: Length<T, U>) -> <Self as Sub>::Output {
+        Length::new(self.get() - other.get())
+    }
+}
+
+// length -= length
+impl<U, T: Clone + SubAssign<T>> SubAssign for Length<T, U> {
+    fn sub_assign(&mut self, other: Length<T, U>) {
+        self.0 -= other.get();
+    }
+}
+
+// Saturating length + length and length - length.
+impl<U, T: Clone + Saturating> Saturating for Length<T, U> {
+    fn saturating_add(self, other: Length<T, U>) -> Length<T, U> {
+        Length::new(self.get().saturating_add(other.get()))
+    }
+
+    fn saturating_sub(self, other: Length<T, U>) -> Length<T, U> {
+        Length::new(self.get().saturating_sub(other.get()))
+    }
+}
+
+// length / length
+impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<Length<T, Src>> for Length<T, Dst> {
+    type Output = TypedScale<T, Src, Dst>;
+    #[inline]
+    fn div(self, other: Length<T, Src>) -> TypedScale<T, Src, Dst> {
+        TypedScale::new(self.get() / other.get())
+    }
+}
+
+// length * scalar
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Length<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        Length::new(self.get() * scale)
+    }
+}
+
+// length *= scalar
+impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for Length<T, U> {
+    #[inline]
+    fn mul_assign(&mut self, scale: T) {
+        *self = *self * scale
+    }
+}
+
+// length / scalar
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for Length<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        Length::new(self.get() / scale)
+    }
+}
+
+// length /= scalar
+impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Length<T, U> {
+    #[inline]
+    fn div_assign(&mut self, scale: T) {
+        *self = *self / scale
+    }
+}
+
+// length * scaleFactor
+impl<Src, Dst, T: Clone + Mul<T, Output = T>> Mul<TypedScale<T, Src, Dst>> for Length<T, Src> {
+    type Output = Length<T, Dst>;
+    #[inline]
+    fn mul(self, scale: TypedScale<T, Src, Dst>) -> Length<T, Dst> {
+        Length::new(self.get() * scale.get())
+    }
+}
+
+// length / scaleFactor
+impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<TypedScale<T, Src, Dst>> for Length<T, Dst> {
+    type Output = Length<T, Src>;
+    #[inline]
+    fn div(self, scale: TypedScale<T, Src, Dst>) -> Length<T, Src> {
+        Length::new(self.get() / scale.get())
+    }
+}
+
+// -length
+impl<U, T: Clone + Neg<Output = T>> Neg for Length<T, U> {
+    type Output = Length<T, U>;
+    #[inline]
+    fn neg(self) -> Length<T, U> {
+        Length::new(-self.get())
+    }
+}
+
+impl<Unit, T0: NumCast + Clone> Length<T0, Unit> {
+    /// Cast from one numeric representation to another, preserving the units.
+    pub fn cast<T1: NumCast + Clone>(&self) -> Length<T1, Unit> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Length<T1, Unit>> {
+        NumCast::from(self.get()).map(Length::new)
+    }
+}
+
+impl<Unit, T: Clone + PartialEq> PartialEq for Length<T, Unit> {
+    fn eq(&self, other: &Self) -> bool {
+        self.get().eq(&other.get())
+    }
+}
+
+impl<Unit, T: Clone + PartialOrd> PartialOrd for Length<T, Unit> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.get().partial_cmp(&other.get())
+    }
+}
+
+impl<Unit, T: Clone + Eq> Eq for Length<T, Unit> {}
+
+impl<Unit, T: Clone + Ord> Ord for Length<T, Unit> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.get().cmp(&other.get())
+    }
+}
+
+impl<Unit, T: Zero> Zero for Length<T, Unit> {
+    fn zero() -> Self {
+        Length::new(Zero::zero())
+    }
+}
+
+impl<T, U> Length<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this length and another length.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        Length::new(one_t * self.get() + t * other.get())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Length;
+    use num::Zero;
+
+    use num_traits::Saturating;
+    use scale::TypedScale;
+    use core::f32::INFINITY;
+
+    enum Inch {}
+    enum Mm {}
+    enum Cm {}
+    enum Second {}
+
+    #[cfg(feature = "serde")]
+    mod serde {
+        use super::*;
+
+        extern crate serde_test;
+        use self::serde_test::Token;
+        use self::serde_test::assert_tokens;
+
+        #[test]
+        fn test_length_serde() {
+            let one_cm: Length<f32, Mm> = Length::new(10.0);
+
+            assert_tokens(&one_cm, &[Token::F32(10.0)]);
+        }
+    }
+
+    #[test]
+    fn test_clone() {
+        // A cloned Length is a separate length with the state matching the
+        // original Length at the point it was cloned.
+        let mut variable_length: Length<f32, Inch> = Length::new(12.0);
+
+        let one_foot = variable_length.clone();
+        variable_length.0 = 24.0;
+
+        assert_eq!(one_foot.get(), 12.0);
+        assert_eq!(variable_length.get(), 24.0);
+    }
+
+    #[test]
+    fn test_get_clones_length_value() {
+        // Calling get returns a clone of the Length's value.
+        // To test this, we need something clone-able - hence a vector.
+        let mut length: Length<Vec<i32>, Inch> = Length::new(vec![1, 2, 3]);
+
+        let value = length.get();
+        length.0.push(4);
+
+        assert_eq!(value, vec![1, 2, 3]);
+        assert_eq!(length.get(), vec![1, 2, 3, 4]);
+    }
+
+    #[test]
+    fn test_add() {
+        let length1: Length<u8, Mm> = Length::new(250);
+        let length2: Length<u8, Mm> = Length::new(5);
+
+        let result = length1 + length2;
+
+        assert_eq!(result.get(), 255);
+    }
+
+    #[test]
+    fn test_addassign() {
+        let one_cm: Length<f32, Mm> = Length::new(10.0);
+        let mut measurement: Length<f32, Mm> = Length::new(5.0);
+
+        measurement += one_cm;
+
+        assert_eq!(measurement.get(), 15.0);
+    }
+
+    #[test]
+    fn test_sub() {
+        let length1: Length<u8, Mm> = Length::new(250);
+        let length2: Length<u8, Mm> = Length::new(5);
+
+        let result = length1 - length2;
+
+        assert_eq!(result.get(), 245);
+    }
+
+    #[test]
+    fn test_subassign() {
+        let one_cm: Length<f32, Mm> = Length::new(10.0);
+        let mut measurement: Length<f32, Mm> = Length::new(5.0);
+
+        measurement -= one_cm;
+
+        assert_eq!(measurement.get(), -5.0);
+    }
+
+    #[test]
+    fn test_saturating_add() {
+        let length1: Length<u8, Mm> = Length::new(250);
+        let length2: Length<u8, Mm> = Length::new(6);
+
+        let result = length1.saturating_add(length2);
+
+        assert_eq!(result.get(), 255);
+    }
+
+    #[test]
+    fn test_saturating_sub() {
+        let length1: Length<u8, Mm> = Length::new(5);
+        let length2: Length<u8, Mm> = Length::new(10);
+
+        let result = length1.saturating_sub(length2);
+
+        assert_eq!(result.get(), 0);
+    }
+
+    #[test]
+    fn test_division_by_length() {
+        // Division results in a TypedScale from denominator units
+        // to numerator units.
+        let length: Length<f32, Cm> = Length::new(5.0);
+        let duration: Length<f32, Second> = Length::new(10.0);
+
+        let result = length / duration;
+
+        let expected: TypedScale<f32, Second, Cm> = TypedScale::new(0.5);
+        assert_eq!(result, expected);
+    }
+
+    #[test]
+    fn test_multiplication() {
+        let length_mm: Length<f32, Mm> = Length::new(10.0);
+        let cm_per_mm: TypedScale<f32, Mm, Cm> = TypedScale::new(0.1);
+
+        let result = length_mm * cm_per_mm;
+
+        let expected: Length<f32, Cm> = Length::new(1.0);
+        assert_eq!(result, expected);
+    }
+
+    #[test]
+    fn test_multiplication_with_scalar() {
+        let length_mm: Length<f32, Mm> = Length::new(10.0);
+
+        let result = length_mm * 2.0;
+
+        let expected: Length<f32, Mm> = Length::new(20.0);
+        assert_eq!(result, expected);
+    }
+
+    #[test]
+    fn test_multiplication_assignment() {
+        let mut length: Length<f32, Mm> = Length::new(10.0);
+
+        length *= 2.0;
+
+        let expected: Length<f32, Mm> = Length::new(20.0);
+        assert_eq!(length, expected);
+    }
+
+    #[test]
+    fn test_division_by_scalefactor() {
+        let length: Length<f32, Cm> = Length::new(5.0);
+        let cm_per_second: TypedScale<f32, Second, Cm> = TypedScale::new(10.0);
+
+        let result = length / cm_per_second;
+
+        let expected: Length<f32, Second> = Length::new(0.5);
+        assert_eq!(result, expected);
+    }
+
+    #[test]
+    fn test_division_by_scalar() {
+        let length: Length<f32, Cm> = Length::new(5.0);
+
+        let result = length / 2.0;
+
+        let expected: Length<f32, Cm> = Length::new(2.5);
+        assert_eq!(result, expected);
+    }
+
+    #[test]
+    fn test_division_assignment() {
+        let mut length: Length<f32, Mm> = Length::new(10.0);
+
+        length /= 2.0;
+
+        let expected: Length<f32, Mm> = Length::new(5.0);
+        assert_eq!(length, expected);
+    }
+
+    #[test]
+    fn test_negation() {
+        let length: Length<f32, Cm> = Length::new(5.0);
+
+        let result = -length;
+
+        let expected: Length<f32, Cm> = Length::new(-5.0);
+        assert_eq!(result, expected);
+    }
+
+    #[test]
+    fn test_cast() {
+        let length_as_i32: Length<i32, Cm> = Length::new(5);
+
+        let result: Length<f32, Cm> = length_as_i32.cast();
+
+        let length_as_f32: Length<f32, Cm> = Length::new(5.0);
+        assert_eq!(result, length_as_f32);
+    }
+
+    #[test]
+    fn test_equality() {
+        let length_5_point_0: Length<f32, Cm> = Length::new(5.0);
+        let length_5_point_1: Length<f32, Cm> = Length::new(5.1);
+        let length_0_point_1: Length<f32, Cm> = Length::new(0.1);
+
+        assert!(length_5_point_0 == length_5_point_1 - length_0_point_1);
+        assert!(length_5_point_0 != length_5_point_1);
+    }
+
+    #[test]
+    fn test_order() {
+        let length_5_point_0: Length<f32, Cm> = Length::new(5.0);
+        let length_5_point_1: Length<f32, Cm> = Length::new(5.1);
+        let length_0_point_1: Length<f32, Cm> = Length::new(0.1);
+
+        assert!(length_5_point_0 < length_5_point_1);
+        assert!(length_5_point_0 <= length_5_point_1);
+        assert!(length_5_point_0 <= length_5_point_1 - length_0_point_1);
+        assert!(length_5_point_1 > length_5_point_0);
+        assert!(length_5_point_1 >= length_5_point_0);
+        assert!(length_5_point_0 >= length_5_point_1 - length_0_point_1);
+    }
+
+    #[test]
+    fn test_zero_add() {
+        type LengthCm = Length<f32, Cm>;
+        let length: LengthCm = Length::new(5.0);
+
+        let result = length - LengthCm::zero();
+
+        assert_eq!(result, length);
+    }
+
+    #[test]
+    fn test_zero_division() {
+        type LengthCm = Length<f32, Cm>;
+        let length: LengthCm = Length::new(5.0);
+        let length_zero: LengthCm = Length::zero();
+
+        let result = length / length_zero;
+
+        let expected: TypedScale<f32, Cm, Cm> = TypedScale::new(INFINITY);
+        assert_eq!(result, expected);
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/lib.rs b/rustc_deps/vendor/euclid/src/lib.rs
new file mode 100644
index 0000000..7f7d5ae
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/lib.rs
@@ -0,0 +1,130 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "unstable", feature(fn_must_use))]
+#![cfg_attr(not(test), no_std)]
+
+//! A collection of strongly typed math tools for computer graphics with an inclination
+//! towards 2d graphics and layout.
+//!
+//! All types are generic over the scalar type of their component (`f32`, `i32`, etc.),
+//! and tagged with a generic Unit parameter which is useful to prevent mixing
+//! values from different spaces. For example it should not be legal to translate
+//! a screen-space position by a world-space vector and this can be expressed using
+//! the generic Unit parameter.
+//!
+//! This unit system is not mandatory and all Typed* structures have an alias
+//! with the default unit: `UnknownUnit`.
+//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
+//! Client code typically creates a set of aliases for each type and doesn't need
+//! to deal with the specifics of typed units further. For example:
+//!
+//! ```rust
+//! use euclid::*;
+//! pub struct ScreenSpace;
+//! pub type ScreenPoint = TypedPoint2D<f32, ScreenSpace>;
+//! pub type ScreenSize = TypedSize2D<f32, ScreenSpace>;
+//! pub struct WorldSpace;
+//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
+//! pub type ProjectionMatrix = TypedTransform3D<f32, WorldSpace, ScreenSpace>;
+//! // etc...
+//! ```
+//!
+//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
+//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
+//!
+//! Components are accessed in their scalar form by default for convenience, and most
+//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers.
+//! For example:
+//!
+//! ```rust
+//! # use euclid::*;
+//! # pub struct WorldSpace;
+//! # pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
+//! let p = WorldPoint::new(0.0, 1.0, 1.0);
+//! // p.x is an f32.
+//! println!("p.x = {:?} ", p.x);
+//! // p.x is a Length<f32, WorldSpace>.
+//! println!("p.x_typed() = {:?} ", p.x_typed());
+//! // Length::get returns the scalar value (f32).
+//! assert_eq!(p.x, p.x_typed().get());
+//! ```
+
+#[cfg(feature = "serde")]
+#[macro_use]
+extern crate serde;
+
+#[cfg(feature = "mint")]
+pub extern crate mint;
+extern crate num_traits;
+#[cfg(test)]
+extern crate rand;
+#[cfg(test)]
+use std as core;
+
+pub use length::Length;
+pub use scale::TypedScale;
+pub use transform2d::{Transform2D, TypedTransform2D};
+pub use transform3d::{Transform3D, TypedTransform3D};
+pub use point::{Point2D, Point3D, TypedPoint2D, TypedPoint3D, point2, point3};
+pub use vector::{TypedVector2D, TypedVector3D, Vector2D, Vector3D, vec2, vec3};
+pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
+pub use homogen::HomogeneousVector;
+
+pub use rect::{rect, Rect, TypedRect};
+pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D};
+pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
+pub use size::{Size2D, TypedSize2D, size2};
+pub use trig::Trig;
+
+#[macro_use]
+mod macros;
+
+pub mod approxeq;
+mod homogen;
+pub mod num;
+mod length;
+mod point;
+mod rect;
+mod rotation;
+mod scale;
+mod side_offsets;
+mod size;
+mod transform2d;
+mod transform3d;
+mod trig;
+mod vector;
+
+/// The default unit.
+#[derive(Clone, Copy)]
+pub struct UnknownUnit;
+
+/// Temporary alias to facilitate the transition to the new naming scheme
+#[deprecated]
+pub type Matrix2D<T> = Transform2D<T>;
+
+/// Temporary alias to facilitate the transition to the new naming scheme
+#[deprecated]
+pub type TypedMatrix2D<T, Src, Dst> = TypedTransform2D<T, Src, Dst>;
+
+/// Temporary alias to facilitate the transition to the new naming scheme
+#[deprecated]
+pub type Matrix4D<T> = Transform3D<T>;
+
+/// Temporary alias to facilitate the transition to the new naming scheme
+#[deprecated]
+pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;
+
+/// Temporary alias to facilitate the transition to the new naming scheme
+#[deprecated]
+pub type ScaleFactor<T, Src, Dst> = TypedScale<T, Src, Dst>;
+
+/// Temporary alias to facilitate the transition to the new naming scheme
+#[deprecated]
+pub use Angle as Radians;
diff --git a/rustc_deps/vendor/euclid/src/macros.rs b/rustc_deps/vendor/euclid/src/macros.rs
new file mode 100644
index 0000000..cf422a8
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/macros.rs
@@ -0,0 +1,108 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! define_matrix {
+    (
+        $(#[$attr:meta])*
+        pub struct $name:ident<T, $($phantom:ident),+> {
+            $(pub $field:ident: T,)+
+        }
+    ) => (
+        #[repr(C)]
+        $(#[$attr])*
+        pub struct $name<T, $($phantom),+> {
+            $(pub $field: T,)+
+
+            // Keep this (secretly) public for the few cases where we would like to
+            // create static constants which currently can't be initialized with a
+            // function.
+            #[doc(hidden)]
+            pub _unit: PhantomData<($($phantom),+)>
+        }
+
+        impl<T: Clone, $($phantom),+> Clone for $name<T, $($phantom),+> {
+            fn clone(&self) -> Self {
+                $name {
+                    $($field: self.$field.clone(),)+
+                    _unit: PhantomData,
+                }
+            }
+        }
+
+        impl<T: Copy, $($phantom),+> Copy for $name<T, $($phantom),+> {}
+
+        #[cfg(feature = "serde")]
+        impl<'de, T, $($phantom),+> ::serde::Deserialize<'de> for $name<T, $($phantom),+>
+            where T: ::serde::Deserialize<'de>
+        {
+            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+                where D: ::serde::Deserializer<'de>
+            {
+                let ($($field,)+) =
+                    try!(::serde::Deserialize::deserialize(deserializer));
+                Ok($name {
+                    $($field: $field,)+
+                    _unit: PhantomData,
+                })
+            }
+        }
+
+        #[cfg(feature = "serde")]
+        impl<T, $($phantom),+> ::serde::Serialize for $name<T, $($phantom),+>
+            where T: ::serde::Serialize
+        {
+            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+                where S: ::serde::Serializer
+            {
+                ($(&self.$field,)+).serialize(serializer)
+            }
+        }
+
+        impl<T, $($phantom),+> ::core::cmp::Eq for $name<T, $($phantom),+>
+            where T: ::core::cmp::Eq {}
+
+        impl<T, $($phantom),+> ::core::cmp::PartialEq for $name<T, $($phantom),+>
+            where T: ::core::cmp::PartialEq
+        {
+            fn eq(&self, other: &Self) -> bool {
+                true $(&& self.$field == other.$field)+
+            }
+        }
+
+        impl<T, $($phantom),+> ::core::hash::Hash for $name<T, $($phantom),+>
+            where T: ::core::hash::Hash
+        {
+            fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
+                $(self.$field.hash(h);)+
+            }
+        }
+    )
+}
+
+macro_rules! mint_vec {
+    ($name:ident [ $($field:ident),* ] = $std_name:ident) => {
+        #[cfg(feature = "mint")]
+        impl<T, U> From<mint::$std_name<T>> for $name<T, U> {
+            fn from(v: mint::$std_name<T>) -> Self {
+                $name {
+                    $( $field: v.$field, )*
+                    _unit: PhantomData,
+                }
+            }
+        }
+        #[cfg(feature = "mint")]
+        impl<T, U> Into<mint::$std_name<T>> for $name<T, U> {
+            fn into(self) -> mint::$std_name<T> {
+                mint::$std_name {
+                    $( $field: self.$field, )*
+                }
+            }
+        }
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/num.rs b/rustc_deps/vendor/euclid/src/num.rs
new file mode 100644
index 0000000..1df86d7
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/num.rs
@@ -0,0 +1,85 @@
+// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//! A one-dimensional length, tagged with its units.
+
+use num_traits;
+
+pub trait Zero {
+    fn zero() -> Self;
+}
+
+impl<T: num_traits::Zero> Zero for T {
+    fn zero() -> T {
+        num_traits::Zero::zero()
+    }
+}
+
+pub trait One {
+    fn one() -> Self;
+}
+
+impl<T: num_traits::One> One for T {
+    fn one() -> T {
+        num_traits::One::one()
+    }
+}
+
+pub trait Round: Copy {
+    fn round(self) -> Self;
+}
+pub trait Floor: Copy {
+    fn floor(self) -> Self;
+}
+pub trait Ceil: Copy {
+    fn ceil(self) -> Self;
+}
+
+macro_rules! num_int {
+    ($ty:ty) => (
+        impl Round for $ty {
+            #[inline]
+            fn round(self) -> $ty { self }
+        }
+        impl Floor for $ty {
+            #[inline]
+            fn floor(self) -> $ty { self }
+        }
+        impl Ceil for $ty {
+            #[inline]
+            fn ceil(self) -> $ty { self }
+        }
+    )
+}
+macro_rules! num_float {
+    ($ty:ty) => (
+        impl Round for $ty {
+            #[inline]
+            fn round(self) -> $ty { self.round() }
+        }
+        impl Floor for $ty {
+            #[inline]
+            fn floor(self) -> $ty { self.floor() }
+        }
+        impl Ceil for $ty {
+            #[inline]
+            fn ceil(self) -> $ty { self.ceil() }
+        }
+    )
+}
+
+num_int!(i16);
+num_int!(u16);
+num_int!(i32);
+num_int!(u32);
+num_int!(i64);
+num_int!(u64);
+num_int!(isize);
+num_int!(usize);
+num_float!(f32);
+num_float!(f64);
diff --git a/rustc_deps/vendor/euclid/src/point.rs b/rustc_deps/vendor/euclid/src/point.rs
new file mode 100644
index 0000000..9168e15
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/point.rs
@@ -0,0 +1,958 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::UnknownUnit;
+use approxeq::ApproxEq;
+use length::Length;
+use scale::TypedScale;
+use size::TypedSize2D;
+#[cfg(feature = "mint")]
+use mint;
+use num::*;
+use num_traits::{Float, NumCast};
+use vector::{TypedVector2D, TypedVector3D, vec2, vec3};
+use core::fmt;
+use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
+use core::marker::PhantomData;
+
+define_matrix! {
+    /// A 2d Point tagged with a unit.
+    pub struct TypedPoint2D<T, U> {
+        pub x: T,
+        pub y: T,
+    }
+}
+mint_vec!(TypedPoint2D[x, y] = Point2);
+
+/// Default 2d point type with no unit.
+///
+/// `Point2D` provides the same methods as `TypedPoint2D`.
+pub type Point2D<T> = TypedPoint2D<T, UnknownUnit>;
+
+impl<T: Copy + Zero, U> TypedPoint2D<T, U> {
+    /// Constructor, setting all components to zero.
+    #[inline]
+    pub fn origin() -> Self {
+        point2(Zero::zero(), Zero::zero())
+    }
+
+    #[inline]
+    pub fn zero() -> Self {
+        Self::origin()
+    }
+
+    /// Convert into a 3d point.
+    #[inline]
+    pub fn to_3d(&self) -> TypedPoint3D<T, U> {
+        point3(self.x, self.y, Zero::zero())
+    }
+}
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedPoint2D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({:?},{:?})", self.x, self.y)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for TypedPoint2D<T, U> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "({},{})", self.x, self.y)
+    }
+}
+
+impl<T, U> TypedPoint2D<T, U> {
+    /// Constructor taking scalar values directly.
+    #[inline]
+    pub fn new(x: T, y: T) -> Self {
+        TypedPoint2D {
+            x,
+            y,
+            _unit: PhantomData,
+        }
+    }
+}
+
+impl<T: Copy, U> TypedPoint2D<T, U> {
+    /// Constructor taking properly typed Lengths instead of scalar values.
+    #[inline]
+    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>) -> Self {
+        point2(x.0, y.0)
+    }
+
+    /// Create a 3d point from this one, using the specified z value.
+    #[inline]
+    pub fn extend(&self, z: T) -> TypedPoint3D<T, U> {
+        point3(self.x, self.y, z)
+    }
+
+    /// Cast this point into a vector.
+    ///
+    /// Equivalent to subtracting the origin from this point.
+    #[inline]
+    pub fn to_vector(&self) -> TypedVector2D<T, U> {
+        vec2(self.x, self.y)
+    }
+
+    /// Swap x and y.
+    #[inline]
+    pub fn yx(&self) -> Self {
+        point2(self.y, self.x)
+    }
+
+    /// Returns self.x as a Length carrying the unit.
+    #[inline]
+    pub fn x_typed(&self) -> Length<T, U> {
+        Length::new(self.x)
+    }
+
+    /// Returns self.y as a Length carrying the unit.
+    #[inline]
+    pub fn y_typed(&self) -> Length<T, U> {
+        Length::new(self.y)
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    #[inline]
+    pub fn to_untyped(&self) -> Point2D<T> {
+        point2(self.x, self.y)
+    }
+
+    /// Tag a unitless value with units.
+    #[inline]
+    pub fn from_untyped(p: &Point2D<T>) -> Self {
+        point2(p.x, p.y)
+    }
+
+    #[inline]
+    pub fn to_array(&self) -> [T; 2] {
+        [self.x, self.y]
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> TypedPoint2D<T, U> {
+    #[inline]
+    pub fn add_size(&self, other: &TypedSize2D<T, U>) -> Self {
+        point2(self.x + other.width, self.y + other.height)
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> Add<TypedSize2D<T, U>> for TypedPoint2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn add(self, other: TypedSize2D<T, U>) -> Self {
+        point2(self.x + other.width, self.y + other.height)
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> AddAssign<TypedVector2D<T, U>> for TypedPoint2D<T, U> {
+    #[inline]
+    fn add_assign(&mut self, other: TypedVector2D<T, U>) {
+        *self = *self + other
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector2D<T, U>> for TypedPoint2D<T, U> {
+    #[inline]
+    fn sub_assign(&mut self, other: TypedVector2D<T, U>) {
+        *self = *self - other
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> Add<TypedVector2D<T, U>> for TypedPoint2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn add(self, other: TypedVector2D<T, U>) -> Self {
+        point2(self.x + other.x, self.y + other.y)
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedPoint2D<T, U> {
+    type Output = TypedVector2D<T, U>;
+    #[inline]
+    fn sub(self, other: Self) -> TypedVector2D<T, U> {
+        vec2(self.x - other.x, self.y - other.y)
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub<TypedVector2D<T, U>> for TypedPoint2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn sub(self, other: TypedVector2D<T, U>) -> Self {
+        point2(self.x - other.x, self.y - other.y)
+    }
+}
+
+impl<T: Float, U> TypedPoint2D<T, U> {
+    #[inline]
+    pub fn min(self, other: Self) -> Self {
+        point2(self.x.min(other.x), self.y.min(other.y))
+    }
+
+    #[inline]
+    pub fn max(self, other: Self) -> Self {
+        point2(self.x.max(other.x), self.y.max(other.y))
+    }
+
+    #[inline]
+    pub fn clamp(&self, start: Self, end: Self) -> Self {
+        self.max(start).min(end)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedPoint2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        point2(self.x * scale, self.y * scale)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for TypedPoint2D<T, U> {
+    #[inline]
+    fn mul_assign(&mut self, scale: T) {
+        *self = *self * scale
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedPoint2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        point2(self.x / scale, self.y / scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for TypedPoint2D<T, U> {
+    #[inline]
+    fn div_assign(&mut self, scale: T) {
+        *self = *self / scale
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedPoint2D<T, U1> {
+    type Output = TypedPoint2D<T, U2>;
+    #[inline]
+    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedPoint2D<T, U2> {
+        point2(self.x * scale.get(), self.y * scale.get())
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedPoint2D<T, U2> {
+    type Output = TypedPoint2D<T, U1>;
+    #[inline]
+    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedPoint2D<T, U1> {
+        point2(self.x / scale.get(), self.y / scale.get())
+    }
+}
+
+impl<T: Round, U> TypedPoint2D<T, U> {
+    /// Rounds each component to the nearest integer value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    /// For example `{ -0.1, -0.8 }.round() == { 0.0, -1.0 }`.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round(&self) -> Self {
+        point2(self.x.round(), self.y.round())
+    }
+}
+
+impl<T: Ceil, U> TypedPoint2D<T, U> {
+    /// Rounds each component to the smallest integer equal or greater than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    /// For example `{ -0.1, -0.8 }.ceil() == { 0.0, 0.0 }`.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn ceil(&self) -> Self {
+        point2(self.x.ceil(), self.y.ceil())
+    }
+}
+
+impl<T: Floor, U> TypedPoint2D<T, U> {
+    /// Rounds each component to the biggest integer equal or lower than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    /// For example `{ -0.1, -0.8 }.floor() == { -1.0, -1.0 }`.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn floor(&self) -> Self {
+        point2(self.x.floor(), self.y.floor())
+    }
+}
+
+impl<T: NumCast + Copy, U> TypedPoint2D<T, U> {
+    /// Cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedPoint2D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedPoint2D<NewT, U>> {
+        match (NumCast::from(self.x), NumCast::from(self.y)) {
+            (Some(x), Some(y)) => Some(point2(x, y)),
+            _ => None,
+        }
+    }
+
+    // Convenience functions for common casts
+
+    /// Cast into an `f32` point.
+    #[inline]
+    pub fn to_f32(&self) -> TypedPoint2D<f32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `f64` point.
+    #[inline]
+    pub fn to_f64(&self) -> TypedPoint2D<f64, U> {
+        self.cast()
+    }
+
+    /// Cast into an `usize` point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_usize(&self) -> TypedPoint2D<usize, U> {
+        self.cast()
+    }
+
+    /// Cast into an `u32` point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_u32(&self) -> TypedPoint2D<u32, U> {
+        self.cast()
+    }
+
+    /// Cast into an i32 point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i32(&self) -> TypedPoint2D<i32, U> {
+        self.cast()
+    }
+
+    /// Cast into an i64 point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i64(&self) -> TypedPoint2D<i64, U> {
+        self.cast()
+    }
+}
+
+impl<T, U> TypedPoint2D<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this point and another point.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        point2(one_t * self.x + t * other.x, one_t * self.y + t * other.y)
+    }
+}
+
+impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedPoint2D<T, U>> for TypedPoint2D<T, U> {
+    #[inline]
+    fn approx_epsilon() -> Self {
+        point2(T::approx_epsilon(), T::approx_epsilon())
+    }
+
+    #[inline]
+    fn approx_eq(&self, other: &Self) -> bool {
+        self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y)
+    }
+
+    #[inline]
+    fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
+        self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
+    }
+}
+
+impl<T: Copy, U> Into<[T; 2]> for TypedPoint2D<T, U> {
+    fn into(self) -> [T; 2] {
+        self.to_array()
+    }
+}
+
+impl<T: Copy, U> From<[T; 2]> for TypedPoint2D<T, U> {
+    fn from(array: [T; 2]) -> Self {
+        point2(array[0], array[1])
+    }
+}
+
+define_matrix! {
+    /// A 3d Point tagged with a unit.
+    pub struct TypedPoint3D<T, U> {
+        pub x: T,
+        pub y: T,
+        pub z: T,
+    }
+}
+mint_vec!(TypedPoint3D[x, y, z] = Point3);
+
+/// Default 3d point type with no unit.
+///
+/// `Point3D` provides the same methods as `TypedPoint3D`.
+pub type Point3D<T> = TypedPoint3D<T, UnknownUnit>;
+
+impl<T: Copy + Zero, U> TypedPoint3D<T, U> {
+    /// Constructor, setting all components to zero.
+    #[inline]
+    pub fn origin() -> Self {
+        point3(Zero::zero(), Zero::zero(), Zero::zero())
+    }
+}
+
+impl<T: Copy + One, U> TypedPoint3D<T, U> {
+    #[inline]
+    pub fn to_array_4d(&self) -> [T; 4] {
+        [self.x, self.y, self.z, One::one()]
+    }
+}
+
+impl<T, U> TypedPoint3D<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this point and another point.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        point3(
+            one_t * self.x + t * other.x,
+            one_t * self.y + t * other.y,
+            one_t * self.z + t * other.z,
+        )
+    }
+}
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedPoint3D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for TypedPoint3D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({},{},{})", self.x, self.y, self.z)
+    }
+}
+
+impl<T: Copy, U> TypedPoint3D<T, U> {
+    /// Constructor taking scalar values directly.
+    #[inline]
+    pub fn new(x: T, y: T, z: T) -> Self {
+        TypedPoint3D {
+            x,
+            y,
+            z,
+            _unit: PhantomData,
+        }
+    }
+
+    /// Constructor taking properly typed Lengths instead of scalar values.
+    #[inline]
+    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>, z: Length<T, U>) -> Self {
+        point3(x.0, y.0, z.0)
+    }
+
+    /// Cast this point into a vector.
+    ///
+    /// Equivalent to subtracting the origin to this point.
+    #[inline]
+    pub fn to_vector(&self) -> TypedVector3D<T, U> {
+        vec3(self.x, self.y, self.z)
+    }
+
+    /// Returns a 2d point using this point's x and y coordinates
+    #[inline]
+    pub fn xy(&self) -> TypedPoint2D<T, U> {
+        point2(self.x, self.y)
+    }
+
+    /// Returns a 2d point using this point's x and z coordinates
+    #[inline]
+    pub fn xz(&self) -> TypedPoint2D<T, U> {
+        point2(self.x, self.z)
+    }
+
+    /// Returns a 2d point using this point's x and z coordinates
+    #[inline]
+    pub fn yz(&self) -> TypedPoint2D<T, U> {
+        point2(self.y, self.z)
+    }
+
+    /// Returns self.x as a Length carrying the unit.
+    #[inline]
+    pub fn x_typed(&self) -> Length<T, U> {
+        Length::new(self.x)
+    }
+
+    /// Returns self.y as a Length carrying the unit.
+    #[inline]
+    pub fn y_typed(&self) -> Length<T, U> {
+        Length::new(self.y)
+    }
+
+    /// Returns self.z as a Length carrying the unit.
+    #[inline]
+    pub fn z_typed(&self) -> Length<T, U> {
+        Length::new(self.z)
+    }
+
+    #[inline]
+    pub fn to_array(&self) -> [T; 3] {
+        [self.x, self.y, self.z]
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    #[inline]
+    pub fn to_untyped(&self) -> Point3D<T> {
+        point3(self.x, self.y, self.z)
+    }
+
+    /// Tag a unitless value with units.
+    #[inline]
+    pub fn from_untyped(p: &Point3D<T>) -> Self {
+        point3(p.x, p.y, p.z)
+    }
+
+    /// Convert into a 2d point.
+    #[inline]
+    pub fn to_2d(&self) -> TypedPoint2D<T, U> {
+        self.xy()
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> AddAssign<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+    #[inline]
+    fn add_assign(&mut self, other: TypedVector3D<T, U>) {
+        *self = *self + other
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+    #[inline]
+    fn sub_assign(&mut self, other: TypedVector3D<T, U>) {
+        *self = *self - other
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> Add<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn add(self, other: TypedVector3D<T, U>) -> Self {
+        point3(self.x + other.x, self.y + other.y, self.z + other.z)
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedPoint3D<T, U> {
+    type Output = TypedVector3D<T, U>;
+    #[inline]
+    fn sub(self, other: Self) -> TypedVector3D<T, U> {
+        vec3(self.x - other.x, self.y - other.y, self.z - other.z)
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn sub(self, other: TypedVector3D<T, U>) -> Self {
+        point3(self.x - other.x, self.y - other.y, self.z - other.z)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedPoint3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        point3(self.x * scale, self.y * scale, self.z * scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedPoint3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        point3(self.x / scale, self.y / scale, self.z / scale)
+    }
+}
+
+impl<T: Float, U> TypedPoint3D<T, U> {
+    #[inline]
+    pub fn min(self, other: Self) -> Self {
+        point3(
+            self.x.min(other.x),
+            self.y.min(other.y),
+            self.z.min(other.z),
+        )
+    }
+
+    #[inline]
+    pub fn max(self, other: Self) -> Self {
+        point3(
+            self.x.max(other.x),
+            self.y.max(other.y),
+            self.z.max(other.z),
+        )
+    }
+
+    #[inline]
+    pub fn clamp(&self, start: Self, end: Self) -> Self {
+        self.max(start).min(end)
+    }
+}
+
+impl<T: Round, U> TypedPoint3D<T, U> {
+    /// Rounds each component to the nearest integer value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round(&self) -> Self {
+        point3(self.x.round(), self.y.round(), self.z.round())
+    }
+}
+
+impl<T: Ceil, U> TypedPoint3D<T, U> {
+    /// Rounds each component to the smallest integer equal or greater than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn ceil(&self) -> Self {
+        point3(self.x.ceil(), self.y.ceil(), self.z.ceil())
+    }
+}
+
+impl<T: Floor, U> TypedPoint3D<T, U> {
+    /// Rounds each component to the biggest integer equal or lower than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn floor(&self) -> Self {
+        point3(self.x.floor(), self.y.floor(), self.z.floor())
+    }
+}
+
+impl<T: NumCast + Copy, U> TypedPoint3D<T, U> {
+    /// Cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedPoint3D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedPoint3D<NewT, U>> {
+        match (
+            NumCast::from(self.x),
+            NumCast::from(self.y),
+            NumCast::from(self.z),
+        ) {
+            (Some(x), Some(y), Some(z)) => Some(point3(x, y, z)),
+            _ => None,
+        }
+    }
+
+    // Convenience functions for common casts
+
+    /// Cast into an `f32` point.
+    #[inline]
+    pub fn to_f32(&self) -> TypedPoint3D<f32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `f64` point.
+    #[inline]
+    pub fn to_f64(&self) -> TypedPoint3D<f64, U> {
+        self.cast()
+    }
+
+    /// Cast into an `usize` point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_usize(&self) -> TypedPoint3D<usize, U> {
+        self.cast()
+    }
+
+    /// Cast into an `u32` point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_u32(&self) -> TypedPoint3D<u32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `i32` point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i32(&self) -> TypedPoint3D<i32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `i64` point, truncating decimals if any.
+    ///
+    /// When casting from floating point points, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i64(&self) -> TypedPoint3D<i64, U> {
+        self.cast()
+    }
+}
+
+impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedPoint3D<T, U>> for TypedPoint3D<T, U> {
+    #[inline]
+    fn approx_epsilon() -> Self {
+        point3(
+            T::approx_epsilon(),
+            T::approx_epsilon(),
+            T::approx_epsilon(),
+        )
+    }
+
+    #[inline]
+    fn approx_eq(&self, other: &Self) -> bool {
+        self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) && self.z.approx_eq(&other.z)
+    }
+
+    #[inline]
+    fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
+        self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
+            && self.z.approx_eq_eps(&other.z, &eps.z)
+    }
+}
+
+impl<T: Copy, U> Into<[T; 3]> for TypedPoint3D<T, U> {
+    fn into(self) -> [T; 3] {
+        self.to_array()
+    }
+}
+
+impl<T: Copy, U> From<[T; 3]> for TypedPoint3D<T, U> {
+    fn from(array: [T; 3]) -> Self {
+        point3(array[0], array[1], array[2])
+    }
+}
+
+pub fn point2<T: Copy, U>(x: T, y: T) -> TypedPoint2D<T, U> {
+    TypedPoint2D::new(x, y)
+}
+
+pub fn point3<T: Copy, U>(x: T, y: T, z: T) -> TypedPoint3D<T, U> {
+    TypedPoint3D::new(x, y, z)
+}
+
+
+#[cfg(test)]
+mod point2d {
+    use super::Point2D;
+    #[cfg(feature = "mint")]
+    use mint;
+
+    #[test]
+    pub fn test_scalar_mul() {
+        let p1: Point2D<f32> = Point2D::new(3.0, 5.0);
+
+        let result = p1 * 5.0;
+
+        assert_eq!(result, Point2D::new(15.0, 25.0));
+    }
+
+    #[test]
+    pub fn test_min() {
+        let p1 = Point2D::new(1.0, 3.0);
+        let p2 = Point2D::new(2.0, 2.0);
+
+        let result = p1.min(p2);
+
+        assert_eq!(result, Point2D::new(1.0, 2.0));
+    }
+
+    #[test]
+    pub fn test_max() {
+        let p1 = Point2D::new(1.0, 3.0);
+        let p2 = Point2D::new(2.0, 2.0);
+
+        let result = p1.max(p2);
+
+        assert_eq!(result, Point2D::new(2.0, 3.0));
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let p1 = Point2D::new(1.0, 3.0);
+        let pm: mint::Point2<_> = p1.into();
+        let p2 = Point2D::from(pm);
+
+        assert_eq!(p1, p2);
+    }
+}
+
+#[cfg(test)]
+mod typedpoint2d {
+    use super::{Point2D, TypedPoint2D, point2};
+    use scale::TypedScale;
+    use vector::vec2;
+
+    pub enum Mm {}
+    pub enum Cm {}
+
+    pub type Point2DMm<T> = TypedPoint2D<T, Mm>;
+    pub type Point2DCm<T> = TypedPoint2D<T, Cm>;
+
+    #[test]
+    pub fn test_add() {
+        let p1 = Point2DMm::new(1.0, 2.0);
+        let p2 = vec2(3.0, 4.0);
+
+        let result = p1 + p2;
+
+        assert_eq!(result, Point2DMm::new(4.0, 6.0));
+    }
+
+    #[test]
+    pub fn test_add_assign() {
+        let mut p1 = Point2DMm::new(1.0, 2.0);
+        p1 += vec2(3.0, 4.0);
+
+        assert_eq!(p1, Point2DMm::new(4.0, 6.0));
+    }
+
+    #[test]
+    pub fn test_scalar_mul() {
+        let p1 = Point2DMm::new(1.0, 2.0);
+        let cm_per_mm: TypedScale<f32, Mm, Cm> = TypedScale::new(0.1);
+
+        let result = p1 * cm_per_mm;
+
+        assert_eq!(result, Point2DCm::new(0.1, 0.2));
+    }
+
+    #[test]
+    pub fn test_conv_vector() {
+        use {Point2D, point2};
+
+        for i in 0..100 {
+            // We don't care about these values as long as they are not the same.
+            let x = i as f32 * 0.012345;
+            let y = i as f32 * 0.987654;
+            let p: Point2D<f32> = point2(x, y);
+            assert_eq!(p.to_vector().to_point(), p);
+        }
+    }
+
+    #[test]
+    pub fn test_swizzling() {
+        let p: Point2D<i32> = point2(1, 2);
+        assert_eq!(p.yx(), point2(2, 1));
+    }
+}
+
+#[cfg(test)]
+mod point3d {
+    use super::{Point3D, point2, point3};
+    #[cfg(feature = "mint")]
+    use mint;
+
+    #[test]
+    pub fn test_min() {
+        let p1 = Point3D::new(1.0, 3.0, 5.0);
+        let p2 = Point3D::new(2.0, 2.0, -1.0);
+
+        let result = p1.min(p2);
+
+        assert_eq!(result, Point3D::new(1.0, 2.0, -1.0));
+    }
+
+    #[test]
+    pub fn test_max() {
+        let p1 = Point3D::new(1.0, 3.0, 5.0);
+        let p2 = Point3D::new(2.0, 2.0, -1.0);
+
+        let result = p1.max(p2);
+
+        assert_eq!(result, Point3D::new(2.0, 3.0, 5.0));
+    }
+
+    #[test]
+    pub fn test_conv_vector() {
+        use point3;
+        for i in 0..100 {
+            // We don't care about these values as long as they are not the same.
+            let x = i as f32 * 0.012345;
+            let y = i as f32 * 0.987654;
+            let z = x * y;
+            let p: Point3D<f32> = point3(x, y, z);
+            assert_eq!(p.to_vector().to_point(), p);
+        }
+    }
+
+    #[test]
+    pub fn test_swizzling() {
+        let p: Point3D<i32> = point3(1, 2, 3);
+        assert_eq!(p.xy(), point2(1, 2));
+        assert_eq!(p.xz(), point2(1, 3));
+        assert_eq!(p.yz(), point2(2, 3));
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let p1 = Point3D::new(1.0, 3.0, 5.0);
+        let pm: mint::Point3<_> = p1.into();
+        let p2 = Point3D::from(pm);
+
+        assert_eq!(p1, p2);
+    }
+
+}
diff --git a/rustc_deps/vendor/euclid/src/rect.rs b/rustc_deps/vendor/euclid/src/rect.rs
new file mode 100644
index 0000000..fe07863
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/rect.rs
@@ -0,0 +1,857 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::UnknownUnit;
+use length::Length;
+use scale::TypedScale;
+use num::*;
+use point::TypedPoint2D;
+use vector::TypedVector2D;
+use side_offsets::TypedSideOffsets2D;
+use size::TypedSize2D;
+
+use num_traits::NumCast;
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+
+use core::borrow::Borrow;
+use core::cmp::PartialOrd;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ops::{Add, Div, Mul, Sub};
+
+
+/// A 2d Rectangle optionally tagged with a unit.
+#[repr(C)]
+pub struct TypedRect<T, U = UnknownUnit> {
+    pub origin: TypedPoint2D<T, U>,
+    pub size: TypedSize2D<T, U>,
+}
+
+/// The default rectangle type with no unit.
+pub type Rect<T> = TypedRect<T, UnknownUnit>;
+
+#[cfg(feature = "serde")]
+impl<'de, T: Copy + Deserialize<'de>, U> Deserialize<'de> for TypedRect<T, U> {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let (origin, size) = try!(Deserialize::deserialize(deserializer));
+        Ok(TypedRect::new(origin, size))
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<T: Serialize, U> Serialize for TypedRect<T, U> {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        (&self.origin, &self.size).serialize(serializer)
+    }
+}
+
+impl<T: Hash, U> Hash for TypedRect<T, U> {
+    fn hash<H: Hasher>(&self, h: &mut H) {
+        self.origin.hash(h);
+        self.size.hash(h);
+    }
+}
+
+impl<T: Copy, U> Copy for TypedRect<T, U> {}
+
+impl<T: Copy, U> Clone for TypedRect<T, U> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T: PartialEq, U> PartialEq<TypedRect<T, U>> for TypedRect<T, U> {
+    fn eq(&self, other: &Self) -> bool {
+        self.origin.eq(&other.origin) && self.size.eq(&other.size)
+    }
+}
+
+impl<T: Eq, U> Eq for TypedRect<T, U> {}
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedRect<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TypedRect({:?} at {:?})", self.size, self.origin)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for TypedRect<T, U> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "Rect({} at {})", self.size, self.origin)
+    }
+}
+
+impl<T, U> TypedRect<T, U> {
+    /// Constructor.
+    pub fn new(origin: TypedPoint2D<T, U>, size: TypedSize2D<T, U>) -> Self {
+        TypedRect {
+            origin,
+            size,
+        }
+    }
+}
+
+impl<T, U> TypedRect<T, U>
+where
+    T: Copy + Zero
+{
+    /// Creates a rect of the given size, at offset zero.
+    pub fn from_size(size: TypedSize2D<T, U>) -> Self {
+        TypedRect {
+            origin: TypedPoint2D::zero(),
+            size,
+        }
+    }
+}
+
+impl<T, U> TypedRect<T, U>
+where
+    T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
+{
+    #[inline]
+    pub fn intersects(&self, other: &Self) -> bool {
+        self.origin.x < other.origin.x + other.size.width
+            && other.origin.x < self.origin.x + self.size.width
+            && self.origin.y < other.origin.y + other.size.height
+            && other.origin.y < self.origin.y + self.size.height
+    }
+
+    #[inline]
+    pub fn max_x(&self) -> T {
+        self.origin.x + self.size.width
+    }
+
+    #[inline]
+    pub fn min_x(&self) -> T {
+        self.origin.x
+    }
+
+    #[inline]
+    pub fn max_y(&self) -> T {
+        self.origin.y + self.size.height
+    }
+
+    #[inline]
+    pub fn min_y(&self) -> T {
+        self.origin.y
+    }
+
+    #[inline]
+    pub fn max_x_typed(&self) -> Length<T, U> {
+        Length::new(self.max_x())
+    }
+
+    #[inline]
+    pub fn min_x_typed(&self) -> Length<T, U> {
+        Length::new(self.min_x())
+    }
+
+    #[inline]
+    pub fn max_y_typed(&self) -> Length<T, U> {
+        Length::new(self.max_y())
+    }
+
+    #[inline]
+    pub fn min_y_typed(&self) -> Length<T, U> {
+        Length::new(self.min_y())
+    }
+
+    #[inline]
+    pub fn intersection(&self, other: &Self) -> Option<Self> {
+        if !self.intersects(other) {
+            return None;
+        }
+
+        let upper_left = TypedPoint2D::new(
+            max(self.min_x(), other.min_x()),
+            max(self.min_y(), other.min_y()),
+        );
+        let lower_right_x = min(self.max_x(), other.max_x());
+        let lower_right_y = min(self.max_y(), other.max_y());
+
+        Some(TypedRect::new(
+            upper_left,
+            TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
+        ))
+    }
+
+    /// Returns the same rectangle, translated by a vector.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn translate(&self, by: &TypedVector2D<T, U>) -> Self {
+        Self::new(self.origin + *by, self.size)
+    }
+
+    /// Returns true if this rectangle contains the point. Points are considered
+    /// in the rectangle if they are on the left or top edge, but outside if they
+    /// are on the right or bottom edge.
+    #[inline]
+    pub fn contains(&self, other: &TypedPoint2D<T, U>) -> bool {
+        self.origin.x <= other.x && other.x < self.origin.x + self.size.width
+            && self.origin.y <= other.y && other.y < self.origin.y + self.size.height
+    }
+
+    /// Returns true if this rectangle contains the interior of rect. Always
+    /// returns true if rect is empty, and always returns false if rect is
+    /// nonempty but this rectangle is empty.
+    #[inline]
+    pub fn contains_rect(&self, rect: &Self) -> bool {
+        rect.is_empty()
+            || (self.min_x() <= rect.min_x() && rect.max_x() <= self.max_x()
+                && self.min_y() <= rect.min_y() && rect.max_y() <= self.max_y())
+    }
+
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn inflate(&self, width: T, height: T) -> Self {
+        TypedRect::new(
+            TypedPoint2D::new(self.origin.x - width, self.origin.y - height),
+            TypedSize2D::new(
+                self.size.width + width + width,
+                self.size.height + height + height,
+            ),
+        )
+    }
+
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn inflate_typed(&self, width: Length<T, U>, height: Length<T, U>) -> Self {
+        self.inflate(width.get(), height.get())
+    }
+
+    #[inline]
+    pub fn top_right(&self) -> TypedPoint2D<T, U> {
+        TypedPoint2D::new(self.max_x(), self.origin.y)
+    }
+
+    #[inline]
+    pub fn bottom_left(&self) -> TypedPoint2D<T, U> {
+        TypedPoint2D::new(self.origin.x, self.max_y())
+    }
+
+    #[inline]
+    pub fn bottom_right(&self) -> TypedPoint2D<T, U> {
+        TypedPoint2D::new(self.max_x(), self.max_y())
+    }
+
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn translate_by_size(&self, size: &TypedSize2D<T, U>) -> Self {
+        self.translate(&size.to_vector())
+    }
+
+    /// Calculate the size and position of an inner rectangle.
+    ///
+    /// Subtracts the side offsets from all sides. The horizontal and vertical
+    /// offsets must not be larger than the original side length.
+    pub fn inner_rect(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
+        let rect = TypedRect::new(
+            TypedPoint2D::new(
+                self.origin.x + offsets.left,
+                self.origin.y + offsets.top
+            ),
+            TypedSize2D::new(
+                self.size.width - offsets.horizontal(),
+                self.size.height - offsets.vertical()
+            )
+        );
+        debug_assert!(rect.size.width >= Zero::zero());
+        debug_assert!(rect.size.height >= Zero::zero());
+        rect
+    }
+
+    /// Calculate the size and position of an outer rectangle.
+    ///
+    /// Add the offsets to all sides. The expanded rectangle is returned.
+    pub fn outer_rect(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
+        TypedRect::new(
+            TypedPoint2D::new(
+                self.origin.x - offsets.left,
+                self.origin.y - offsets.top
+            ),
+            TypedSize2D::new(
+                self.size.width + offsets.horizontal(),
+                self.size.height + offsets.vertical()
+            )
+        )
+    }
+
+    /// Returns the smallest rectangle defined by the top/bottom/left/right-most
+    /// points provided as parameter.
+    ///
+    /// Note: This function has a behavior that can be surprising because
+    /// the right-most and bottom-most points are exactly on the edge
+    /// of the rectangle while the `contains` function is has exclusive
+    /// semantic on these edges. This means that the right-most and bottom-most
+    /// points provided to `from_points` will count as not contained by the rect.
+    /// This behavior may change in the future.
+    pub fn from_points<I>(points: I) -> Self
+    where
+        I: IntoIterator,
+        I::Item: Borrow<TypedPoint2D<T, U>>,
+    {
+        let mut points = points.into_iter();
+
+        let (mut min_x, mut min_y) = match points.next() {
+            Some(first) => (first.borrow().x, first.borrow().y),
+            None => return TypedRect::zero(),
+        };
+
+        let (mut max_x, mut max_y) = (min_x, min_y);
+        for point in points {
+            let p = point.borrow();
+            if p.x < min_x {
+                min_x = p.x
+            }
+            if p.x > max_x {
+                max_x = p.x
+            }
+            if p.y < min_y {
+                min_y = p.y
+            }
+            if p.y > max_y {
+                max_y = p.y
+            }
+        }
+        TypedRect::new(
+            TypedPoint2D::new(min_x, min_y),
+            TypedSize2D::new(max_x - min_x, max_y - min_y),
+        )
+    }
+}
+
+impl<T, U> TypedRect<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this rectangle and another rectangle.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        Self::new(
+            self.origin.lerp(other.origin, t),
+            self.size.lerp(other.size, t),
+        )
+    }
+}
+
+impl<T, U> TypedRect<T, U>
+where
+    T: Copy + One + Add<Output = T> + Div<Output = T>,
+{
+    pub fn center(&self) -> TypedPoint2D<T, U> {
+        let two = T::one() + T::one();
+        self.origin + self.size.to_vector() / two
+    }
+}
+
+impl<T, U> TypedRect<T, U>
+where
+    T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
+{
+    #[inline]
+    pub fn union(&self, other: &Self) -> Self {
+        if self.size == Zero::zero() {
+            return *other;
+        }
+        if other.size == Zero::zero() {
+            return *self;
+        }
+
+        let upper_left = TypedPoint2D::new(
+            min(self.min_x(), other.min_x()),
+            min(self.min_y(), other.min_y()),
+        );
+
+        let lower_right_x = max(self.max_x(), other.max_x());
+        let lower_right_y = max(self.max_y(), other.max_y());
+
+        TypedRect::new(
+            upper_left,
+            TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
+        )
+    }
+}
+
+impl<T, U> TypedRect<T, U> {
+    #[inline]
+    pub fn scale<S: Copy>(&self, x: S, y: S) -> Self
+    where
+        T: Copy + Clone + Mul<S, Output = T>,
+    {
+        TypedRect::new(
+            TypedPoint2D::new(self.origin.x * x, self.origin.y * y),
+            TypedSize2D::new(self.size.width * x, self.size.height * y),
+        )
+    }
+}
+
+impl<T: Copy + PartialEq + Zero, U> TypedRect<T, U> {
+    /// Constructor, setting all sides to zero.
+    pub fn zero() -> Self {
+        TypedRect::new(TypedPoint2D::origin(), TypedSize2D::zero())
+    }
+
+    /// Returns true if the size is zero, regardless of the origin's value.
+    pub fn is_empty(&self) -> bool {
+        self.size.width == Zero::zero() || self.size.height == Zero::zero()
+    }
+}
+
+pub fn min<T: Clone + PartialOrd>(x: T, y: T) -> T {
+    if x <= y {
+        x
+    } else {
+        y
+    }
+}
+
+pub fn max<T: Clone + PartialOrd>(x: T, y: T) -> T {
+    if x >= y {
+        x
+    } else {
+        y
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedRect<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        TypedRect::new(self.origin * scale, self.size * scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedRect<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        TypedRect::new(self.origin / scale, self.size / scale)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedRect<T, U1> {
+    type Output = TypedRect<T, U2>;
+    #[inline]
+    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedRect<T, U2> {
+        TypedRect::new(self.origin * scale, self.size * scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedRect<T, U2> {
+    type Output = TypedRect<T, U1>;
+    #[inline]
+    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedRect<T, U1> {
+        TypedRect::new(self.origin / scale, self.size / scale)
+    }
+}
+
+impl<T: Copy, Unit> TypedRect<T, Unit> {
+    /// Drop the units, preserving only the numeric value.
+    pub fn to_untyped(&self) -> Rect<T> {
+        TypedRect::new(self.origin.to_untyped(), self.size.to_untyped())
+    }
+
+    /// Tag a unitless value with units.
+    pub fn from_untyped(r: &Rect<T>) -> TypedRect<T, Unit> {
+        TypedRect::new(
+            TypedPoint2D::from_untyped(&r.origin),
+            TypedSize2D::from_untyped(&r.size),
+        )
+    }
+}
+
+impl<T0: NumCast + Copy, Unit> TypedRect<T0, Unit> {
+    /// Cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using round(), round_in or round_out() before casting.
+    pub fn cast<T1: NumCast + Copy>(&self) -> TypedRect<T1, Unit> {
+        TypedRect::new(
+            self.origin.cast(),
+            self.size.cast(),
+        )
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using round(), round_in or round_out() before casting.
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedRect<T1, Unit>> {
+        match (self.origin.try_cast(), self.size.try_cast()) {
+            (Some(origin), Some(size)) => Some(TypedRect::new(origin, size)),
+            _ => None,
+        }
+    }
+}
+
+impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> TypedRect<T, U> {
+    /// Return a rectangle with edges rounded to integer coordinates, such that
+    /// the returned rectangle has the same set of pixel centers as the original
+    /// one.
+    /// Edges at offset 0.5 round up.
+    /// Suitable for most places where integral device coordinates
+    /// are needed, but note that any translation should be applied first to
+    /// avoid pixel rounding errors.
+    /// Note that this is *not* rounding to nearest integer if the values are negative.
+    /// They are always rounding as floor(n + 0.5).
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round(&self) -> Self {
+        let origin = self.origin.round();
+        let size = self.origin.add_size(&self.size).round() - origin;
+        TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
+    }
+
+    /// Return a rectangle with edges rounded to integer coordinates, such that
+    /// the original rectangle contains the resulting rectangle.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round_in(&self) -> Self {
+        let origin = self.origin.ceil();
+        let size = self.origin.add_size(&self.size).floor() - origin;
+        TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
+    }
+
+    /// Return a rectangle with edges rounded to integer coordinates, such that
+    /// the original rectangle is contained in the resulting rectangle.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round_out(&self) -> Self {
+        let origin = self.origin.floor();
+        let size = self.origin.add_size(&self.size).ceil() - origin;
+        TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
+    }
+}
+
+// Convenience functions for common casts
+impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
+    /// Cast into an `f32` rectangle.
+    pub fn to_f32(&self) -> TypedRect<f32, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `f64` rectangle.
+    pub fn to_f64(&self) -> TypedRect<f64, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `usize` rectangle, truncating decimals if any.
+    ///
+    /// When casting from floating point rectangles, it is worth considering whether
+    /// to `round()`, `round_in()` or `round_out()` before the cast in order to
+    /// obtain the desired conversion behavior.
+    pub fn to_usize(&self) -> TypedRect<usize, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `u32` rectangle, truncating decimals if any.
+    ///
+    /// When casting from floating point rectangles, it is worth considering whether
+    /// to `round()`, `round_in()` or `round_out()` before the cast in order to
+    /// obtain the desired conversion behavior.
+    pub fn to_u32(&self) -> TypedRect<u32, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `i32` rectangle, truncating decimals if any.
+    ///
+    /// When casting from floating point rectangles, it is worth considering whether
+    /// to `round()`, `round_in()` or `round_out()` before the cast in order to
+    /// obtain the desired conversion behavior.
+    pub fn to_i32(&self) -> TypedRect<i32, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `i64` rectangle, truncating decimals if any.
+    ///
+    /// When casting from floating point rectangles, it is worth considering whether
+    /// to `round()`, `round_in()` or `round_out()` before the cast in order to
+    /// obtain the desired conversion behavior.
+    pub fn to_i64(&self) -> TypedRect<i64, Unit> {
+        self.cast()
+    }
+}
+
+impl<T, U> From<TypedSize2D<T, U>> for TypedRect<T, U>
+where T: Copy + Zero
+{
+    fn from(size: TypedSize2D<T, U>) -> Self {
+        Self::from_size(size)
+    }
+}
+
+/// Shorthand for `TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))`.
+pub fn rect<T: Copy, U>(x: T, y: T, w: T, h: T) -> TypedRect<T, U> {
+    TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))
+}
+
+#[cfg(test)]
+mod tests {
+    use point::{Point2D, point2};
+    use vector::vec2;
+    use side_offsets::SideOffsets2D;
+    use size::Size2D;
+    use super::*;
+
+    #[test]
+    fn test_min_max() {
+        assert!(min(0u32, 1u32) == 0u32);
+        assert!(min(-1.0f32, 0.0f32) == -1.0f32);
+
+        assert!(max(0u32, 1u32) == 1u32);
+        assert!(max(-1.0f32, 0.0f32) == 0.0f32);
+    }
+
+    #[test]
+    fn test_translate() {
+        let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
+        let pp = p.translate(&vec2(10, 15));
+
+        assert!(pp.size.width == 50);
+        assert!(pp.size.height == 40);
+        assert!(pp.origin.x == 10);
+        assert!(pp.origin.y == 15);
+
+        let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
+        let rr = r.translate(&vec2(0, -10));
+
+        assert!(rr.size.width == 50);
+        assert!(rr.size.height == 40);
+        assert!(rr.origin.x == -10);
+        assert!(rr.origin.y == -15);
+    }
+
+    #[test]
+    fn test_translate_by_size() {
+        let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
+        let pp = p.translate_by_size(&Size2D::new(10, 15));
+
+        assert!(pp.size.width == 50);
+        assert!(pp.size.height == 40);
+        assert!(pp.origin.x == 10);
+        assert!(pp.origin.y == 15);
+
+        let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
+        let rr = r.translate_by_size(&Size2D::new(0, -10));
+
+        assert!(rr.size.width == 50);
+        assert!(rr.size.height == 40);
+        assert!(rr.origin.x == -10);
+        assert!(rr.origin.y == -15);
+    }
+
+    #[test]
+    fn test_union() {
+        let p = Rect::new(Point2D::new(0, 0), Size2D::new(50, 40));
+        let q = Rect::new(Point2D::new(20, 20), Size2D::new(5, 5));
+        let r = Rect::new(Point2D::new(-15, -30), Size2D::new(200, 15));
+        let s = Rect::new(Point2D::new(20, -15), Size2D::new(250, 200));
+
+        let pq = p.union(&q);
+        assert!(pq.origin == Point2D::new(0, 0));
+        assert!(pq.size == Size2D::new(50, 40));
+
+        let pr = p.union(&r);
+        assert!(pr.origin == Point2D::new(-15, -30));
+        assert!(pr.size == Size2D::new(200, 70));
+
+        let ps = p.union(&s);
+        assert!(ps.origin == Point2D::new(0, -15));
+        assert!(ps.size == Size2D::new(270, 200));
+    }
+
+    #[test]
+    fn test_intersection() {
+        let p = Rect::new(Point2D::new(0, 0), Size2D::new(10, 20));
+        let q = Rect::new(Point2D::new(5, 15), Size2D::new(10, 10));
+        let r = Rect::new(Point2D::new(-5, -5), Size2D::new(8, 8));
+
+        let pq = p.intersection(&q);
+        assert!(pq.is_some());
+        let pq = pq.unwrap();
+        assert!(pq.origin == Point2D::new(5, 15));
+        assert!(pq.size == Size2D::new(5, 5));
+
+        let pr = p.intersection(&r);
+        assert!(pr.is_some());
+        let pr = pr.unwrap();
+        assert!(pr.origin == Point2D::new(0, 0));
+        assert!(pr.size == Size2D::new(3, 3));
+
+        let qr = q.intersection(&r);
+        assert!(qr.is_none());
+    }
+
+    #[test]
+    fn test_contains() {
+        let r = Rect::new(Point2D::new(-20, 15), Size2D::new(100, 200));
+
+        assert!(r.contains(&Point2D::new(0, 50)));
+        assert!(r.contains(&Point2D::new(-10, 200)));
+
+        // The `contains` method is inclusive of the top/left edges, but not the
+        // bottom/right edges.
+        assert!(r.contains(&Point2D::new(-20, 15)));
+        assert!(!r.contains(&Point2D::new(80, 15)));
+        assert!(!r.contains(&Point2D::new(80, 215)));
+        assert!(!r.contains(&Point2D::new(-20, 215)));
+
+        // Points beyond the top-left corner.
+        assert!(!r.contains(&Point2D::new(-25, 15)));
+        assert!(!r.contains(&Point2D::new(-15, 10)));
+
+        // Points beyond the top-right corner.
+        assert!(!r.contains(&Point2D::new(85, 20)));
+        assert!(!r.contains(&Point2D::new(75, 10)));
+
+        // Points beyond the bottom-right corner.
+        assert!(!r.contains(&Point2D::new(85, 210)));
+        assert!(!r.contains(&Point2D::new(75, 220)));
+
+        // Points beyond the bottom-left corner.
+        assert!(!r.contains(&Point2D::new(-25, 210)));
+        assert!(!r.contains(&Point2D::new(-15, 220)));
+
+        let r = Rect::new(Point2D::new(-20.0, 15.0), Size2D::new(100.0, 200.0));
+        assert!(r.contains_rect(&r));
+        assert!(!r.contains_rect(&r.translate(&vec2(0.1, 0.0))));
+        assert!(!r.contains_rect(&r.translate(&vec2(-0.1, 0.0))));
+        assert!(!r.contains_rect(&r.translate(&vec2(0.0, 0.1))));
+        assert!(!r.contains_rect(&r.translate(&vec2(0.0, -0.1))));
+        // Empty rectangles are always considered as contained in other rectangles,
+        // even if their origin is not.
+        let p = Point2D::new(1.0, 1.0);
+        assert!(!r.contains(&p));
+        assert!(r.contains_rect(&Rect::new(p, Size2D::zero())));
+    }
+
+    #[test]
+    fn test_scale() {
+        let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
+        let pp = p.scale(10, 15);
+
+        assert!(pp.size.width == 500);
+        assert!(pp.size.height == 600);
+        assert!(pp.origin.x == 0);
+        assert!(pp.origin.y == 0);
+
+        let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
+        let rr = r.scale(1, 20);
+
+        assert!(rr.size.width == 50);
+        assert!(rr.size.height == 800);
+        assert!(rr.origin.x == -10);
+        assert!(rr.origin.y == -100);
+    }
+
+    #[test]
+    fn test_inflate() {
+        let p = Rect::new(Point2D::new(0, 0), Size2D::new(10, 10));
+        let pp = p.inflate(10, 20);
+
+        assert!(pp.size.width == 30);
+        assert!(pp.size.height == 50);
+        assert!(pp.origin.x == -10);
+        assert!(pp.origin.y == -20);
+
+        let r = Rect::new(Point2D::new(0, 0), Size2D::new(10, 20));
+        let rr = r.inflate(-2, -5);
+
+        assert!(rr.size.width == 6);
+        assert!(rr.size.height == 10);
+        assert!(rr.origin.x == 2);
+        assert!(rr.origin.y == 5);
+    }
+
+    #[test]
+    fn test_inner_outer_rect() {
+        let inner_rect: Rect<i32> = Rect::new(Point2D::new(20, 40), Size2D::new(80, 100));
+        let offsets = SideOffsets2D::new(20, 10, 10, 10);
+        let outer_rect = inner_rect.outer_rect(offsets);
+        assert_eq!(outer_rect.origin.x, 10);
+        assert_eq!(outer_rect.origin.y, 20);
+        assert_eq!(outer_rect.size.width, 100);
+        assert_eq!(outer_rect.size.height, 130);
+        assert_eq!(outer_rect.inner_rect(offsets), inner_rect);
+    }
+
+    #[test]
+    fn test_min_max_x_y() {
+        let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
+        assert!(p.max_y() == 40);
+        assert!(p.min_y() == 0);
+        assert!(p.max_x() == 50);
+        assert!(p.min_x() == 0);
+
+        let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
+        assert!(r.max_y() == 35);
+        assert!(r.min_y() == -5);
+        assert!(r.max_x() == 40);
+        assert!(r.min_x() == -10);
+    }
+
+    #[test]
+    fn test_is_empty() {
+        assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(0u32, 0u32)).is_empty());
+        assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(10u32, 0u32)).is_empty());
+        assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(0u32, 10u32)).is_empty());
+        assert!(!Rect::new(Point2D::new(0u32, 0u32), Size2D::new(1u32, 1u32)).is_empty());
+        assert!(Rect::new(Point2D::new(10u32, 10u32), Size2D::new(0u32, 0u32)).is_empty());
+        assert!(Rect::new(Point2D::new(10u32, 10u32), Size2D::new(10u32, 0u32)).is_empty());
+        assert!(Rect::new(Point2D::new(10u32, 10u32), Size2D::new(0u32, 10u32)).is_empty());
+        assert!(!Rect::new(Point2D::new(10u32, 10u32), Size2D::new(1u32, 1u32)).is_empty());
+    }
+
+    #[test]
+    fn test_round() {
+        let mut x = -2.0;
+        let mut y = -2.0;
+        let mut w = -2.0;
+        let mut h = -2.0;
+        while x < 2.0 {
+            while y < 2.0 {
+                while w < 2.0 {
+                    while h < 2.0 {
+                        let rect = Rect::new(Point2D::new(x, y), Size2D::new(w, h));
+
+                        assert!(rect.contains_rect(&rect.round_in()));
+                        assert!(rect.round_in().inflate(1.0, 1.0).contains_rect(&rect));
+
+                        assert!(rect.round_out().contains_rect(&rect));
+                        assert!(rect.inflate(1.0, 1.0).contains_rect(&rect.round_out()));
+
+                        assert!(rect.inflate(1.0, 1.0).contains_rect(&rect.round()));
+                        assert!(rect.round().inflate(1.0, 1.0).contains_rect(&rect));
+
+                        h += 0.1;
+                    }
+                    w += 0.1;
+                }
+                y += 0.1;
+            }
+            x += 0.1
+        }
+    }
+
+    #[test]
+    fn test_center() {
+        let r: Rect<i32> = rect(-2, 5, 4, 10);
+        assert_eq!(r.center(), point2(0, 10));
+
+        let r: Rect<f32> = rect(1.0, 2.0, 3.0, 4.0);
+        assert_eq!(r.center(), point2(2.5, 4.0));
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/rotation.rs b/rustc_deps/vendor/euclid/src/rotation.rs
new file mode 100644
index 0000000..5405686
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/rotation.rs
@@ -0,0 +1,1057 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use approxeq::ApproxEq;
+use num_traits::{Float, FloatConst, One, Zero};
+use core::fmt;
+use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
+use core::marker::PhantomData;
+use trig::Trig;
+use {TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, Vector3D, point2, point3, vec3};
+use {TypedTransform2D, TypedTransform3D, UnknownUnit};
+
+/// An angle in radians
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct Angle<T> {
+    pub radians: T,
+}
+
+impl<T> Angle<T> {
+    #[inline]
+    pub fn radians(radians: T) -> Self {
+        Angle { radians }
+    }
+
+    #[inline]
+    pub fn get(self) -> T {
+        self.radians
+    }
+}
+
+impl<T> Angle<T>
+where
+    T: Trig,
+{
+    #[inline]
+    pub fn degrees(deg: T) -> Self {
+        Angle {
+            radians: T::degrees_to_radians(deg),
+        }
+    }
+
+    #[inline]
+    pub fn to_degrees(self) -> T {
+        T::radians_to_degrees(self.radians)
+    }
+}
+
+impl<T> Angle<T>
+where
+    T: Rem<Output = T> + Sub<Output = T> + Add<Output = T> + Zero + FloatConst + PartialOrd + Copy,
+{
+    /// Returns this angle in the [0..2*PI[ range.
+    pub fn positive(&self) -> Self {
+        let two_pi = T::PI() + T::PI();
+        let mut a = self.radians % two_pi;
+        if a < T::zero() {
+            a = a + two_pi;
+        }
+        Angle::radians(a)
+    }
+
+    /// Returns this angle in the ]-PI..PI] range.
+    pub fn signed(&self) -> Self {
+        Angle::pi() - (Angle::pi() - *self).positive()
+    }
+}
+
+impl<T> Angle<T>
+where
+    T: Float,
+{
+    /// Returns (sin(self), cos(self)).
+    pub fn sin_cos(self) -> (T, T) {
+        self.radians.sin_cos()
+    }
+}
+
+impl<T> Angle<T>
+where
+    T: Zero,
+{
+    pub fn zero() -> Self {
+        Angle::radians(T::zero())
+    }
+}
+
+impl<T> Angle<T>
+where
+    T: FloatConst + Add<Output = T>,
+{
+    pub fn pi() -> Self {
+        Angle::radians(T::PI())
+    }
+
+    pub fn two_pi() -> Self {
+        Angle::radians(T::PI() + T::PI())
+    }
+
+    pub fn frac_pi_2() -> Self {
+        Angle::radians(T::FRAC_PI_2())
+    }
+
+    pub fn frac_pi_3() -> Self {
+        Angle::radians(T::FRAC_PI_3())
+    }
+
+    pub fn frac_pi_4() -> Self {
+        Angle::radians(T::FRAC_PI_4())
+    }
+}
+
+impl<T: Clone + Add<T, Output = T>> Add for Angle<T> {
+    type Output = Angle<T>;
+    fn add(self, other: Angle<T>) -> Angle<T> {
+        Angle::radians(self.radians + other.radians)
+    }
+}
+
+impl<T: Clone + AddAssign<T>> AddAssign for Angle<T> {
+    fn add_assign(&mut self, other: Angle<T>) {
+        self.radians += other.radians;
+    }
+}
+
+impl<T: Clone + Sub<T, Output = T>> Sub<Angle<T>> for Angle<T> {
+    type Output = Angle<T>;
+    fn sub(self, other: Angle<T>) -> <Self as Sub>::Output {
+        Angle::radians(self.radians - other.radians)
+    }
+}
+
+impl<T: Clone + SubAssign<T>> SubAssign for Angle<T> {
+    fn sub_assign(&mut self, other: Angle<T>) {
+        self.radians -= other.radians;
+    }
+}
+
+impl<T: Clone + Div<T, Output = T>> Div<Angle<T>> for Angle<T> {
+    type Output = T;
+    #[inline]
+    fn div(self, other: Angle<T>) -> T {
+        self.radians / other.radians
+    }
+}
+
+impl<T: Clone + Div<T, Output = T>> Div<T> for Angle<T> {
+    type Output = Angle<T>;
+    #[inline]
+    fn div(self, factor: T) -> Angle<T> {
+        Angle::radians(self.radians / factor)
+    }
+}
+
+impl<T: Clone + DivAssign<T>> DivAssign<T> for Angle<T> {
+    fn div_assign(&mut self, factor: T) {
+        self.radians /= factor;
+    }
+}
+
+impl<T: Clone + Mul<T, Output = T>> Mul<T> for Angle<T> {
+    type Output = Angle<T>;
+    #[inline]
+    fn mul(self, factor: T) -> Angle<T> {
+        Angle::radians(self.radians * factor)
+    }
+}
+
+impl<T: Clone + MulAssign<T>> MulAssign<T> for Angle<T> {
+    fn mul_assign(&mut self, factor: T) {
+        self.radians *= factor;
+    }
+}
+
+impl<T: Neg<Output = T>> Neg for Angle<T> {
+    type Output = Self;
+    fn neg(self) -> Self {
+        Angle::radians(-self.radians)
+    }
+}
+
+define_matrix! {
+    /// A transform that can represent rotations in 2d, represented as an angle in radians.
+    pub struct TypedRotation2D<T, Src, Dst> {
+        pub angle : T,
+    }
+}
+
+/// The default 2d rotation type with no units.
+pub type Rotation2D<T> = TypedRotation2D<T, UnknownUnit, UnknownUnit>;
+
+impl<T, Src, Dst> TypedRotation2D<T, Src, Dst> {
+    #[inline]
+    /// Creates a rotation from an angle in radians.
+    pub fn new(angle: Angle<T>) -> Self {
+        TypedRotation2D {
+            angle: angle.radians,
+            _unit: PhantomData,
+        }
+    }
+
+    pub fn radians(angle: T) -> Self {
+        Self::new(Angle::radians(angle))
+    }
+
+    /// Creates the identity rotation.
+    #[inline]
+    pub fn identity() -> Self
+    where
+        T: Zero,
+    {
+        Self::radians(T::zero())
+    }
+}
+
+impl<T, Src, Dst> TypedRotation2D<T, Src, Dst>
+where
+    T: Clone,
+{
+    /// Returns self.angle as a strongly typed `Angle<T>`.
+    pub fn get_angle(&self) -> Angle<T> {
+        Angle::radians(self.angle.clone())
+    }
+}
+
+impl<T, Src, Dst> TypedRotation2D<T, Src, Dst>
+where
+    T: Copy
+        + Clone
+        + Add<T, Output = T>
+        + Sub<T, Output = T>
+        + Mul<T, Output = T>
+        + Div<T, Output = T>
+        + Neg<Output = T>
+        + PartialOrd
+        + Float
+        + One
+        + Zero,
+{
+    /// Creates a 3d rotation (around the z axis) from this 2d rotation.
+    #[inline]
+    pub fn to_3d(&self) -> TypedRotation3D<T, Src, Dst> {
+        TypedRotation3D::around_z(self.get_angle())
+    }
+
+    /// Returns the inverse of this rotation.
+    #[inline]
+    pub fn inverse(&self) -> TypedRotation2D<T, Dst, Src> {
+        TypedRotation2D::radians(-self.angle)
+    }
+
+    /// Returns a rotation representing the other rotation followed by this rotation.
+    #[inline]
+    pub fn pre_rotate<NewSrc>(
+        &self,
+        other: &TypedRotation2D<T, NewSrc, Src>,
+    ) -> TypedRotation2D<T, NewSrc, Dst> {
+        TypedRotation2D::radians(self.angle + other.angle)
+    }
+
+    /// Returns a rotation representing this rotation followed by the other rotation.
+    #[inline]
+    pub fn post_rotate<NewDst>(
+        &self,
+        other: &TypedRotation2D<T, Dst, NewDst>,
+    ) -> TypedRotation2D<T, Src, NewDst> {
+        other.pre_rotate(self)
+    }
+
+    /// Returns the given 2d point transformed by this rotation.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
+        let (sin, cos) = Float::sin_cos(self.angle);
+        point2(point.x * cos - point.y * sin, point.y * cos + point.x * sin)
+    }
+
+    /// Returns the given 2d vector transformed by this rotation.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_vector(&self, vector: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
+        self.transform_point(&vector.to_point()).to_vector()
+    }
+}
+
+impl<T, Src, Dst> TypedRotation2D<T, Src, Dst>
+where
+    T: Copy
+        + Clone
+        + Add<T, Output = T>
+        + Mul<T, Output = T>
+        + Div<T, Output = T>
+        + Sub<T, Output = T>
+        + Trig
+        + PartialOrd
+        + One
+        + Zero,
+{
+    /// Returns the matrix representation of this rotation.
+    #[inline]
+    pub fn to_transform(&self) -> TypedTransform2D<T, Src, Dst> {
+        TypedTransform2D::create_rotation(self.get_angle())
+    }
+}
+
+define_matrix! {
+    /// A transform that can represent rotations in 3d, represented as a quaternion.
+    ///
+    /// Most methods expect the quaternion to be normalized.
+    /// When in doubt, use `unit_quaternion` instead of `quaternion` to create
+    /// a rotation as the former will ensure that its result is normalized.
+    ///
+    /// Some people use the `x, y, z, w` (or `w, x, y, z`) notations. The equivalence is
+    /// as follows: `x -> i`, `y -> j`, `z -> k`, `w -> r`.
+    /// The memory layout of this type corresponds to the `x, y, z, w` notation
+    pub struct TypedRotation3D<T, Src, Dst> {
+        // Component multiplied by the imaginary number `i`.
+        pub i: T,
+        // Component multiplied by the imaginary number `j`.
+        pub j: T,
+        // Component multiplied by the imaginary number `k`.
+        pub k: T,
+        // The real part.
+        pub r: T,
+    }
+}
+
+/// The default 3d rotation type with no units.
+pub type Rotation3D<T> = TypedRotation3D<T, UnknownUnit, UnknownUnit>;
+
+impl<T, Src, Dst> TypedRotation3D<T, Src, Dst> {
+    /// Creates a rotation around from a quaternion representation.
+    ///
+    /// The parameters are a, b, c and r compose the quaternion `a*i + b*j + c*k + r`
+    /// where `a`, `b` and `c` describe the vector part and the last parameter `r` is
+    /// the real part.
+    ///
+    /// The resulting quaternion is not necessarily normalized. See `unit_quaternion`.
+    #[inline]
+    pub fn quaternion(a: T, b: T, c: T, r: T) -> Self {
+        TypedRotation3D {
+            i: a,
+            j: b,
+            k: c,
+            r,
+            _unit: PhantomData,
+        }
+    }
+}
+
+impl<T, Src, Dst> TypedRotation3D<T, Src, Dst>
+where
+    T: Copy,
+{
+    /// Returns the vector part (i, j, k) of this quaternion.
+    #[inline]
+    pub fn vector_part(&self) -> Vector3D<T> {
+        vec3(self.i, self.j, self.k)
+    }
+}
+
+impl<T, Src, Dst> TypedRotation3D<T, Src, Dst>
+where
+    T: Float,
+{
+    /// Creates the identity rotation.
+    #[inline]
+    pub fn identity() -> Self {
+        let zero = T::zero();
+        let one = T::one();
+        Self::quaternion(zero, zero, zero, one)
+    }
+
+    /// Creates a rotation around from a quaternion representation and normalizes it.
+    ///
+    /// The parameters are a, b, c and r compose the quaternion `a*i + b*j + c*k + r`
+    /// before normalization, where `a`, `b` and `c` describe the vector part and the
+    /// last parameter `r` is the real part.
+    #[inline]
+    pub fn unit_quaternion(i: T, j: T, k: T, r: T) -> Self {
+        Self::quaternion(i, j, k, r).normalize()
+    }
+
+    /// Creates a rotation around a given axis.
+    pub fn around_axis(axis: TypedVector3D<T, Src>, angle: Angle<T>) -> Self {
+        let axis = axis.normalize();
+        let two = T::one() + T::one();
+        let (sin, cos) = Angle::sin_cos(angle / two);
+        Self::quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos)
+    }
+
+    /// Creates a rotation around the x axis.
+    pub fn around_x(angle: Angle<T>) -> Self {
+        let zero = Zero::zero();
+        let two = T::one() + T::one();
+        let (sin, cos) = Angle::sin_cos(angle / two);
+        Self::quaternion(sin, zero, zero, cos)
+    }
+
+    /// Creates a rotation around the y axis.
+    pub fn around_y(angle: Angle<T>) -> Self {
+        let zero = Zero::zero();
+        let two = T::one() + T::one();
+        let (sin, cos) = Angle::sin_cos(angle / two);
+        Self::quaternion(zero, sin, zero, cos)
+    }
+
+    /// Creates a rotation around the z axis.
+    pub fn around_z(angle: Angle<T>) -> Self {
+        let zero = Zero::zero();
+        let two = T::one() + T::one();
+        let (sin, cos) = Angle::sin_cos(angle / two);
+        Self::quaternion(zero, zero, sin, cos)
+    }
+
+    /// Creates a rotation from Euler angles.
+    ///
+    /// The rotations are applied in roll then pitch then yaw order.
+    ///
+    ///  - Roll (also called bank) is a rotation around the x axis.
+    ///  - Pitch (also called bearing) is a rotation around the y axis.
+    ///  - Yaw (also called heading) is a rotation around the z axis.
+    pub fn euler(roll: Angle<T>, pitch: Angle<T>, yaw: Angle<T>) -> Self {
+        let half = T::one() / (T::one() + T::one());
+
+        let (sy, cy) = Float::sin_cos(half * yaw.get());
+        let (sp, cp) = Float::sin_cos(half * pitch.get());
+        let (sr, cr) = Float::sin_cos(half * roll.get());
+
+        Self::quaternion(
+            cy * sr * cp - sy * cr * sp,
+            cy * cr * sp + sy * sr * cp,
+            sy * cr * cp - cy * sr * sp,
+            cy * cr * cp + sy * sr * sp,
+        )
+    }
+
+    /// Returns the inverse of this rotation.
+    #[inline]
+    pub fn inverse(&self) -> TypedRotation3D<T, Dst, Src> {
+        TypedRotation3D::quaternion(-self.i, -self.j, -self.k, self.r)
+    }
+
+    /// Computes the norm of this quaternion
+    #[inline]
+    pub fn norm(&self) -> T {
+        self.square_norm().sqrt()
+    }
+
+    #[inline]
+    pub fn square_norm(&self) -> T {
+        (self.i * self.i + self.j * self.j + self.k * self.k + self.r * self.r)
+    }
+
+    /// Returns a unit quaternion from this one.
+    #[inline]
+    pub fn normalize(&self) -> Self {
+        self.mul(T::one() / self.norm())
+    }
+
+    #[inline]
+    pub fn is_normalized(&self) -> bool
+    where
+        T: ApproxEq<T>,
+    {
+        // TODO: we might need to relax the threshold here, because of floating point imprecision.
+        self.square_norm().approx_eq(&T::one())
+    }
+
+    /// Spherical linear interpolation between this rotation and another rotation.
+    ///
+    /// `t` is expected to be between zero and one.
+    pub fn slerp(&self, other: &Self, t: T) -> Self
+    where
+        T: ApproxEq<T>,
+    {
+        debug_assert!(self.is_normalized());
+        debug_assert!(other.is_normalized());
+
+        let r1 = *self;
+        let mut r2 = *other;
+
+        let mut dot = r1.i * r2.i + r1.j * r2.j + r1.k * r2.k + r1.r * r2.r;
+
+        let one = T::one();
+
+        if dot.approx_eq(&T::one()) {
+            // If the inputs are too close, linearly interpolate to avoid precision issues.
+            return r1.lerp(&r2, t);
+        }
+
+        // If the dot product is negative, the quaternions
+        // have opposite handed-ness and slerp won't take
+        // the shorter path. Fix by reversing one quaternion.
+        if dot < T::zero() {
+            r2 = r2.mul(-T::one());
+            dot = -dot;
+        }
+
+        // For robustness, stay within the domain of acos.
+        dot = Float::min(dot, one);
+
+        // Angle between r1 and the result.
+        let theta = Float::acos(dot) * t;
+
+        // r1 and r3 form an orthonormal basis.
+        let r3 = r2.sub(r1.mul(dot)).normalize();
+        let (sin, cos) = Float::sin_cos(theta);
+        r1.mul(cos).add(r3.mul(sin))
+    }
+
+    /// Basic Linear interpolation between this rotation and another rotation.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: &Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        self.mul(one_t).add(other.mul(t)).normalize()
+    }
+
+    /// Returns the given 3d point transformed by this rotation.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    pub fn rotate_point3d(&self, point: &TypedPoint3D<T, Src>) -> TypedPoint3D<T, Dst>
+    where
+        T: ApproxEq<T>,
+    {
+        debug_assert!(self.is_normalized());
+
+        let two = T::one() + T::one();
+        let cross = self.vector_part().cross(point.to_vector().to_untyped()) * two;
+
+        point3(
+            point.x + self.r * cross.x + self.j * cross.z - self.k * cross.y,
+            point.y + self.r * cross.y + self.k * cross.x - self.i * cross.z,
+            point.z + self.r * cross.z + self.i * cross.y - self.j * cross.x,
+        )
+    }
+
+    /// Returns the given 2d point transformed by this rotation then projected on the xy plane.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn rotate_point2d(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst>
+    where
+        T: ApproxEq<T>,
+    {
+        self.rotate_point3d(&point.to_3d()).xy()
+    }
+
+    /// Returns the given 3d vector transformed by this rotation then projected on the xy plane.
+    ///
+    /// The input vector must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn rotate_vector3d(&self, vector: &TypedVector3D<T, Src>) -> TypedVector3D<T, Dst>
+    where
+        T: ApproxEq<T>,
+    {
+        self.rotate_point3d(&vector.to_point()).to_vector()
+    }
+
+    /// Returns the given 2d vector transformed by this rotation then projected on the xy plane.
+    ///
+    /// The input vector must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn rotate_vector2d(&self, vector: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst>
+    where
+        T: ApproxEq<T>,
+    {
+        self.rotate_vector3d(&vector.to_3d()).xy()
+    }
+
+    /// Returns the matrix representation of this rotation.
+    #[inline]
+    pub fn to_transform(&self) -> TypedTransform3D<T, Src, Dst>
+    where
+        T: ApproxEq<T>,
+    {
+        debug_assert!(self.is_normalized());
+
+        let i2 = self.i + self.i;
+        let j2 = self.j + self.j;
+        let k2 = self.k + self.k;
+        let ii = self.i * i2;
+        let ij = self.i * j2;
+        let ik = self.i * k2;
+        let jj = self.j * j2;
+        let jk = self.j * k2;
+        let kk = self.k * k2;
+        let ri = self.r * i2;
+        let rj = self.r * j2;
+        let rk = self.r * k2;
+
+        let one = T::one();
+        let zero = T::zero();
+
+        let m11 = one - (jj + kk);
+        let m12 = ij + rk;
+        let m13 = ik - rj;
+
+        let m21 = ij - rk;
+        let m22 = one - (ii + kk);
+        let m23 = jk + ri;
+
+        let m31 = ik + rj;
+        let m32 = jk - ri;
+        let m33 = one - (ii + jj);
+
+        TypedTransform3D::row_major(
+            m11,
+            m12,
+            m13,
+            zero,
+            m21,
+            m22,
+            m23,
+            zero,
+            m31,
+            m32,
+            m33,
+            zero,
+            zero,
+            zero,
+            zero,
+            one,
+        )
+    }
+
+    /// Returns a rotation representing the other rotation followed by this rotation.
+    pub fn pre_rotate<NewSrc>(
+        &self,
+        other: &TypedRotation3D<T, NewSrc, Src>,
+    ) -> TypedRotation3D<T, NewSrc, Dst>
+    where
+        T: ApproxEq<T>,
+    {
+        debug_assert!(self.is_normalized());
+        TypedRotation3D::quaternion(
+            self.i * other.r + self.r * other.i + self.j * other.k - self.k * other.j,
+            self.j * other.r + self.r * other.j + self.k * other.i - self.i * other.k,
+            self.k * other.r + self.r * other.k + self.i * other.j - self.j * other.i,
+            self.r * other.r - self.i * other.i - self.j * other.j - self.k * other.k,
+        )
+    }
+
+    /// Returns a rotation representing this rotation followed by the other rotation.
+    #[inline]
+    pub fn post_rotate<NewDst>(
+        &self,
+        other: &TypedRotation3D<T, Dst, NewDst>,
+    ) -> TypedRotation3D<T, Src, NewDst>
+    where
+        T: ApproxEq<T>,
+    {
+        other.pre_rotate(self)
+    }
+
+    // add, sub and mul are used internally for intermediate computation but aren't public
+    // because they don't carry real semantic meanings (I think?).
+
+    #[inline]
+    fn add(&self, other: Self) -> Self {
+        Self::quaternion(
+            self.i + other.i,
+            self.j + other.j,
+            self.k + other.k,
+            self.r + other.r,
+        )
+    }
+
+    #[inline]
+    fn sub(&self, other: Self) -> Self {
+        Self::quaternion(
+            self.i - other.i,
+            self.j - other.j,
+            self.k - other.k,
+            self.r - other.r,
+        )
+    }
+
+    #[inline]
+    fn mul(&self, factor: T) -> Self {
+        Self::quaternion(
+            self.i * factor,
+            self.j * factor,
+            self.k * factor,
+            self.r * factor,
+        )
+    }
+}
+
+impl<T: fmt::Debug, Src, Dst> fmt::Debug for TypedRotation3D<T, Src, Dst> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "Quat({:?}*i + {:?}*j + {:?}*k + {:?})",
+            self.i, self.j, self.k, self.r
+        )
+    }
+}
+
+impl<T: fmt::Display, Src, Dst> fmt::Display for TypedRotation3D<T, Src, Dst> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "Quat({}*i + {}*j + {}*k + {})",
+            self.i, self.j, self.k, self.r
+        )
+    }
+}
+
+impl<T, Src, Dst> ApproxEq<T> for TypedRotation3D<T, Src, Dst>
+where
+    T: Copy + Neg<Output = T> + ApproxEq<T>,
+{
+    fn approx_epsilon() -> T {
+        T::approx_epsilon()
+    }
+
+    fn approx_eq(&self, other: &Self) -> bool {
+        self.approx_eq_eps(other, &Self::approx_epsilon())
+    }
+
+    fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool {
+        (self.i.approx_eq_eps(&other.i, eps) && self.j.approx_eq_eps(&other.j, eps)
+            && self.k.approx_eq_eps(&other.k, eps) && self.r.approx_eq_eps(&other.r, eps))
+            || (self.i.approx_eq_eps(&-other.i, eps) && self.j.approx_eq_eps(&-other.j, eps)
+                && self.k.approx_eq_eps(&-other.k, eps)
+                && self.r.approx_eq_eps(&-other.r, eps))
+    }
+}
+
+#[test]
+fn simple_rotation_2d() {
+    use core::f32::consts::{FRAC_PI_2, PI};
+    let ri = Rotation2D::identity();
+    let r90 = Rotation2D::radians(FRAC_PI_2);
+    let rm90 = Rotation2D::radians(-FRAC_PI_2);
+    let r180 = Rotation2D::radians(PI);
+
+    assert!(
+        ri.transform_point(&point2(1.0, 2.0))
+            .approx_eq(&point2(1.0, 2.0))
+    );
+    assert!(
+        r90.transform_point(&point2(1.0, 2.0))
+            .approx_eq(&point2(-2.0, 1.0))
+    );
+    assert!(
+        rm90.transform_point(&point2(1.0, 2.0))
+            .approx_eq(&point2(2.0, -1.0))
+    );
+    assert!(
+        r180.transform_point(&point2(1.0, 2.0))
+            .approx_eq(&point2(-1.0, -2.0))
+    );
+
+    assert!(
+        r90.inverse()
+            .inverse()
+            .transform_point(&point2(1.0, 2.0))
+            .approx_eq(&r90.transform_point(&point2(1.0, 2.0)))
+    );
+}
+
+#[test]
+fn simple_rotation_3d_in_2d() {
+    use core::f32::consts::{FRAC_PI_2, PI};
+    let ri = Rotation3D::identity();
+    let r90 = Rotation3D::around_z(Angle::radians(FRAC_PI_2));
+    let rm90 = Rotation3D::around_z(Angle::radians(-FRAC_PI_2));
+    let r180 = Rotation3D::around_z(Angle::radians(PI));
+
+    assert!(
+        ri.rotate_point2d(&point2(1.0, 2.0))
+            .approx_eq(&point2(1.0, 2.0))
+    );
+    assert!(
+        r90.rotate_point2d(&point2(1.0, 2.0))
+            .approx_eq(&point2(-2.0, 1.0))
+    );
+    assert!(
+        rm90.rotate_point2d(&point2(1.0, 2.0))
+            .approx_eq(&point2(2.0, -1.0))
+    );
+    assert!(
+        r180.rotate_point2d(&point2(1.0, 2.0))
+            .approx_eq(&point2(-1.0, -2.0))
+    );
+
+    assert!(
+        r90.inverse()
+            .inverse()
+            .rotate_point2d(&point2(1.0, 2.0))
+            .approx_eq(&r90.rotate_point2d(&point2(1.0, 2.0)))
+    );
+}
+
+#[test]
+fn pre_post() {
+    use core::f32::consts::FRAC_PI_2;
+    let r1 = Rotation3D::around_x(Angle::radians(FRAC_PI_2));
+    let r2 = Rotation3D::around_y(Angle::radians(FRAC_PI_2));
+    let r3 = Rotation3D::around_z(Angle::radians(FRAC_PI_2));
+
+    let t1 = r1.to_transform();
+    let t2 = r2.to_transform();
+    let t3 = r3.to_transform();
+
+    let p = point3(1.0, 2.0, 3.0);
+
+    // Check that the order of transformations is correct (corresponds to what
+    // we do in Transform3D).
+    let p1 = r1.post_rotate(&r2).post_rotate(&r3).rotate_point3d(&p);
+    let p2 = t1.post_mul(&t2).post_mul(&t3).transform_point3d(&p);
+
+    assert!(p1.approx_eq(&p2.unwrap()));
+
+    // Check that changing the order indeed matters.
+    let p3 = t3.post_mul(&t1).post_mul(&t2).transform_point3d(&p);
+    assert!(!p1.approx_eq(&p3.unwrap()));
+}
+
+#[test]
+fn to_transform3d() {
+    use core::f32::consts::{FRAC_PI_2, PI};
+    let rotations = [
+        Rotation3D::identity(),
+        Rotation3D::around_x(Angle::radians(FRAC_PI_2)),
+        Rotation3D::around_x(Angle::radians(-FRAC_PI_2)),
+        Rotation3D::around_x(Angle::radians(PI)),
+        Rotation3D::around_y(Angle::radians(FRAC_PI_2)),
+        Rotation3D::around_y(Angle::radians(-FRAC_PI_2)),
+        Rotation3D::around_y(Angle::radians(PI)),
+        Rotation3D::around_z(Angle::radians(FRAC_PI_2)),
+        Rotation3D::around_z(Angle::radians(-FRAC_PI_2)),
+        Rotation3D::around_z(Angle::radians(PI)),
+    ];
+
+    let points = [
+        point3(0.0, 0.0, 0.0),
+        point3(1.0, 2.0, 3.0),
+        point3(-5.0, 3.0, -1.0),
+        point3(-0.5, -1.0, 1.5),
+    ];
+
+    for rotation in &rotations {
+        for point in &points {
+            let p1 = rotation.rotate_point3d(point);
+            let p2 = rotation.to_transform().transform_point3d(point);
+            assert!(p1.approx_eq(&p2.unwrap()));
+        }
+    }
+}
+
+#[test]
+fn slerp() {
+    let q1 = Rotation3D::quaternion(1.0, 0.0, 0.0, 0.0);
+    let q2 = Rotation3D::quaternion(0.0, 1.0, 0.0, 0.0);
+    let q3 = Rotation3D::quaternion(0.0, 0.0, -1.0, 0.0);
+
+    // The values below can be obtained with a python program:
+    // import numpy
+    // import quaternion
+    // q1 = numpy.quaternion(1, 0, 0, 0)
+    // q2 = numpy.quaternion(0, 1, 0, 0)
+    // quaternion.slerp_evaluate(q1, q2, 0.2)
+
+    assert!(q1.slerp(&q2, 0.0).approx_eq(&q1));
+    assert!(q1.slerp(&q2, 0.2).approx_eq(&Rotation3D::quaternion(
+        0.951056516295154,
+        0.309016994374947,
+        0.0,
+        0.0
+    )));
+    assert!(q1.slerp(&q2, 0.4).approx_eq(&Rotation3D::quaternion(
+        0.809016994374947,
+        0.587785252292473,
+        0.0,
+        0.0
+    )));
+    assert!(q1.slerp(&q2, 0.6).approx_eq(&Rotation3D::quaternion(
+        0.587785252292473,
+        0.809016994374947,
+        0.0,
+        0.0
+    )));
+    assert!(q1.slerp(&q2, 0.8).approx_eq(&Rotation3D::quaternion(
+        0.309016994374947,
+        0.951056516295154,
+        0.0,
+        0.0
+    )));
+    assert!(q1.slerp(&q2, 1.0).approx_eq(&q2));
+
+    assert!(q1.slerp(&q3, 0.0).approx_eq(&q1));
+    assert!(q1.slerp(&q3, 0.2).approx_eq(&Rotation3D::quaternion(
+        0.951056516295154,
+        0.0,
+        -0.309016994374947,
+        0.0
+    )));
+    assert!(q1.slerp(&q3, 0.4).approx_eq(&Rotation3D::quaternion(
+        0.809016994374947,
+        0.0,
+        -0.587785252292473,
+        0.0
+    )));
+    assert!(q1.slerp(&q3, 0.6).approx_eq(&Rotation3D::quaternion(
+        0.587785252292473,
+        0.0,
+        -0.809016994374947,
+        0.0
+    )));
+    assert!(q1.slerp(&q3, 0.8).approx_eq(&Rotation3D::quaternion(
+        0.309016994374947,
+        0.0,
+        -0.951056516295154,
+        0.0
+    )));
+    assert!(q1.slerp(&q3, 1.0).approx_eq(&q3));
+}
+
+#[test]
+fn around_axis() {
+    use core::f32::consts::{FRAC_PI_2, PI};
+
+    // Two sort of trivial cases:
+    let r1 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(PI));
+    let r2 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(FRAC_PI_2));
+    assert!(
+        r1.rotate_point3d(&point3(1.0, 2.0, 0.0))
+            .approx_eq(&point3(2.0, 1.0, 0.0))
+    );
+    assert!(
+        r2.rotate_point3d(&point3(1.0, 0.0, 0.0))
+            .approx_eq(&point3(0.5, 0.5, -0.5.sqrt()))
+    );
+
+    // A more arbitrary test (made up with numpy):
+    let r3 = Rotation3D::around_axis(vec3(0.5, 1.0, 2.0), Angle::radians(2.291288));
+    assert!(r3.rotate_point3d(&point3(1.0, 0.0, 0.0)).approx_eq(&point3(
+        -0.58071821,
+        0.81401868,
+        -0.01182979
+    )));
+}
+
+#[test]
+fn from_euler() {
+    use core::f32::consts::FRAC_PI_2;
+
+    // First test simple separate yaw pitch and roll rotations, because it is easy to come
+    // up with the corresponding quaternion.
+    // Since several quaternions can represent the same transformation we compare the result
+    // of transforming a point rather than the values of each quaternions.
+    let p = point3(1.0, 2.0, 3.0);
+
+    let angle = Angle::radians(FRAC_PI_2);
+    let zero = Angle::radians(0.0);
+
+    // roll
+    let roll_re = Rotation3D::euler(angle, zero, zero);
+    let roll_rq = Rotation3D::around_x(angle);
+    let roll_pe = roll_re.rotate_point3d(&p);
+    let roll_pq = roll_rq.rotate_point3d(&p);
+
+    // pitch
+    let pitch_re = Rotation3D::euler(zero, angle, zero);
+    let pitch_rq = Rotation3D::around_y(angle);
+    let pitch_pe = pitch_re.rotate_point3d(&p);
+    let pitch_pq = pitch_rq.rotate_point3d(&p);
+
+    // yaw
+    let yaw_re = Rotation3D::euler(zero, zero, angle);
+    let yaw_rq = Rotation3D::around_z(angle);
+    let yaw_pe = yaw_re.rotate_point3d(&p);
+    let yaw_pq = yaw_rq.rotate_point3d(&p);
+
+    assert!(roll_pe.approx_eq(&roll_pq));
+    assert!(pitch_pe.approx_eq(&pitch_pq));
+    assert!(yaw_pe.approx_eq(&yaw_pq));
+
+    // Now check that the yaw pitch and roll transformations when combined are applied in
+    // the proper order: roll -> pitch -> yaw.
+    let ypr_e = Rotation3D::euler(angle, angle, angle);
+    let ypr_q = roll_rq.post_rotate(&pitch_rq).post_rotate(&yaw_rq);
+    let ypr_pe = ypr_e.rotate_point3d(&p);
+    let ypr_pq = ypr_q.rotate_point3d(&p);
+
+    assert!(ypr_pe.approx_eq(&ypr_pq));
+}
+
+#[test]
+fn wrap_angles() {
+    use core::f32::consts::{FRAC_PI_2, PI};
+    assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
+    assert!(
+        Angle::radians(FRAC_PI_2)
+            .positive()
+            .radians
+            .approx_eq(&FRAC_PI_2)
+    );
+    assert!(
+        Angle::radians(-FRAC_PI_2)
+            .positive()
+            .radians
+            .approx_eq(&(3.0 * FRAC_PI_2))
+    );
+    assert!(
+        Angle::radians(3.0 * FRAC_PI_2)
+            .positive()
+            .radians
+            .approx_eq(&(3.0 * FRAC_PI_2))
+    );
+    assert!(
+        Angle::radians(5.0 * FRAC_PI_2)
+            .positive()
+            .radians
+            .approx_eq(&FRAC_PI_2)
+    );
+    assert!(Angle::radians(2.0 * PI).positive().radians.approx_eq(&0.0));
+    assert!(Angle::radians(-2.0 * PI).positive().radians.approx_eq(&0.0));
+    assert!(Angle::radians(PI).positive().radians.approx_eq(&PI));
+    assert!(Angle::radians(-PI).positive().radians.approx_eq(&PI));
+
+    assert!(
+        Angle::radians(FRAC_PI_2)
+            .signed()
+            .radians
+            .approx_eq(&FRAC_PI_2)
+    );
+    assert!(
+        Angle::radians(3.0 * FRAC_PI_2)
+            .signed()
+            .radians
+            .approx_eq(&-FRAC_PI_2)
+    );
+    assert!(
+        Angle::radians(5.0 * FRAC_PI_2)
+            .signed()
+            .radians
+            .approx_eq(&FRAC_PI_2)
+    );
+    assert!(Angle::radians(2.0 * PI).signed().radians.approx_eq(&0.0));
+    assert!(Angle::radians(-2.0 * PI).signed().radians.approx_eq(&0.0));
+    assert!(Angle::radians(-PI).signed().radians.approx_eq(&PI));
+    assert!(Angle::radians(PI).signed().radians.approx_eq(&PI));
+}
diff --git a/rustc_deps/vendor/euclid/src/scale.rs b/rustc_deps/vendor/euclid/src/scale.rs
new file mode 100644
index 0000000..4772fa6
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/scale.rs
@@ -0,0 +1,235 @@
+// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//! A type-checked scaling factor between units.
+
+use num::One;
+
+use num_traits::NumCast;
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use core::fmt;
+use core::ops::{Add, Div, Mul, Neg, Sub};
+use core::marker::PhantomData;
+use {TypedPoint2D, TypedRect, TypedSize2D, TypedVector2D};
+
+/// A scaling factor between two different units of measurement.
+///
+/// This is effectively a type-safe float, intended to be used in combination with other types like
+/// `length::Length` to enforce conversion between systems of measurement at compile time.
+///
+/// `Src` and `Dst` represent the units before and after multiplying a value by a `TypedScale`. They
+/// may be types without values, such as empty enums.  For example:
+///
+/// ```rust
+/// use euclid::TypedScale;
+/// use euclid::Length;
+/// enum Mm {};
+/// enum Inch {};
+///
+/// let mm_per_inch: TypedScale<f32, Inch, Mm> = TypedScale::new(25.4);
+///
+/// let one_foot: Length<f32, Inch> = Length::new(12.0);
+/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
+/// ```
+#[repr(C)]
+pub struct TypedScale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);
+
+#[cfg(feature = "serde")]
+impl<'de, T, Src, Dst> Deserialize<'de> for TypedScale<T, Src, Dst>
+where
+    T: Deserialize<'de>,
+{
+    fn deserialize<D>(deserializer: D) -> Result<TypedScale<T, Src, Dst>, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        Ok(TypedScale(
+            try!(Deserialize::deserialize(deserializer)),
+            PhantomData,
+        ))
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<T, Src, Dst> Serialize for TypedScale<T, Src, Dst>
+where
+    T: Serialize,
+{
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.0.serialize(serializer)
+    }
+}
+
+impl<T, Src, Dst> TypedScale<T, Src, Dst> {
+    pub fn new(x: T) -> Self {
+        TypedScale(x, PhantomData)
+    }
+}
+
+impl<T: Clone, Src, Dst> TypedScale<T, Src, Dst> {
+    pub fn get(&self) -> T {
+        self.0.clone()
+    }
+}
+
+impl<Src, Dst> TypedScale<f32, Src, Dst> {
+    /// Identity scaling, could be used to safely transit from one space to another.
+    pub const ONE: Self = TypedScale(1.0, PhantomData);
+}
+
+impl<T: Clone + One + Div<T, Output = T>, Src, Dst> TypedScale<T, Src, Dst> {
+    /// The inverse TypedScale (1.0 / self).
+    pub fn inv(&self) -> TypedScale<T, Dst, Src> {
+        let one: T = One::one();
+        TypedScale::new(one / self.get())
+    }
+}
+
+// scale0 * scale1
+impl<T: Clone + Mul<T, Output = T>, A, B, C> Mul<TypedScale<T, B, C>> for TypedScale<T, A, B> {
+    type Output = TypedScale<T, A, C>;
+    #[inline]
+    fn mul(self, other: TypedScale<T, B, C>) -> TypedScale<T, A, C> {
+        TypedScale::new(self.get() * other.get())
+    }
+}
+
+// scale0 + scale1
+impl<T: Clone + Add<T, Output = T>, Src, Dst> Add for TypedScale<T, Src, Dst> {
+    type Output = TypedScale<T, Src, Dst>;
+    #[inline]
+    fn add(self, other: TypedScale<T, Src, Dst>) -> TypedScale<T, Src, Dst> {
+        TypedScale::new(self.get() + other.get())
+    }
+}
+
+// scale0 - scale1
+impl<T: Clone + Sub<T, Output = T>, Src, Dst> Sub for TypedScale<T, Src, Dst> {
+    type Output = TypedScale<T, Src, Dst>;
+    #[inline]
+    fn sub(self, other: TypedScale<T, Src, Dst>) -> TypedScale<T, Src, Dst> {
+        TypedScale::new(self.get() - other.get())
+    }
+}
+
+impl<T: NumCast + Clone, Src, Dst0> TypedScale<T, Src, Dst0> {
+    /// Cast from one numeric representation to another, preserving the units.
+    pub fn cast<T1: NumCast + Clone>(&self) -> TypedScale<T1, Src, Dst0> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<TypedScale<T1, Src, Dst0>> {
+        NumCast::from(self.get()).map(TypedScale::new)
+    }
+}
+
+impl<T, Src, Dst> TypedScale<T, Src, Dst>
+where
+    T: Copy + Clone + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
+{
+    /// Returns the given point transformed by this scale.
+    #[inline]
+    pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
+        TypedPoint2D::new(point.x * self.get(), point.y * self.get())
+    }
+
+    /// Returns the given vector transformed by this scale.
+    #[inline]
+    pub fn transform_vector(&self, vec: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
+        TypedVector2D::new(vec.x * self.get(), vec.y * self.get())
+    }
+
+    /// Returns the given vector transformed by this scale.
+    #[inline]
+    pub fn transform_size(&self, size: &TypedSize2D<T, Src>) -> TypedSize2D<T, Dst> {
+        TypedSize2D::new(size.width * self.get(), size.height * self.get())
+    }
+
+    /// Returns the given rect transformed by this scale.
+    #[inline]
+    pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
+        TypedRect::new(
+            self.transform_point(&rect.origin),
+            self.transform_size(&rect.size),
+        )
+    }
+
+    /// Returns the inverse of this scale.
+    #[inline]
+    pub fn inverse(&self) -> TypedScale<T, Dst, Src> {
+        TypedScale::new(-self.get())
+    }
+
+    /// Returns true if this scale has no effect.
+    #[inline]
+    pub fn is_identity(&self) -> bool {
+        self.get() == T::one()
+    }
+}
+
+// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
+// https://github.com/mozilla/rust/issues/7671
+
+impl<T: PartialEq, Src, Dst> PartialEq for TypedScale<T, Src, Dst> {
+    fn eq(&self, other: &TypedScale<T, Src, Dst>) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl<T: Clone, Src, Dst> Clone for TypedScale<T, Src, Dst> {
+    fn clone(&self) -> TypedScale<T, Src, Dst> {
+        TypedScale::new(self.get())
+    }
+}
+
+impl<T: Copy, Src, Dst> Copy for TypedScale<T, Src, Dst> {}
+
+impl<T: fmt::Debug, Src, Dst> fmt::Debug for TypedScale<T, Src, Dst> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl<T: fmt::Display, Src, Dst> fmt::Display for TypedScale<T, Src, Dst> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::TypedScale;
+
+    enum Inch {}
+    enum Cm {}
+    enum Mm {}
+
+    #[test]
+    fn test_scale() {
+        let mm_per_inch: TypedScale<f32, Inch, Mm> = TypedScale::new(25.4);
+        let cm_per_mm: TypedScale<f32, Mm, Cm> = TypedScale::new(0.1);
+
+        let mm_per_cm: TypedScale<f32, Cm, Mm> = cm_per_mm.inv();
+        assert_eq!(mm_per_cm.get(), 10.0);
+
+        let cm_per_inch: TypedScale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
+        assert_eq!(cm_per_inch, TypedScale::new(2.54));
+
+        let a: TypedScale<isize, Inch, Inch> = TypedScale::new(2);
+        let b: TypedScale<isize, Inch, Inch> = TypedScale::new(3);
+        assert!(a != b);
+        assert_eq!(a, a.clone());
+        assert_eq!(a.clone() + b.clone(), TypedScale::new(5));
+        assert_eq!(a - b, TypedScale::new(-1));
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/side_offsets.rs b/rustc_deps/vendor/euclid/src/side_offsets.rs
new file mode 100644
index 0000000..581aa28
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/side_offsets.rs
@@ -0,0 +1,138 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
+//! and margins in CSS.
+
+use super::UnknownUnit;
+use length::Length;
+use num::Zero;
+use core::fmt;
+use core::ops::Add;
+use core::marker::PhantomData;
+
+/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
+/// and margins in CSS, optionally tagged with a unit.
+define_matrix! {
+    pub struct TypedSideOffsets2D<T, U> {
+        pub top: T,
+        pub right: T,
+        pub bottom: T,
+        pub left: T,
+    }
+}
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedSideOffsets2D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "({:?},{:?},{:?},{:?})",
+            self.top, self.right, self.bottom, self.left
+        )
+    }
+}
+
+/// The default side offset type with no unit.
+pub type SideOffsets2D<T> = TypedSideOffsets2D<T, UnknownUnit>;
+
+impl<T: Copy, U> TypedSideOffsets2D<T, U> {
+    /// Constructor taking a scalar for each side.
+    pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
+        TypedSideOffsets2D {
+            top,
+            right,
+            bottom,
+            left,
+            _unit: PhantomData,
+        }
+    }
+
+    /// Constructor taking a typed Length for each side.
+    pub fn from_lengths(
+        top: Length<T, U>,
+        right: Length<T, U>,
+        bottom: Length<T, U>,
+        left: Length<T, U>,
+    ) -> Self {
+        TypedSideOffsets2D::new(top.0, right.0, bottom.0, left.0)
+    }
+
+    /// Access self.top as a typed Length instead of a scalar value.
+    pub fn top_typed(&self) -> Length<T, U> {
+        Length::new(self.top)
+    }
+
+    /// Access self.right as a typed Length instead of a scalar value.
+    pub fn right_typed(&self) -> Length<T, U> {
+        Length::new(self.right)
+    }
+
+    /// Access self.bottom as a typed Length instead of a scalar value.
+    pub fn bottom_typed(&self) -> Length<T, U> {
+        Length::new(self.bottom)
+    }
+
+    /// Access self.left as a typed Length instead of a scalar value.
+    pub fn left_typed(&self) -> Length<T, U> {
+        Length::new(self.left)
+    }
+
+    /// Constructor setting the same value to all sides, taking a scalar value directly.
+    pub fn new_all_same(all: T) -> Self {
+        TypedSideOffsets2D::new(all, all, all, all)
+    }
+
+    /// Constructor setting the same value to all sides, taking a typed Length.
+    pub fn from_length_all_same(all: Length<T, U>) -> Self {
+        TypedSideOffsets2D::new_all_same(all.0)
+    }
+}
+
+impl<T, U> TypedSideOffsets2D<T, U>
+where
+    T: Add<T, Output = T> + Copy,
+{
+    pub fn horizontal(&self) -> T {
+        self.left + self.right
+    }
+
+    pub fn vertical(&self) -> T {
+        self.top + self.bottom
+    }
+
+    pub fn horizontal_typed(&self) -> Length<T, U> {
+        Length::new(self.horizontal())
+    }
+
+    pub fn vertical_typed(&self) -> Length<T, U> {
+        Length::new(self.vertical())
+    }
+}
+
+impl<T, U> Add for TypedSideOffsets2D<T, U>
+where
+    T: Copy + Add<T, Output = T>,
+{
+    type Output = Self;
+    fn add(self, other: Self) -> Self {
+        TypedSideOffsets2D::new(
+            self.top + other.top,
+            self.right + other.right,
+            self.bottom + other.bottom,
+            self.left + other.left,
+        )
+    }
+}
+
+impl<T: Copy + Zero, U> TypedSideOffsets2D<T, U> {
+    /// Constructor, setting all sides to zero.
+    pub fn zero() -> Self {
+        TypedSideOffsets2D::new(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/size.rs b/rustc_deps/vendor/euclid/src/size.rs
new file mode 100644
index 0000000..068c4bb
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/size.rs
@@ -0,0 +1,441 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::UnknownUnit;
+#[cfg(feature = "mint")]
+use mint;
+use length::Length;
+use scale::TypedScale;
+use vector::{TypedVector2D, vec2, BoolVector2D};
+use num::*;
+
+use num_traits::{Float, NumCast, Signed};
+use core::fmt;
+use core::ops::{Add, Div, Mul, Sub};
+use core::marker::PhantomData;
+
+/// A 2d size tagged with a unit.
+define_matrix! {
+    pub struct TypedSize2D<T, U> {
+        pub width: T,
+        pub height: T,
+    }
+}
+
+/// Default 2d size type with no unit.
+///
+/// `Size2D` provides the same methods as `TypedSize2D`.
+pub type Size2D<T> = TypedSize2D<T, UnknownUnit>;
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedSize2D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}×{:?}", self.width, self.height)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for TypedSize2D<T, U> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "({}x{})", self.width, self.height)
+    }
+}
+
+impl<T, U> TypedSize2D<T, U> {
+    /// Constructor taking scalar values.
+    pub fn new(width: T, height: T) -> Self {
+        TypedSize2D {
+            width,
+            height,
+            _unit: PhantomData,
+        }
+    }
+}
+
+impl<T: Clone, U> TypedSize2D<T, U> {
+    /// Constructor taking scalar strongly typed lengths.
+    pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
+        TypedSize2D::new(width.get(), height.get())
+    }
+}
+
+impl<T: Round, U> TypedSize2D<T, U> {
+    /// Rounds each component to the nearest integer value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    pub fn round(&self) -> Self {
+        TypedSize2D::new(self.width.round(), self.height.round())
+    }
+}
+
+impl<T: Ceil, U> TypedSize2D<T, U> {
+    /// Rounds each component to the smallest integer equal or greater than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    pub fn ceil(&self) -> Self {
+        TypedSize2D::new(self.width.ceil(), self.height.ceil())
+    }
+}
+
+impl<T: Floor, U> TypedSize2D<T, U> {
+    /// Rounds each component to the biggest integer equal or lower than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    pub fn floor(&self) -> Self {
+        TypedSize2D::new(self.width.floor(), self.height.floor())
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> Add for TypedSize2D<T, U> {
+    type Output = Self;
+    fn add(self, other: Self) -> Self {
+        TypedSize2D::new(self.width + other.width, self.height + other.height)
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedSize2D<T, U> {
+    type Output = Self;
+    fn sub(self, other: Self) -> Self {
+        TypedSize2D::new(self.width - other.width, self.height - other.height)
+    }
+}
+
+impl<T: Copy + Clone + Mul<T>, U> TypedSize2D<T, U> {
+    pub fn area(&self) -> T::Output {
+        self.width * self.height
+    }
+}
+
+impl<T, U> TypedSize2D<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this size and another size.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        size2(
+            one_t * self.width + t * other.width,
+            one_t * self.height + t * other.height,
+        )
+    }
+}
+
+impl<T: Zero + PartialOrd, U> TypedSize2D<T, U> {
+    pub fn is_empty_or_negative(&self) -> bool {
+        let zero = T::zero();
+        self.width <= zero || self.height <= zero
+    }
+}
+
+impl<T: Zero, U> TypedSize2D<T, U> {
+    pub fn zero() -> Self {
+        TypedSize2D::new(Zero::zero(), Zero::zero())
+    }
+}
+
+impl<T: Zero, U> Zero for TypedSize2D<T, U> {
+    fn zero() -> Self {
+        TypedSize2D::new(Zero::zero(), Zero::zero())
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedSize2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        TypedSize2D::new(self.width * scale, self.height * scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedSize2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        TypedSize2D::new(self.width / scale, self.height / scale)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedSize2D<T, U1> {
+    type Output = TypedSize2D<T, U2>;
+    #[inline]
+    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedSize2D<T, U2> {
+        TypedSize2D::new(self.width * scale.get(), self.height * scale.get())
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedSize2D<T, U2> {
+    type Output = TypedSize2D<T, U1>;
+    #[inline]
+    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedSize2D<T, U1> {
+        TypedSize2D::new(self.width / scale.get(), self.height / scale.get())
+    }
+}
+
+impl<T: Copy, U> TypedSize2D<T, U> {
+    /// Returns self.width as a Length carrying the unit.
+    #[inline]
+    pub fn width_typed(&self) -> Length<T, U> {
+        Length::new(self.width)
+    }
+
+    /// Returns self.height as a Length carrying the unit.
+    #[inline]
+    pub fn height_typed(&self) -> Length<T, U> {
+        Length::new(self.height)
+    }
+
+    #[inline]
+    pub fn to_array(&self) -> [T; 2] {
+        [self.width, self.height]
+    }
+
+    #[inline]
+    pub fn to_vector(&self) -> TypedVector2D<T, U> {
+        vec2(self.width, self.height)
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    pub fn to_untyped(&self) -> Size2D<T> {
+        TypedSize2D::new(self.width, self.height)
+    }
+
+    /// Tag a unitless value with units.
+    pub fn from_untyped(p: &Size2D<T>) -> Self {
+        TypedSize2D::new(p.width, p.height)
+    }
+}
+
+impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
+    /// Cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize2D<NewT, Unit> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize2D<NewT, Unit>> {
+        match (NumCast::from(self.width), NumCast::from(self.height)) {
+            (Some(w), Some(h)) => Some(TypedSize2D::new(w, h)),
+            _ => None,
+        }
+    }
+
+    // Convenience functions for common casts
+
+    /// Cast into an `f32` size.
+    pub fn to_f32(&self) -> TypedSize2D<f32, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `f64` size.
+    pub fn to_f64(&self) -> TypedSize2D<f64, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `uint` size, truncating decimals if any.
+    ///
+    /// When casting from floating point sizes, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    pub fn to_usize(&self) -> TypedSize2D<usize, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `u32` size, truncating decimals if any.
+    ///
+    /// When casting from floating point sizes, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    pub fn to_u32(&self) -> TypedSize2D<u32, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `i32` size, truncating decimals if any.
+    ///
+    /// When casting from floating point sizes, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    pub fn to_i32(&self) -> TypedSize2D<i32, Unit> {
+        self.cast()
+    }
+
+    /// Cast into an `i64` size, truncating decimals if any.
+    ///
+    /// When casting from floating point sizes, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    pub fn to_i64(&self) -> TypedSize2D<i64, Unit> {
+        self.cast()
+    }
+}
+
+impl<T, U> TypedSize2D<T, U>
+where
+    T: Signed,
+{
+    pub fn abs(&self) -> Self {
+        size2(self.width.abs(), self.height.abs())
+    }
+
+    pub fn is_positive(&self) -> bool {
+        self.width.is_positive() && self.height.is_positive()
+    }
+}
+
+impl<T: PartialOrd, U> TypedSize2D<T, U> {
+    pub fn greater_than(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.width > other.width,
+            y: self.height > other.height,
+        }
+    }
+
+    pub fn lower_than(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.width < other.width,
+            y: self.height < other.height,
+        }
+    }
+}
+
+
+impl<T: PartialEq, U> TypedSize2D<T, U> {
+    pub fn equal(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.width == other.width,
+            y: self.height == other.height,
+        }
+    }
+
+    pub fn not_equal(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.width != other.width,
+            y: self.height != other.height,
+        }
+    }
+}
+
+impl<T: Float, U> TypedSize2D<T, U> {
+    #[inline]
+    pub fn min(self, other: Self) -> Self {
+        size2(
+            self.width.min(other.width),
+            self.height.min(other.height),
+        )
+    }
+
+    #[inline]
+    pub fn max(self, other: Self) -> Self {
+        size2(
+            self.width.max(other.width),
+            self.height.max(other.height),
+        )
+    }
+
+    #[inline]
+    pub fn clamp(&self, start: Self, end: Self) -> Self {
+        self.max(start).min(end)
+    }
+}
+
+
+/// Shorthand for `TypedSize2D::new(w, h)`.
+pub fn size2<T, U>(w: T, h: T) -> TypedSize2D<T, U> {
+    TypedSize2D::new(w, h)
+}
+
+#[cfg(feature = "mint")]
+impl<T, U> From<mint::Vector2<T>> for TypedSize2D<T, U> {
+    fn from(v: mint::Vector2<T>) -> Self {
+        TypedSize2D {
+            width: v.x,
+            height: v.y,
+            _unit: PhantomData,
+        }
+    }
+}
+#[cfg(feature = "mint")]
+impl<T, U> Into<mint::Vector2<T>> for TypedSize2D<T, U> {
+    fn into(self) -> mint::Vector2<T> {
+        mint::Vector2 {
+            x: self.width,
+            y: self.height,
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod size2d {
+    use super::Size2D;
+    #[cfg(feature = "mint")]
+    use mint;
+
+    #[test]
+    pub fn test_add() {
+        let p1 = Size2D::new(1.0, 2.0);
+        let p2 = Size2D::new(3.0, 4.0);
+        assert_eq!(p1 + p2, Size2D::new(4.0, 6.0));
+
+        let p1 = Size2D::new(1.0, 2.0);
+        let p2 = Size2D::new(0.0, 0.0);
+        assert_eq!(p1 + p2, Size2D::new(1.0, 2.0));
+
+        let p1 = Size2D::new(1.0, 2.0);
+        let p2 = Size2D::new(-3.0, -4.0);
+        assert_eq!(p1 + p2, Size2D::new(-2.0, -2.0));
+
+        let p1 = Size2D::new(0.0, 0.0);
+        let p2 = Size2D::new(0.0, 0.0);
+        assert_eq!(p1 + p2, Size2D::new(0.0, 0.0));
+    }
+
+    #[test]
+    pub fn test_sub() {
+        let p1 = Size2D::new(1.0, 2.0);
+        let p2 = Size2D::new(3.0, 4.0);
+        assert_eq!(p1 - p2, Size2D::new(-2.0, -2.0));
+
+        let p1 = Size2D::new(1.0, 2.0);
+        let p2 = Size2D::new(0.0, 0.0);
+        assert_eq!(p1 - p2, Size2D::new(1.0, 2.0));
+
+        let p1 = Size2D::new(1.0, 2.0);
+        let p2 = Size2D::new(-3.0, -4.0);
+        assert_eq!(p1 - p2, Size2D::new(4.0, 6.0));
+
+        let p1 = Size2D::new(0.0, 0.0);
+        let p2 = Size2D::new(0.0, 0.0);
+        assert_eq!(p1 - p2, Size2D::new(0.0, 0.0));
+    }
+
+    #[test]
+    pub fn test_area() {
+        let p = Size2D::new(1.5, 2.0);
+        assert_eq!(p.area(), 3.0);
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let s1 = Size2D::new(1.0, 2.0);
+        let sm: mint::Vector2<_> = s1.into();
+        let s2 = Size2D::from(sm);
+
+        assert_eq!(s1, s2);
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/transform2d.rs b/rustc_deps/vendor/euclid/src/transform2d.rs
new file mode 100644
index 0000000..9ff19bd
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/transform2d.rs
@@ -0,0 +1,579 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "cargo-clippy", allow(just_underscores_and_digits))]
+
+use super::{UnknownUnit, Angle};
+#[cfg(feature = "mint")]
+use mint;
+use num::{One, Zero};
+use point::TypedPoint2D;
+use vector::{TypedVector2D, vec2};
+use rect::TypedRect;
+use transform3d::TypedTransform3D;
+use core::ops::{Add, Mul, Div, Sub, Neg};
+use core::marker::PhantomData;
+use approxeq::ApproxEq;
+use trig::Trig;
+use core::fmt;
+use num_traits::NumCast;
+
+define_matrix! {
+    /// A 2d transform stored as a 3 by 2 matrix in row-major order in memory.
+    ///
+    /// Transforms can be parametrized over the source and destination units, to describe a
+    /// transformation from a space to another.
+    /// For example, `TypedTransform2D<f32, WorldSpace, ScreenSpace>::transform_point4d`
+    /// takes a `TypedPoint2D<f32, WorldSpace>` and returns a `TypedPoint2D<f32, ScreenSpace>`.
+    ///
+    /// Transforms expose a set of convenience methods for pre- and post-transformations.
+    /// A pre-transformation corresponds to adding an operation that is applied before
+    /// the rest of the transformation, while a post-transformation adds an operation
+    /// that is applied after.
+    pub struct TypedTransform2D<T, Src, Dst> {
+        pub m11: T, pub m12: T,
+        pub m21: T, pub m22: T,
+        pub m31: T, pub m32: T,
+    }
+}
+
+/// The default 2d transform type with no units.
+pub type Transform2D<T> = TypedTransform2D<T, UnknownUnit, UnknownUnit>;
+
+impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
+    /// Create a transform specifying its matrix elements in row-major order.
+    pub fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
+        TypedTransform2D {
+            m11, m12,
+            m21, m22,
+            m31, m32,
+            _unit: PhantomData,
+        }
+    }
+
+    /// Create a transform specifying its matrix elements in column-major order.
+    pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
+        TypedTransform2D {
+            m11, m12,
+            m21, m22,
+            m31, m32,
+            _unit: PhantomData,
+        }
+    }
+
+    /// Returns an array containing this transform's terms in row-major order (the order
+    /// in which the transform is actually laid out in memory).
+    pub fn to_row_major_array(&self) -> [T; 6] {
+        [
+            self.m11, self.m12,
+            self.m21, self.m22,
+            self.m31, self.m32
+        ]
+    }
+
+    /// Returns an array containing this transform's terms in column-major order.
+    pub fn to_column_major_array(&self) -> [T; 6] {
+        [
+            self.m11, self.m21, self.m31,
+            self.m12, self.m22, self.m32
+        ]
+    }
+
+    /// Returns an array containing this transform's 3 rows in (in row-major order)
+    /// as arrays.
+    ///
+    /// This is a convenience method to interface with other libraries like glium.
+    pub fn to_row_arrays(&self) -> [[T; 2]; 3] {
+        [
+            [self.m11, self.m12],
+            [self.m21, self.m22],
+            [self.m31, self.m32],
+        ]
+    }
+
+    /// Creates a transform from an array of 6 elements in row-major order.
+    pub fn from_row_major_array(array: [T; 6]) -> Self {
+        Self::row_major(
+            array[0], array[1],
+            array[2], array[3],
+            array[4], array[5],
+        )
+    }
+
+    /// Creates a transform from 3 rows of 2 elements (row-major order).
+    pub fn from_row_arrays(array: [[T; 2]; 3]) -> Self {
+        Self::row_major(
+            array[0][0], array[0][1],
+            array[1][0], array[1][1],
+            array[2][0], array[2][1],
+        )
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    pub fn to_untyped(&self) -> Transform2D<T> {
+        Transform2D::row_major(
+            self.m11, self.m12,
+            self.m21, self.m22,
+            self.m31, self.m32
+        )
+    }
+
+    /// Tag a unitless value with units.
+    pub fn from_untyped(p: &Transform2D<T>) -> Self {
+        TypedTransform2D::row_major(
+            p.m11, p.m12,
+            p.m21, p.m22,
+            p.m31, p.m32
+        )
+    }
+}
+
+impl<T0: NumCast + Copy, Src, Dst> TypedTransform2D<T0, Src, Dst> {
+    /// Cast from one numeric representation to another, preserving the units.
+    pub fn cast<T1: NumCast + Copy>(&self) -> TypedTransform2D<T1, Src, Dst> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform2D<T1, Src, Dst>> {
+        match (NumCast::from(self.m11), NumCast::from(self.m12),
+               NumCast::from(self.m21), NumCast::from(self.m22),
+               NumCast::from(self.m31), NumCast::from(self.m32)) {
+            (Some(m11), Some(m12),
+             Some(m21), Some(m22),
+             Some(m31), Some(m32)) => {
+                Some(TypedTransform2D::row_major(
+                    m11, m12,
+                    m21, m22,
+                    m31, m32
+                ))
+            },
+            _ => None
+        }
+    }
+}
+
+impl<T, Src, Dst> TypedTransform2D<T, Src, Dst>
+where T: Copy +
+         PartialEq +
+         One + Zero {
+    pub fn identity() -> Self {
+        let (_0, _1) = (Zero::zero(), One::one());
+        TypedTransform2D::row_major(
+           _1, _0,
+           _0, _1,
+           _0, _0
+        )
+    }
+
+    // Intentional not public, because it checks for exact equivalence
+    // while most consumers will probably want some sort of approximate
+    // equivalence to deal with floating-point errors.
+    fn is_identity(&self) -> bool {
+        *self == TypedTransform2D::identity()
+    }
+}
+
+impl<T, Src, Dst> TypedTransform2D<T, Src, Dst>
+where T: Copy + Clone +
+         Add<T, Output=T> +
+         Mul<T, Output=T> +
+         Div<T, Output=T> +
+         Sub<T, Output=T> +
+         Trig +
+         PartialOrd +
+         One + Zero  {
+
+    /// Returns the multiplication of the two matrices such that mat's transformation
+    /// applies after self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_mul<NewDst>(&self, mat: &TypedTransform2D<T, Dst, NewDst>) -> TypedTransform2D<T, Src, NewDst> {
+        TypedTransform2D::row_major(
+            self.m11 * mat.m11 + self.m12 * mat.m21,
+            self.m11 * mat.m12 + self.m12 * mat.m22,
+            self.m21 * mat.m11 + self.m22 * mat.m21,
+            self.m21 * mat.m12 + self.m22 * mat.m22,
+            self.m31 * mat.m11 + self.m32 * mat.m21 + mat.m31,
+            self.m31 * mat.m12 + self.m32 * mat.m22 + mat.m32,
+        )
+    }
+
+    /// Returns the multiplication of the two matrices such that mat's transformation
+    /// applies before self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_mul<NewSrc>(&self, mat: &TypedTransform2D<T, NewSrc, Src>) -> TypedTransform2D<T, NewSrc, Dst> {
+        mat.post_mul(self)
+    }
+
+    /// Returns a translation transform.
+    pub fn create_translation(x: T, y: T) -> Self {
+         let (_0, _1): (T, T) = (Zero::zero(), One::one());
+         TypedTransform2D::row_major(
+            _1, _0,
+            _0, _1,
+             x,  y
+        )
+    }
+
+    /// Applies a translation after self's transformation and returns the resulting transform.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_translate(&self, v: TypedVector2D<T, Dst>) -> Self {
+        self.post_mul(&TypedTransform2D::create_translation(v.x, v.y))
+    }
+
+    /// Applies a translation before self's transformation and returns the resulting transform.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_translate(&self, v: TypedVector2D<T, Src>) -> Self {
+        self.pre_mul(&TypedTransform2D::create_translation(v.x, v.y))
+    }
+
+    /// Returns a scale transform.
+    pub fn create_scale(x: T, y: T) -> Self {
+        let _0 = Zero::zero();
+        TypedTransform2D::row_major(
+             x, _0,
+            _0,  y,
+            _0, _0
+        )
+    }
+
+    /// Applies a scale after self's transformation and returns the resulting transform.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_scale(&self, x: T, y: T) -> Self {
+        self.post_mul(&TypedTransform2D::create_scale(x, y))
+    }
+
+    /// Applies a scale before self's transformation and returns the resulting transform.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_scale(&self, x: T, y: T) -> Self {
+        TypedTransform2D::row_major(
+            self.m11 * x, self.m12,
+            self.m21,     self.m22 * y,
+            self.m31,     self.m32
+        )
+    }
+
+    /// Returns a rotation transform.
+    pub fn create_rotation(theta: Angle<T>) -> Self {
+        let _0 = Zero::zero();
+        let cos = theta.get().cos();
+        let sin = theta.get().sin();
+        TypedTransform2D::row_major(
+            cos, _0 - sin,
+            sin, cos,
+             _0, _0
+        )
+    }
+
+    /// Applies a rotation after self's transformation and returns the resulting transform.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_rotate(&self, theta: Angle<T>) -> Self {
+        self.post_mul(&TypedTransform2D::create_rotation(theta))
+    }
+
+    /// Applies a rotation after self's transformation and returns the resulting transform.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_rotate(&self, theta: Angle<T>) -> Self {
+        self.pre_mul(&TypedTransform2D::create_rotation(theta))
+    }
+
+    /// Returns the given point transformed by this transform.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
+        TypedPoint2D::new(point.x * self.m11 + point.y * self.m21 + self.m31,
+                          point.x * self.m12 + point.y * self.m22 + self.m32)
+    }
+
+    /// Returns the given vector transformed by this matrix.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn transform_vector(&self, vec: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
+        vec2(vec.x * self.m11 + vec.y * self.m21,
+             vec.x * self.m12 + vec.y * self.m22)
+    }
+
+    /// Returns a rectangle that encompasses the result of transforming the given rectangle by this
+    /// transform.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
+        TypedRect::from_points(&[
+            self.transform_point(&rect.origin),
+            self.transform_point(&rect.top_right()),
+            self.transform_point(&rect.bottom_left()),
+            self.transform_point(&rect.bottom_right()),
+        ])
+    }
+
+    /// Computes and returns the determinant of this transform.
+    pub fn determinant(&self) -> T {
+        self.m11 * self.m22 - self.m12 * self.m21
+    }
+
+    /// Returns the inverse transform if possible.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn inverse(&self) -> Option<TypedTransform2D<T, Dst, Src>> {
+        let det = self.determinant();
+
+        let _0: T = Zero::zero();
+        let _1: T = One::one();
+
+        if det == _0 {
+          return None;
+        }
+
+        let inv_det = _1 / det;
+        Some(TypedTransform2D::row_major(
+            inv_det * self.m22,
+            inv_det * (_0 - self.m12),
+            inv_det * (_0 - self.m21),
+            inv_det * self.m11,
+            inv_det * (self.m21 * self.m32 - self.m22 * self.m31),
+            inv_det * (self.m31 * self.m12 - self.m11 * self.m32),
+        ))
+    }
+
+    /// Returns the same transform with a different destination unit.
+    #[inline]
+    pub fn with_destination<NewDst>(&self) -> TypedTransform2D<T, Src, NewDst> {
+        TypedTransform2D::row_major(
+            self.m11, self.m12,
+            self.m21, self.m22,
+            self.m31, self.m32,
+        )
+    }
+
+    /// Returns the same transform with a different source unit.
+    #[inline]
+    pub fn with_source<NewSrc>(&self) -> TypedTransform2D<T, NewSrc, Dst> {
+        TypedTransform2D::row_major(
+            self.m11, self.m12,
+            self.m21, self.m22,
+            self.m31, self.m32,
+        )
+    }
+}
+
+impl <T, Src, Dst> TypedTransform2D<T, Src, Dst>
+where T: Copy + Clone +
+         Add<T, Output=T> +
+         Sub<T, Output=T> +
+         Mul<T, Output=T> +
+         Div<T, Output=T> +
+         Neg<Output=T> +
+         PartialOrd +
+         Trig +
+         One + Zero {
+    /// Create a 3D transform from the current transform
+    pub fn to_3d(&self) -> TypedTransform3D<T, Src, Dst> {
+        TypedTransform3D::row_major_2d(self.m11, self.m12, self.m21, self.m22, self.m31, self.m32)
+    }
+
+}
+
+impl <T, Src, Dst> Default for TypedTransform2D<T, Src, Dst>
+    where T: Copy + PartialEq + One + Zero
+{
+    fn default() -> Self {
+        Self::identity()
+    }
+}
+
+impl<T: ApproxEq<T>, Src, Dst> TypedTransform2D<T, Src, Dst> {
+    pub fn approx_eq(&self, other: &Self) -> bool {
+        self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
+        self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
+        self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32)
+    }
+}
+
+impl<T: Copy + fmt::Debug, Src, Dst> fmt::Debug for TypedTransform2D<T, Src, Dst>
+where T: Copy + fmt::Debug +
+         PartialEq +
+         One + Zero {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.is_identity() {
+            write!(f, "[I]")
+        } else {
+            self.to_row_major_array().fmt(f)
+        }
+    }
+}
+
+#[cfg(feature = "mint")]
+impl<T, Src, Dst> From<mint::RowMatrix3x2<T>> for TypedTransform2D<T, Src, Dst> {
+    fn from(m: mint::RowMatrix3x2<T>) -> Self {
+        TypedTransform2D {
+            m11: m.x.x, m12: m.x.y,
+            m21: m.y.x, m22: m.y.y,
+            m31: m.z.x, m32: m.z.y,
+            _unit: PhantomData,
+        }
+    }
+}
+#[cfg(feature = "mint")]
+impl<T, Src, Dst> Into<mint::RowMatrix3x2<T>> for TypedTransform2D<T, Src, Dst> {
+    fn into(self) -> mint::RowMatrix3x2<T> {
+        mint::RowMatrix3x2 {
+            x: mint::Vector2 { x: self.m11, y: self.m12 },
+            y: mint::Vector2 { x: self.m21, y: self.m22 },
+            z: mint::Vector2 { x: self.m31, y: self.m32 },
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use approxeq::ApproxEq;
+    use point::Point2D;
+    use Angle;
+    #[cfg(feature = "mint")]
+    use mint;
+
+    use core::f32::consts::FRAC_PI_2;
+
+    type Mat = Transform2D<f32>;
+
+    fn rad(v: f32) -> Angle<f32> { Angle::radians(v) }
+
+    #[test]
+    pub fn test_translation() {
+        let t1 = Mat::create_translation(1.0, 2.0);
+        let t2 = Mat::identity().pre_translate(vec2(1.0, 2.0));
+        let t3 = Mat::identity().post_translate(vec2(1.0, 2.0));
+        assert_eq!(t1, t2);
+        assert_eq!(t1, t3);
+
+        assert_eq!(t1.transform_point(&Point2D::new(1.0, 1.0)), Point2D::new(2.0, 3.0));
+
+        assert_eq!(t1.post_mul(&t1), Mat::create_translation(2.0, 4.0));
+    }
+
+    #[test]
+    pub fn test_rotation() {
+        let r1 = Mat::create_rotation(rad(FRAC_PI_2));
+        let r2 = Mat::identity().pre_rotate(rad(FRAC_PI_2));
+        let r3 = Mat::identity().post_rotate(rad(FRAC_PI_2));
+        assert_eq!(r1, r2);
+        assert_eq!(r1, r3);
+
+        assert!(r1.transform_point(&Point2D::new(1.0, 2.0)).approx_eq(&Point2D::new(2.0, -1.0)));
+
+        assert!(r1.post_mul(&r1).approx_eq(&Mat::create_rotation(rad(FRAC_PI_2*2.0))));
+    }
+
+    #[test]
+    pub fn test_scale() {
+        let s1 = Mat::create_scale(2.0, 3.0);
+        let s2 = Mat::identity().pre_scale(2.0, 3.0);
+        let s3 = Mat::identity().post_scale(2.0, 3.0);
+        assert_eq!(s1, s2);
+        assert_eq!(s1, s3);
+
+        assert!(s1.transform_point(&Point2D::new(2.0, 2.0)).approx_eq(&Point2D::new(4.0, 6.0)));
+    }
+
+    #[test]
+    fn test_column_major() {
+        assert_eq!(
+            Mat::row_major(
+                1.0,  2.0,
+                3.0,  4.0,
+                5.0,  6.0
+            ),
+            Mat::column_major(
+                1.0,  3.0,  5.0,
+                2.0,  4.0,  6.0,
+            )
+        );
+    }
+
+    #[test]
+    pub fn test_inverse_simple() {
+        let m1 = Mat::identity();
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.approx_eq(&m2));
+    }
+
+    #[test]
+    pub fn test_inverse_scale() {
+        let m1 = Mat::create_scale(1.5, 0.3);
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.pre_mul(&m2).approx_eq(&Mat::identity()));
+    }
+
+    #[test]
+    pub fn test_inverse_translate() {
+        let m1 = Mat::create_translation(-132.0, 0.3);
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.pre_mul(&m2).approx_eq(&Mat::identity()));
+    }
+
+    #[test]
+    fn test_inverse_none() {
+        assert!(Mat::create_scale(2.0, 0.0).inverse().is_none());
+        assert!(Mat::create_scale(2.0, 2.0).inverse().is_some());
+    }
+
+    #[test]
+    pub fn test_pre_post() {
+        let m1 = Transform2D::identity().post_scale(1.0, 2.0).post_translate(vec2(1.0, 2.0));
+        let m2 = Transform2D::identity().pre_translate(vec2(1.0, 2.0)).pre_scale(1.0, 2.0);
+        assert!(m1.approx_eq(&m2));
+
+        let r = Mat::create_rotation(rad(FRAC_PI_2));
+        let t = Mat::create_translation(2.0, 3.0);
+
+        let a = Point2D::new(1.0, 1.0);
+
+        assert!(r.post_mul(&t).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0)));
+        assert!(t.post_mul(&r).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0)));
+        assert!(t.post_mul(&r).transform_point(&a).approx_eq(&r.transform_point(&t.transform_point(&a))));
+
+        assert!(r.pre_mul(&t).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0)));
+        assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0)));
+        assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&t.transform_point(&r.transform_point(&a))));
+    }
+
+    #[test]
+    fn test_size_of() {
+        use core::mem::size_of;
+        assert_eq!(size_of::<Transform2D<f32>>(), 6*size_of::<f32>());
+        assert_eq!(size_of::<Transform2D<f64>>(), 6*size_of::<f64>());
+    }
+
+    #[test]
+    pub fn test_is_identity() {
+        let m1 = Transform2D::identity();
+        assert!(m1.is_identity());
+        let m2 = m1.post_translate(vec2(0.1, 0.0));
+        assert!(!m2.is_identity());
+    }
+
+    #[test]
+    pub fn test_transform_vector() {
+        // Translation does not apply to vectors.
+        let m1 = Mat::create_translation(1.0, 1.0);
+        let v1 = vec2(10.0, -10.0);
+        assert_eq!(v1, m1.transform_vector(&v1));
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let m1 = Mat::create_rotation(rad(FRAC_PI_2));
+        let mm: mint::RowMatrix3x2<_> = m1.into();
+        let m2 = Mat::from(mm);
+
+        assert_eq!(m1, m2);
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/transform3d.rs b/rustc_deps/vendor/euclid/src/transform3d.rs
new file mode 100644
index 0000000..94b2e45
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/transform3d.rs
@@ -0,0 +1,1061 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "cargo-clippy", allow(just_underscores_and_digits))]
+
+use super::{UnknownUnit, Angle};
+use approxeq::ApproxEq;
+use homogen::HomogeneousVector;
+#[cfg(feature = "mint")]
+use mint;
+use trig::Trig;
+use point::{TypedPoint2D, TypedPoint3D};
+use vector::{TypedVector2D, TypedVector3D, vec2, vec3};
+use rect::TypedRect;
+use transform2d::TypedTransform2D;
+use scale::TypedScale;
+use num::{One, Zero};
+use core::ops::{Add, Mul, Sub, Div, Neg};
+use core::marker::PhantomData;
+use core::fmt;
+use num_traits::NumCast;
+
+define_matrix! {
+    /// A 3d transform stored as a 4 by 4 matrix in row-major order in memory.
+    ///
+    /// Transforms can be parametrized over the source and destination units, to describe a
+    /// transformation from a space to another.
+    /// For example, `TypedTransform3D<f32, WorldSpace, ScreenSpace>::transform_point3d`
+    /// takes a `TypedPoint3D<f32, WorldSpace>` and returns a `TypedPoint3D<f32, ScreenSpace>`.
+    ///
+    /// Transforms expose a set of convenience methods for pre- and post-transformations.
+    /// A pre-transformation corresponds to adding an operation that is applied before
+    /// the rest of the transformation, while a post-transformation adds an operation
+    /// that is applied after.
+    pub struct TypedTransform3D<T, Src, Dst> {
+        pub m11: T, pub m12: T, pub m13: T, pub m14: T,
+        pub m21: T, pub m22: T, pub m23: T, pub m24: T,
+        pub m31: T, pub m32: T, pub m33: T, pub m34: T,
+        pub m41: T, pub m42: T, pub m43: T, pub m44: T,
+    }
+}
+
+/// The default 3d transform type with no units.
+pub type Transform3D<T> = TypedTransform3D<T, UnknownUnit, UnknownUnit>;
+
+impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
+    /// Create a transform specifying its components in row-major order.
+    ///
+    /// For example, the translation terms m41, m42, m43 on the last row with the
+    /// row-major convention) are the 13rd, 14th and 15th parameters.
+    #[inline]
+    #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
+    pub fn row_major(
+            m11: T, m12: T, m13: T, m14: T,
+            m21: T, m22: T, m23: T, m24: T,
+            m31: T, m32: T, m33: T, m34: T,
+            m41: T, m42: T, m43: T, m44: T)
+         -> Self {
+        TypedTransform3D {
+            m11, m12, m13, m14,
+            m21, m22, m23, m24,
+            m31, m32, m33, m34,
+            m41, m42, m43, m44,
+            _unit: PhantomData,
+        }
+    }
+
+    /// Create a transform specifying its components in column-major order.
+    ///
+    /// For example, the translation terms m41, m42, m43 on the last column with the
+    /// column-major convention) are the 4th, 8th and 12nd parameters.
+    #[inline]
+    #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
+    pub fn column_major(
+            m11: T, m21: T, m31: T, m41: T,
+            m12: T, m22: T, m32: T, m42: T,
+            m13: T, m23: T, m33: T, m43: T,
+            m14: T, m24: T, m34: T, m44: T)
+         -> Self {
+        TypedTransform3D {
+            m11, m12, m13, m14,
+            m21, m22, m23, m24,
+            m31, m32, m33, m34,
+            m41, m42, m43, m44,
+            _unit: PhantomData,
+        }
+    }
+}
+
+impl <T, Src, Dst> TypedTransform3D<T, Src, Dst>
+where T: Copy + Clone +
+         PartialEq +
+         One + Zero {
+    #[inline]
+    pub fn identity() -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        TypedTransform3D::row_major(
+            _1, _0, _0, _0,
+            _0, _1, _0, _0,
+            _0, _0, _1, _0,
+            _0, _0, _0, _1
+        )
+    }
+
+    // Intentional not public, because it checks for exact equivalence
+    // while most consumers will probably want some sort of approximate
+    // equivalence to deal with floating-point errors.
+    #[inline]
+    fn is_identity(&self) -> bool {
+        *self == TypedTransform3D::identity()
+    }
+}
+
+impl <T, Src, Dst> TypedTransform3D<T, Src, Dst>
+where T: Copy + Clone +
+         Add<T, Output=T> +
+         Sub<T, Output=T> +
+         Mul<T, Output=T> +
+         Div<T, Output=T> +
+         Neg<Output=T> +
+         PartialOrd +
+         Trig +
+         One + Zero {
+
+    /// Create a 4 by 4 transform representing a 2d transformation, specifying its components
+    /// in row-major order.
+    #[inline]
+    pub fn row_major_2d(m11: T, m12: T, m21: T, m22: T, m41: T, m42: T) -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        TypedTransform3D::row_major(
+            m11, m12, _0, _0,
+            m21, m22, _0, _0,
+             _0,  _0, _1, _0,
+            m41, m42, _0, _1
+       )
+    }
+
+    /// Create an orthogonal projection transform.
+    pub fn ortho(left: T, right: T,
+                 bottom: T, top: T,
+                 near: T, far: T) -> Self {
+        let tx = -((right + left) / (right - left));
+        let ty = -((top + bottom) / (top - bottom));
+        let tz = -((far + near) / (far - near));
+
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        let _2 = _1 + _1;
+        TypedTransform3D::row_major(
+            _2 / (right - left), _0                 , _0                , _0,
+            _0                 , _2 / (top - bottom), _0                , _0,
+            _0                 , _0                 , -_2 / (far - near), _0,
+            tx                 , ty                 , tz                , _1
+        )
+    }
+
+    /// Returns true if this transform can be represented with a `TypedTransform2D`.
+    ///
+    /// See <https://drafts.csswg.org/css-transforms/#2d-transform>
+    #[inline]
+    pub fn is_2d(&self) -> bool {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        self.m31 == _0 && self.m32 == _0 &&
+        self.m13 == _0 && self.m23 == _0 &&
+        self.m43 == _0 && self.m14 == _0 &&
+        self.m24 == _0 && self.m34 == _0 &&
+        self.m33 == _1 && self.m44 == _1
+    }
+
+    /// Create a 2D transform picking the relevant terms from this transform.
+    ///
+    /// This method assumes that self represents a 2d transformation, callers
+    /// should check that self.is_2d() returns true beforehand.
+    pub fn to_2d(&self) -> TypedTransform2D<T, Src, Dst> {
+        TypedTransform2D::row_major(
+            self.m11, self.m12,
+            self.m21, self.m22,
+            self.m41, self.m42
+        )
+    }
+
+    /// Check whether shapes on the XY plane with Z pointing towards the
+    /// screen transformed by this matrix would be facing back.
+    pub fn is_backface_visible(&self) -> bool {
+        // inverse().m33 < 0;
+        let det = self.determinant();
+        let m33 = self.m12 * self.m24 * self.m41 - self.m14 * self.m22 * self.m41 +
+                  self.m14 * self.m21 * self.m42 - self.m11 * self.m24 * self.m42 -
+                  self.m12 * self.m21 * self.m44 + self.m11 * self.m22 * self.m44;
+        let _0: T = Zero::zero();
+        (m33 * det) < _0
+    }
+
+    pub fn approx_eq(&self, other: &Self) -> bool
+    where T : ApproxEq<T> {
+        self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
+        self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) &&
+        self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
+        self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) &&
+        self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) &&
+        self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) &&
+        self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) &&
+        self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44)
+    }
+
+    /// Returns the same transform with a different destination unit.
+    #[inline]
+    pub fn with_destination<NewDst>(&self) -> TypedTransform3D<T, Src, NewDst> {
+        TypedTransform3D::row_major(
+            self.m11, self.m12, self.m13, self.m14,
+            self.m21, self.m22, self.m23, self.m24,
+            self.m31, self.m32, self.m33, self.m34,
+            self.m41, self.m42, self.m43, self.m44,
+        )
+    }
+
+    /// Returns the same transform with a different source unit.
+    #[inline]
+    pub fn with_source<NewSrc>(&self) -> TypedTransform3D<T, NewSrc, Dst> {
+        TypedTransform3D::row_major(
+            self.m11, self.m12, self.m13, self.m14,
+            self.m21, self.m22, self.m23, self.m24,
+            self.m31, self.m32, self.m33, self.m34,
+            self.m41, self.m42, self.m43, self.m44,
+        )
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    #[inline]
+    pub fn to_untyped(&self) -> Transform3D<T> {
+        Transform3D::row_major(
+            self.m11, self.m12, self.m13, self.m14,
+            self.m21, self.m22, self.m23, self.m24,
+            self.m31, self.m32, self.m33, self.m34,
+            self.m41, self.m42, self.m43, self.m44,
+        )
+    }
+
+    /// Tag a unitless value with units.
+    #[inline]
+    pub fn from_untyped(m: &Transform3D<T>) -> Self {
+        TypedTransform3D::row_major(
+            m.m11, m.m12, m.m13, m.m14,
+            m.m21, m.m22, m.m23, m.m24,
+            m.m31, m.m32, m.m33, m.m34,
+            m.m41, m.m42, m.m43, m.m44,
+        )
+    }
+
+    /// Returns the multiplication of the two matrices such that mat's transformation
+    /// applies after self's transformation.
+    pub fn post_mul<NewDst>(&self, mat: &TypedTransform3D<T, Dst, NewDst>) -> TypedTransform3D<T, Src, NewDst> {
+        TypedTransform3D::row_major(
+            self.m11 * mat.m11  +  self.m12 * mat.m21  +  self.m13 * mat.m31  +  self.m14 * mat.m41,
+            self.m11 * mat.m12  +  self.m12 * mat.m22  +  self.m13 * mat.m32  +  self.m14 * mat.m42,
+            self.m11 * mat.m13  +  self.m12 * mat.m23  +  self.m13 * mat.m33  +  self.m14 * mat.m43,
+            self.m11 * mat.m14  +  self.m12 * mat.m24  +  self.m13 * mat.m34  +  self.m14 * mat.m44,
+            self.m21 * mat.m11  +  self.m22 * mat.m21  +  self.m23 * mat.m31  +  self.m24 * mat.m41,
+            self.m21 * mat.m12  +  self.m22 * mat.m22  +  self.m23 * mat.m32  +  self.m24 * mat.m42,
+            self.m21 * mat.m13  +  self.m22 * mat.m23  +  self.m23 * mat.m33  +  self.m24 * mat.m43,
+            self.m21 * mat.m14  +  self.m22 * mat.m24  +  self.m23 * mat.m34  +  self.m24 * mat.m44,
+            self.m31 * mat.m11  +  self.m32 * mat.m21  +  self.m33 * mat.m31  +  self.m34 * mat.m41,
+            self.m31 * mat.m12  +  self.m32 * mat.m22  +  self.m33 * mat.m32  +  self.m34 * mat.m42,
+            self.m31 * mat.m13  +  self.m32 * mat.m23  +  self.m33 * mat.m33  +  self.m34 * mat.m43,
+            self.m31 * mat.m14  +  self.m32 * mat.m24  +  self.m33 * mat.m34  +  self.m34 * mat.m44,
+            self.m41 * mat.m11  +  self.m42 * mat.m21  +  self.m43 * mat.m31  +  self.m44 * mat.m41,
+            self.m41 * mat.m12  +  self.m42 * mat.m22  +  self.m43 * mat.m32  +  self.m44 * mat.m42,
+            self.m41 * mat.m13  +  self.m42 * mat.m23  +  self.m43 * mat.m33  +  self.m44 * mat.m43,
+            self.m41 * mat.m14  +  self.m42 * mat.m24  +  self.m43 * mat.m34  +  self.m44 * mat.m44,
+        )
+    }
+
+    /// Returns the multiplication of the two matrices such that mat's transformation
+    /// applies before self's transformation.
+    pub fn pre_mul<NewSrc>(&self, mat: &TypedTransform3D<T, NewSrc, Src>) -> TypedTransform3D<T, NewSrc, Dst> {
+        mat.post_mul(self)
+    }
+
+    /// Returns the inverse transform if possible.
+    pub fn inverse(&self) -> Option<TypedTransform3D<T, Dst, Src>> {
+        let det = self.determinant();
+
+        if det == Zero::zero() {
+            return None;
+        }
+
+        // todo(gw): this could be made faster by special casing
+        // for simpler transform types.
+        let m = TypedTransform3D::row_major(
+            self.m23*self.m34*self.m42 - self.m24*self.m33*self.m42 +
+            self.m24*self.m32*self.m43 - self.m22*self.m34*self.m43 -
+            self.m23*self.m32*self.m44 + self.m22*self.m33*self.m44,
+
+            self.m14*self.m33*self.m42 - self.m13*self.m34*self.m42 -
+            self.m14*self.m32*self.m43 + self.m12*self.m34*self.m43 +
+            self.m13*self.m32*self.m44 - self.m12*self.m33*self.m44,
+
+            self.m13*self.m24*self.m42 - self.m14*self.m23*self.m42 +
+            self.m14*self.m22*self.m43 - self.m12*self.m24*self.m43 -
+            self.m13*self.m22*self.m44 + self.m12*self.m23*self.m44,
+
+            self.m14*self.m23*self.m32 - self.m13*self.m24*self.m32 -
+            self.m14*self.m22*self.m33 + self.m12*self.m24*self.m33 +
+            self.m13*self.m22*self.m34 - self.m12*self.m23*self.m34,
+
+            self.m24*self.m33*self.m41 - self.m23*self.m34*self.m41 -
+            self.m24*self.m31*self.m43 + self.m21*self.m34*self.m43 +
+            self.m23*self.m31*self.m44 - self.m21*self.m33*self.m44,
+
+            self.m13*self.m34*self.m41 - self.m14*self.m33*self.m41 +
+            self.m14*self.m31*self.m43 - self.m11*self.m34*self.m43 -
+            self.m13*self.m31*self.m44 + self.m11*self.m33*self.m44,
+
+            self.m14*self.m23*self.m41 - self.m13*self.m24*self.m41 -
+            self.m14*self.m21*self.m43 + self.m11*self.m24*self.m43 +
+            self.m13*self.m21*self.m44 - self.m11*self.m23*self.m44,
+
+            self.m13*self.m24*self.m31 - self.m14*self.m23*self.m31 +
+            self.m14*self.m21*self.m33 - self.m11*self.m24*self.m33 -
+            self.m13*self.m21*self.m34 + self.m11*self.m23*self.m34,
+
+            self.m22*self.m34*self.m41 - self.m24*self.m32*self.m41 +
+            self.m24*self.m31*self.m42 - self.m21*self.m34*self.m42 -
+            self.m22*self.m31*self.m44 + self.m21*self.m32*self.m44,
+
+            self.m14*self.m32*self.m41 - self.m12*self.m34*self.m41 -
+            self.m14*self.m31*self.m42 + self.m11*self.m34*self.m42 +
+            self.m12*self.m31*self.m44 - self.m11*self.m32*self.m44,
+
+            self.m12*self.m24*self.m41 - self.m14*self.m22*self.m41 +
+            self.m14*self.m21*self.m42 - self.m11*self.m24*self.m42 -
+            self.m12*self.m21*self.m44 + self.m11*self.m22*self.m44,
+
+            self.m14*self.m22*self.m31 - self.m12*self.m24*self.m31 -
+            self.m14*self.m21*self.m32 + self.m11*self.m24*self.m32 +
+            self.m12*self.m21*self.m34 - self.m11*self.m22*self.m34,
+
+            self.m23*self.m32*self.m41 - self.m22*self.m33*self.m41 -
+            self.m23*self.m31*self.m42 + self.m21*self.m33*self.m42 +
+            self.m22*self.m31*self.m43 - self.m21*self.m32*self.m43,
+
+            self.m12*self.m33*self.m41 - self.m13*self.m32*self.m41 +
+            self.m13*self.m31*self.m42 - self.m11*self.m33*self.m42 -
+            self.m12*self.m31*self.m43 + self.m11*self.m32*self.m43,
+
+            self.m13*self.m22*self.m41 - self.m12*self.m23*self.m41 -
+            self.m13*self.m21*self.m42 + self.m11*self.m23*self.m42 +
+            self.m12*self.m21*self.m43 - self.m11*self.m22*self.m43,
+
+            self.m12*self.m23*self.m31 - self.m13*self.m22*self.m31 +
+            self.m13*self.m21*self.m32 - self.m11*self.m23*self.m32 -
+            self.m12*self.m21*self.m33 + self.m11*self.m22*self.m33
+        );
+
+        let _1: T = One::one();
+        Some(m.mul_s(_1 / det))
+    }
+
+    /// Compute the determinant of the transform.
+    pub fn determinant(&self) -> T {
+        self.m14 * self.m23 * self.m32 * self.m41 -
+        self.m13 * self.m24 * self.m32 * self.m41 -
+        self.m14 * self.m22 * self.m33 * self.m41 +
+        self.m12 * self.m24 * self.m33 * self.m41 +
+        self.m13 * self.m22 * self.m34 * self.m41 -
+        self.m12 * self.m23 * self.m34 * self.m41 -
+        self.m14 * self.m23 * self.m31 * self.m42 +
+        self.m13 * self.m24 * self.m31 * self.m42 +
+        self.m14 * self.m21 * self.m33 * self.m42 -
+        self.m11 * self.m24 * self.m33 * self.m42 -
+        self.m13 * self.m21 * self.m34 * self.m42 +
+        self.m11 * self.m23 * self.m34 * self.m42 +
+        self.m14 * self.m22 * self.m31 * self.m43 -
+        self.m12 * self.m24 * self.m31 * self.m43 -
+        self.m14 * self.m21 * self.m32 * self.m43 +
+        self.m11 * self.m24 * self.m32 * self.m43 +
+        self.m12 * self.m21 * self.m34 * self.m43 -
+        self.m11 * self.m22 * self.m34 * self.m43 -
+        self.m13 * self.m22 * self.m31 * self.m44 +
+        self.m12 * self.m23 * self.m31 * self.m44 +
+        self.m13 * self.m21 * self.m32 * self.m44 -
+        self.m11 * self.m23 * self.m32 * self.m44 -
+        self.m12 * self.m21 * self.m33 * self.m44 +
+        self.m11 * self.m22 * self.m33 * self.m44
+    }
+
+    /// Multiplies all of the transform's component by a scalar and returns the result.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn mul_s(&self, x: T) -> Self {
+        TypedTransform3D::row_major(
+            self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
+            self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
+            self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
+            self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x
+        )
+    }
+
+    /// Convenience function to create a scale transform from a `TypedScale`.
+    pub fn from_scale(scale: TypedScale<T, Src, Dst>) -> Self {
+        TypedTransform3D::create_scale(scale.get(), scale.get(), scale.get())
+    }
+
+    /// Returns the homogeneous vector corresponding to the transformed 2d point.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_point2d_homogeneous(
+        &self, p: &TypedPoint2D<T, Src>
+    ) -> HomogeneousVector<T, Dst> {
+        let x = p.x * self.m11 + p.y * self.m21 + self.m41;
+        let y = p.x * self.m12 + p.y * self.m22 + self.m42;
+        let z = p.x * self.m13 + p.y * self.m23 + self.m43;
+        let w = p.x * self.m14 + p.y * self.m24 + self.m44;
+
+        HomogeneousVector::new(x, y, z, w)
+    }
+
+    /// Returns the given 2d point transformed by this transform, if the transform makes sense,
+    /// or `None` otherwise.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    ///
+    #[inline]
+    pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> Option<TypedPoint2D<T, Dst>> {
+        //Note: could use `transform_point2d_homogeneous()` but it would waste the calculus of `z`
+        let w = p.x * self.m14 + p.y * self.m24 + self.m44;
+        if w > T::zero() {
+            let x = p.x * self.m11 + p.y * self.m21 + self.m41;
+            let y = p.x * self.m12 + p.y * self.m22 + self.m42;
+
+            Some(TypedPoint2D::new(x / w, y / w))
+        } else {
+            None
+        }
+    }
+
+    /// Returns the given 2d vector transformed by this matrix.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_vector2d(&self, v: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
+        vec2(
+            v.x * self.m11 + v.y * self.m21,
+            v.x * self.m12 + v.y * self.m22,
+        )
+    }
+
+    /// Returns the homogeneous vector corresponding to the transformed 3d point.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_point3d_homogeneous(
+        &self, p: &TypedPoint3D<T, Src>
+    ) -> HomogeneousVector<T, Dst> {
+        let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + self.m41;
+        let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + self.m42;
+        let z = p.x * self.m13 + p.y * self.m23 + p.z * self.m33 + self.m43;
+        let w = p.x * self.m14 + p.y * self.m24 + p.z * self.m34 + self.m44;
+
+        HomogeneousVector::new(x, y, z, w)
+    }
+
+    /// Returns the given 3d point transformed by this transform, if the transform makes sense,
+    /// or `None` otherwise.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> Option<TypedPoint3D<T, Dst>> {
+        self.transform_point3d_homogeneous(p).to_point3d()
+    }
+
+    /// Returns the given 3d vector transformed by this matrix.
+    ///
+    /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    #[inline]
+    pub fn transform_vector3d(&self, v: &TypedVector3D<T, Src>) -> TypedVector3D<T, Dst> {
+        vec3(
+            v.x * self.m11 + v.y * self.m21 + v.z * self.m31,
+            v.x * self.m12 + v.y * self.m22 + v.z * self.m32,
+            v.x * self.m13 + v.y * self.m23 + v.z * self.m33,
+        )
+    }
+
+    /// Returns a rectangle that encompasses the result of transforming the given rectangle by this
+    /// transform, if the transform makes sense for it, or `None` otherwise.
+    pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> Option<TypedRect<T, Dst>> {
+        Some(TypedRect::from_points(&[
+            self.transform_point2d(&rect.origin)?,
+            self.transform_point2d(&rect.top_right())?,
+            self.transform_point2d(&rect.bottom_left())?,
+            self.transform_point2d(&rect.bottom_right())?,
+        ]))
+    }
+
+    /// Create a 3d translation transform
+    pub fn create_translation(x: T, y: T, z: T) -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        TypedTransform3D::row_major(
+            _1, _0, _0, _0,
+            _0, _1, _0, _0,
+            _0, _0, _1, _0,
+             x,  y,  z, _1
+        )
+    }
+
+    /// Returns a transform with a translation applied before self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_translate(&self, v: TypedVector3D<T, Src>) -> Self {
+        self.pre_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z))
+    }
+
+    /// Returns a transform with a translation applied after self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_translate(&self, v: TypedVector3D<T, Dst>) -> Self {
+        self.post_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z))
+    }
+
+    /// 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());
+        TypedTransform3D::row_major(
+             x, _0, _0, _0,
+            _0,  y, _0, _0,
+            _0, _0,  z, _0,
+            _0, _0, _0, _1
+        )
+    }
+
+    /// Returns a transform with a scale applied before self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_scale(&self, x: T, y: T, z: T) -> Self {
+        TypedTransform3D::row_major(
+            self.m11 * x, self.m12,     self.m13,     self.m14,
+            self.m21    , self.m22 * y, self.m23,     self.m24,
+            self.m31    , self.m32,     self.m33 * z, self.m34,
+            self.m41    , self.m42,     self.m43,     self.m44
+        )
+    }
+
+    /// Returns a transform with a scale applied after self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_scale(&self, x: T, y: T, z: T) -> Self {
+        self.post_mul(&TypedTransform3D::create_scale(x, y, z))
+    }
+
+    /// Create a 3d rotation transform from an angle / axis.
+    /// The supplied axis must be normalized.
+    pub fn create_rotation(x: T, y: T, z: T, theta: Angle<T>) -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        let _2 = _1 + _1;
+
+        let xx = x * x;
+        let yy = y * y;
+        let zz = z * z;
+
+        let half_theta = theta.get() / _2;
+        let sc = half_theta.sin() * half_theta.cos();
+        let sq = half_theta.sin() * half_theta.sin();
+
+        TypedTransform3D::row_major(
+            _1 - _2 * (yy + zz) * sq,
+            _2 * (x * y * sq - z * sc),
+            _2 * (x * z * sq + y * sc),
+            _0,
+
+            _2 * (x * y * sq + z * sc),
+            _1 - _2 * (xx + zz) * sq,
+            _2 * (y * z * sq - x * sc),
+            _0,
+
+            _2 * (x * z * sq - y * sc),
+            _2 * (y * z * sq + x * sc),
+            _1 - _2 * (xx + yy) * sq,
+            _0,
+
+            _0,
+            _0,
+            _0,
+            _1
+        )
+    }
+
+    /// Returns a transform with a rotation applied after self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn post_rotate(&self, x: T, y: T, z: T, theta: Angle<T>) -> Self {
+        self.post_mul(&TypedTransform3D::create_rotation(x, y, z, theta))
+    }
+
+    /// Returns a transform with a rotation applied before self's transformation.
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn pre_rotate(&self, x: T, y: T, z: T, theta: Angle<T>) -> Self {
+        self.pre_mul(&TypedTransform3D::create_rotation(x, y, z, theta))
+    }
+
+    /// Create a 2d skew transform.
+    ///
+    /// See <https://drafts.csswg.org/css-transforms/#funcdef-skew>
+    pub fn create_skew(alpha: Angle<T>, beta: Angle<T>) -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        let (sx, sy) = (beta.get().tan(), alpha.get().tan());
+        TypedTransform3D::row_major(
+            _1, sx, _0, _0,
+            sy, _1, _0, _0,
+            _0, _0, _1, _0,
+            _0, _0, _0, _1
+        )
+    }
+
+    /// Create a simple perspective projection transform
+    pub fn create_perspective(d: T) -> Self {
+        let (_0, _1): (T, T) = (Zero::zero(), One::one());
+        TypedTransform3D::row_major(
+            _1, _0, _0, _0,
+            _0, _1, _0, _0,
+            _0, _0, _1, -_1 / d,
+            _0, _0, _0, _1
+        )
+    }
+}
+
+impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
+    /// Returns an array containing this transform's terms in row-major order (the order
+    /// in which the transform is actually laid out in memory).
+    pub fn to_row_major_array(&self) -> [T; 16] {
+        [
+            self.m11, self.m12, self.m13, self.m14,
+            self.m21, self.m22, self.m23, self.m24,
+            self.m31, self.m32, self.m33, self.m34,
+            self.m41, self.m42, self.m43, self.m44
+        ]
+    }
+
+    /// Returns an array containing this transform's terms in column-major order.
+    pub fn to_column_major_array(&self) -> [T; 16] {
+        [
+            self.m11, self.m21, self.m31, self.m41,
+            self.m12, self.m22, self.m32, self.m42,
+            self.m13, self.m23, self.m33, self.m43,
+            self.m14, self.m24, self.m34, self.m44
+        ]
+    }
+
+    /// Returns an array containing this transform's 4 rows in (in row-major order)
+    /// as arrays.
+    ///
+    /// This is a convenience method to interface with other libraries like glium.
+    pub fn to_row_arrays(&self) -> [[T; 4]; 4] {
+        [
+            [self.m11, self.m12, self.m13, self.m14],
+            [self.m21, self.m22, self.m23, self.m24],
+            [self.m31, self.m32, self.m33, self.m34],
+            [self.m41, self.m42, self.m43, self.m44]
+        ]
+    }
+
+    /// Returns an array containing this transform's 4 columns in (in row-major order,
+    /// or 4 rows in column-major order) as arrays.
+    ///
+    /// This is a convenience method to interface with other libraries like glium.
+    pub fn to_column_arrays(&self) -> [[T; 4]; 4] {
+        [
+            [self.m11, self.m21, self.m31, self.m41],
+            [self.m12, self.m22, self.m32, self.m42],
+            [self.m13, self.m23, self.m33, self.m43],
+            [self.m14, self.m24, self.m34, self.m44]
+        ]
+    }
+
+    /// Creates a transform from an array of 16 elements in row-major order.
+    pub fn from_array(array: [T; 16]) -> Self {
+        Self::row_major(
+            array[0],  array[1],  array[2],  array[3],
+            array[4],  array[5],  array[6],  array[7],
+            array[8],  array[9],  array[10], array[11],
+            array[12], array[13], array[14], array[15],
+        )
+    }
+
+    /// Creates a transform from 4 rows of 4 elements (row-major order).
+    pub fn from_row_arrays(array: [[T; 4]; 4]) -> Self {
+        Self::row_major(
+            array[0][0], array[0][1], array[0][2], array[0][3],
+            array[1][0], array[1][1], array[1][2], array[1][3],
+            array[2][0], array[2][1], array[2][2], array[2][3],
+            array[3][0], array[3][1], array[3][2], array[3][3],
+        )
+    }
+}
+
+impl<T0: NumCast + Copy, Src, Dst> TypedTransform3D<T0, Src, Dst> {
+    /// Cast from one numeric representation to another, preserving the units.
+    pub fn cast<T1: NumCast + Copy>(&self) -> TypedTransform3D<T1, Src, Dst> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform3D<T1, Src, Dst>> {
+        match (NumCast::from(self.m11), NumCast::from(self.m12),
+               NumCast::from(self.m13), NumCast::from(self.m14),
+               NumCast::from(self.m21), NumCast::from(self.m22),
+               NumCast::from(self.m23), NumCast::from(self.m24),
+               NumCast::from(self.m31), NumCast::from(self.m32),
+               NumCast::from(self.m33), NumCast::from(self.m34),
+               NumCast::from(self.m41), NumCast::from(self.m42),
+               NumCast::from(self.m43), NumCast::from(self.m44)) {
+            (Some(m11), Some(m12), Some(m13), Some(m14),
+             Some(m21), Some(m22), Some(m23), Some(m24),
+             Some(m31), Some(m32), Some(m33), Some(m34),
+             Some(m41), Some(m42), Some(m43), Some(m44)) => {
+                Some(TypedTransform3D::row_major(m11, m12, m13, m14,
+                                                 m21, m22, m23, m24,
+                                                 m31, m32, m33, m34,
+                                                 m41, m42, m43, m44))
+            },
+            _ => None
+        }
+    }
+}
+
+impl <T, Src, Dst> Default for TypedTransform3D<T, Src, Dst>
+    where T: Copy + PartialEq + One + Zero
+{
+    fn default() -> Self {
+        Self::identity()
+    }
+}
+
+impl<T, Src, Dst> fmt::Debug for TypedTransform3D<T, Src, Dst>
+where T: Copy + fmt::Debug +
+         PartialEq +
+         One + Zero {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.is_identity() {
+            write!(f, "[I]")
+        } else {
+            self.to_row_major_array().fmt(f)
+        }
+    }
+}
+
+#[cfg(feature = "mint")]
+impl<T, Src, Dst> From<mint::RowMatrix4<T>> for TypedTransform3D<T, Src, Dst> {
+    fn from(m: mint::RowMatrix4<T>) -> Self {
+        TypedTransform3D {
+            m11: m.x.x, m12: m.x.y, m13: m.x.z, m14: m.x.w,
+            m21: m.y.x, m22: m.y.y, m23: m.y.z, m24: m.y.w,
+            m31: m.z.x, m32: m.z.y, m33: m.z.z, m34: m.z.w,
+            m41: m.w.x, m42: m.w.y, m43: m.w.z, m44: m.w.w,
+            _unit: PhantomData,
+        }
+    }
+}
+#[cfg(feature = "mint")]
+impl<T, Src, Dst> Into<mint::RowMatrix4<T>> for TypedTransform3D<T, Src, Dst> {
+    fn into(self) -> mint::RowMatrix4<T> {
+        mint::RowMatrix4 {
+            x: mint::Vector4 { x: self.m11, y: self.m12, z: self.m13, w: self.m14 },
+            y: mint::Vector4 { x: self.m21, y: self.m22, z: self.m23, w: self.m24 },
+            z: mint::Vector4 { x: self.m31, y: self.m32, z: self.m33, w: self.m34 },
+            w: mint::Vector4 { x: self.m41, y: self.m42, z: self.m43, w: self.m44 },
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use approxeq::ApproxEq;
+    use transform2d::Transform2D;
+    use point::{point2, point3};
+    use Angle;
+    use super::*;
+
+    use core::f32::consts::{FRAC_PI_2, PI};
+
+    type Mf32 = Transform3D<f32>;
+
+    // For convenience.
+    fn rad(v: f32) -> Angle<f32> { Angle::radians(v) }
+
+    #[test]
+    pub fn test_translation() {
+        let t1 = Mf32::create_translation(1.0, 2.0, 3.0);
+        let t2 = Mf32::identity().pre_translate(vec3(1.0, 2.0, 3.0));
+        let t3 = Mf32::identity().post_translate(vec3(1.0, 2.0, 3.0));
+        assert_eq!(t1, t2);
+        assert_eq!(t1, t3);
+
+        assert_eq!(t1.transform_point3d(&point3(1.0, 1.0, 1.0)), Some(point3(2.0, 3.0, 4.0)));
+        assert_eq!(t1.transform_point2d(&point2(1.0, 1.0)), Some(point2(2.0, 3.0)));
+
+        assert_eq!(t1.post_mul(&t1), Mf32::create_translation(2.0, 4.0, 6.0));
+
+        assert!(!t1.is_2d());
+        assert_eq!(Mf32::create_translation(1.0, 2.0, 3.0).to_2d(), Transform2D::create_translation(1.0, 2.0));
+    }
+
+    #[test]
+    pub fn test_rotation() {
+        let r1 = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2));
+        let r2 = Mf32::identity().pre_rotate(0.0, 0.0, 1.0, rad(FRAC_PI_2));
+        let r3 = Mf32::identity().post_rotate(0.0, 0.0, 1.0, rad(FRAC_PI_2));
+        assert_eq!(r1, r2);
+        assert_eq!(r1, r3);
+
+        assert!(r1.transform_point3d(&point3(1.0, 2.0, 3.0)).unwrap().approx_eq(&point3(2.0, -1.0, 3.0)));
+        assert!(r1.transform_point2d(&point2(1.0, 2.0)).unwrap().approx_eq(&point2(2.0, -1.0)));
+
+        assert!(r1.post_mul(&r1).approx_eq(&Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2*2.0))));
+
+        assert!(r1.is_2d());
+        assert!(r1.to_2d().approx_eq(&Transform2D::create_rotation(rad(FRAC_PI_2))));
+    }
+
+    #[test]
+    pub fn test_scale() {
+        let s1 = Mf32::create_scale(2.0, 3.0, 4.0);
+        let s2 = Mf32::identity().pre_scale(2.0, 3.0, 4.0);
+        let s3 = Mf32::identity().post_scale(2.0, 3.0, 4.0);
+        assert_eq!(s1, s2);
+        assert_eq!(s1, s3);
+
+        assert!(s1.transform_point3d(&point3(2.0, 2.0, 2.0)).unwrap().approx_eq(&point3(4.0, 6.0, 8.0)));
+        assert!(s1.transform_point2d(&point2(2.0, 2.0)).unwrap().approx_eq(&point2(4.0, 6.0)));
+
+        assert_eq!(s1.post_mul(&s1), Mf32::create_scale(4.0, 9.0, 16.0));
+
+        assert!(!s1.is_2d());
+        assert_eq!(Mf32::create_scale(2.0, 3.0, 0.0).to_2d(), Transform2D::create_scale(2.0, 3.0));
+    }
+
+    #[test]
+    pub fn test_ortho() {
+        let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32);
+        let (near, far) = (-1.0f32, 1.0f32);
+        let result = Mf32::ortho(left, right, bottom, top, near, far);
+        let expected = Mf32::row_major(
+             2.0,  0.0,         0.0, 0.0,
+             0.0,  2.22222222,  0.0, 0.0,
+             0.0,  0.0,        -1.0, 0.0,
+            -1.0, -1.22222222, -0.0, 1.0
+        );
+        assert!(result.approx_eq(&expected));
+    }
+
+    #[test]
+    pub fn test_is_2d() {
+        assert!(Mf32::identity().is_2d());
+        assert!(Mf32::create_rotation(0.0, 0.0, 1.0, rad(0.7854)).is_2d());
+        assert!(!Mf32::create_rotation(0.0, 1.0, 0.0, rad(0.7854)).is_2d());
+    }
+
+    #[test]
+    pub fn test_row_major_2d() {
+        let m1 = Mf32::row_major_2d(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
+        let m2 = Mf32::row_major(
+            1.0, 2.0, 0.0, 0.0,
+            3.0, 4.0, 0.0, 0.0,
+            0.0, 0.0, 1.0, 0.0,
+            5.0, 6.0, 0.0, 1.0
+        );
+        assert_eq!(m1, m2);
+    }
+
+    #[test]
+    fn test_column_major() {
+        assert_eq!(
+            Mf32::row_major(
+                1.0,  2.0,  3.0,  4.0,
+                5.0,  6.0,  7.0,  8.0,
+                9.0,  10.0, 11.0, 12.0,
+                13.0, 14.0, 15.0, 16.0,
+            ),
+            Mf32::column_major(
+                1.0,  5.0,  9.0,  13.0,
+                2.0,  6.0,  10.0, 14.0,
+                3.0,  7.0,  11.0, 15.0,
+                4.0,  8.0,  12.0, 16.0,
+            )
+        );
+    }
+
+    #[test]
+    pub fn test_inverse_simple() {
+        let m1 = Mf32::identity();
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.approx_eq(&m2));
+    }
+
+    #[test]
+    pub fn test_inverse_scale() {
+        let m1 = Mf32::create_scale(1.5, 0.3, 2.1);
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
+    }
+
+    #[test]
+    pub fn test_inverse_translate() {
+        let m1 = Mf32::create_translation(-132.0, 0.3, 493.0);
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
+    }
+
+    #[test]
+    pub fn test_inverse_rotate() {
+        let m1 = Mf32::create_rotation(0.0, 1.0, 0.0, rad(1.57));
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
+    }
+
+    #[test]
+    pub fn test_inverse_transform_point_2d() {
+        let m1 = Mf32::create_translation(100.0, 200.0, 0.0);
+        let m2 = m1.inverse().unwrap();
+        assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
+
+        let p1 = point2(1000.0, 2000.0);
+        let p2 = m1.transform_point2d(&p1);
+        assert_eq!(p2, Some(point2(1100.0, 2200.0)));
+
+        let p3 = m2.transform_point2d(&p2.unwrap());
+        assert_eq!(p3, Some(p1));
+    }
+
+    #[test]
+    fn test_inverse_none() {
+        assert!(Mf32::create_scale(2.0, 0.0, 2.0).inverse().is_none());
+        assert!(Mf32::create_scale(2.0, 2.0, 2.0).inverse().is_some());
+    }
+
+    #[test]
+    pub fn test_pre_post() {
+        let m1 = Transform3D::identity().post_scale(1.0, 2.0, 3.0).post_translate(vec3(1.0, 2.0, 3.0));
+        let m2 = Transform3D::identity().pre_translate(vec3(1.0, 2.0, 3.0)).pre_scale(1.0, 2.0, 3.0);
+        assert!(m1.approx_eq(&m2));
+
+        let r = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2));
+        let t = Mf32::create_translation(2.0, 3.0, 0.0);
+
+        let a = point3(1.0, 1.0, 1.0);
+
+        assert!(r.post_mul(&t).transform_point3d(&a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
+        assert!(t.post_mul(&r).transform_point3d(&a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
+        assert!(t.post_mul(&r).transform_point3d(&a).unwrap().approx_eq(&r.transform_point3d(&t.transform_point3d(&a).unwrap()).unwrap()));
+
+        assert!(r.pre_mul(&t).transform_point3d(&a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
+        assert!(t.pre_mul(&r).transform_point3d(&a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
+        assert!(t.pre_mul(&r).transform_point3d(&a).unwrap().approx_eq(&t.transform_point3d(&r.transform_point3d(&a).unwrap()).unwrap()));
+    }
+
+    #[test]
+    fn test_size_of() {
+        use core::mem::size_of;
+        assert_eq!(size_of::<Transform3D<f32>>(), 16*size_of::<f32>());
+        assert_eq!(size_of::<Transform3D<f64>>(), 16*size_of::<f64>());
+    }
+
+    #[test]
+    pub fn test_transform_associativity() {
+        let m1 = Mf32::row_major(3.0, 2.0, 1.5, 1.0,
+                                 0.0, 4.5, -1.0, -4.0,
+                                 0.0, 3.5, 2.5, 40.0,
+                                 0.0, 3.0, 0.0, 1.0);
+        let m2 = Mf32::row_major(1.0, -1.0, 3.0, 0.0,
+                                 -1.0, 0.5, 0.0, 2.0,
+                                 1.5, -2.0, 6.0, 0.0,
+                                 -2.5, 6.0, 1.0, 1.0);
+
+        let p = point3(1.0, 3.0, 5.0);
+        let p1 = m2.pre_mul(&m1).transform_point3d(&p).unwrap();
+        let p2 = m2.transform_point3d(&m1.transform_point3d(&p).unwrap()).unwrap();
+        assert!(p1.approx_eq(&p2));
+    }
+
+    #[test]
+    pub fn test_is_identity() {
+        let m1 = Transform3D::identity();
+        assert!(m1.is_identity());
+        let m2 = m1.post_translate(vec3(0.1, 0.0, 0.0));
+        assert!(!m2.is_identity());
+    }
+
+    #[test]
+    pub fn test_transform_vector() {
+        // Translation does not apply to vectors.
+        let m = Mf32::create_translation(1.0, 2.0, 3.0);
+        let v1 = vec3(10.0, -10.0, 3.0);
+        assert_eq!(v1, m.transform_vector3d(&v1));
+        // While it does apply to points.
+        assert_ne!(Some(v1.to_point()), m.transform_point3d(&v1.to_point()));
+
+        // same thing with 2d vectors/points
+        let v2 = vec2(10.0, -5.0);
+        assert_eq!(v2, m.transform_vector2d(&v2));
+        assert_ne!(Some(v2.to_point()), m.transform_point2d(&v2.to_point()));
+    }
+
+    #[test]
+    pub fn test_is_backface_visible() {
+        // backface is not visible for rotate-x 0 degree.
+        let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(0.0));
+        assert!(!r1.is_backface_visible());
+        // backface is not visible for rotate-x 45 degree.
+        let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(PI * 0.25));
+        assert!(!r1.is_backface_visible());
+        // backface is visible for rotate-x 180 degree.
+        let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(PI));
+        assert!(r1.is_backface_visible());
+        // backface is visible for rotate-x 225 degree.
+        let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(PI * 1.25));
+        assert!(r1.is_backface_visible());
+        // backface is not visible for non-inverseable matrix
+        let r1 = Mf32::create_scale(2.0, 0.0, 2.0);
+        assert!(!r1.is_backface_visible());
+    }
+
+    #[test]
+    pub fn test_homogeneous() {
+        let m = Mf32::row_major(
+            1.0, 2.0, 0.5, 5.0,
+            3.0, 4.0, 0.25, 6.0,
+            0.5, -1.0, 1.0, -1.0,
+            -1.0, 1.0, -1.0, 2.0,
+        );
+        assert_eq!(
+            m.transform_point2d_homogeneous(&point2(1.0, 2.0)),
+            HomogeneousVector::new(6.0, 11.0, 0.0, 19.0),
+        );
+        assert_eq!(
+            m.transform_point3d_homogeneous(&point3(1.0, 2.0, 4.0)),
+            HomogeneousVector::new(8.0, 7.0, 4.0, 15.0),
+        );
+    }
+
+    #[test]
+    pub fn test_perspective_division() {
+        let p = point2(1.0, 2.0);
+        let mut m = Mf32::identity();
+        assert!(m.transform_point2d(&p).is_some());
+        m.m44 = 0.0;
+        assert_eq!(None, m.transform_point2d(&p));
+        m.m44 = 1.0;
+        m.m24 = -1.0;
+        assert_eq!(None, m.transform_point2d(&p));
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let m1 = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2));
+        let mm: mint::RowMatrix4<_> = m1.into();
+        let m2 = Mf32::from(mm);
+
+        assert_eq!(m1, m2);
+    }
+}
diff --git a/rustc_deps/vendor/euclid/src/trig.rs b/rustc_deps/vendor/euclid/src/trig.rs
new file mode 100644
index 0000000..9eb9c23
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/trig.rs
@@ -0,0 +1,73 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Trait for basic trigonometry functions, so they can be used on generic numeric types
+pub trait Trig {
+    fn sin(self) -> Self;
+    fn cos(self) -> Self;
+    fn tan(self) -> Self;
+    fn fast_atan2(y: Self, x: Self) -> Self;
+    fn degrees_to_radians(deg: Self) -> Self;
+    fn radians_to_degrees(rad: Self) -> Self;
+}
+
+macro_rules! trig {
+    ($ty:ident) => (
+        impl Trig for $ty {
+            #[inline]
+            fn sin(self) -> $ty { self.sin() }
+            #[inline]
+            fn cos(self) -> $ty { self.cos() }
+            #[inline]
+            fn tan(self) -> $ty { self.tan() }
+
+            /// A slightly faster approximation of `atan2`.
+            ///
+            /// Note that it does not deal with the case where both x and y are 0.
+            #[inline]
+            fn fast_atan2(y: $ty, x: $ty) -> $ty {
+                // This macro is used with f32 and f64 and clippy warns about the extra
+                // precision with f32.
+                #![cfg_attr(feature = "cargo-clippy", allow(excessive_precision))]
+
+                // See https://math.stackexchange.com/questions/1098487/atan2-faster-approximation#1105038
+                use core::$ty::consts;
+                let x_abs = x.abs();
+                let y_abs = y.abs();
+                let a = x_abs.min(y_abs) / x_abs.max(y_abs);
+                let s = a * a;
+                let mut result = ((-0.046_496_474_9 * s + 0.159_314_22) * s - 0.327_622_764) * s * a + a;
+                if y_abs > x_abs {
+                    result = consts::FRAC_PI_2 - result;
+                }
+                if x < 0.0 {
+                    result = consts::PI - result
+                }
+                if y < 0.0 {
+                    result = -result
+                }
+
+                result
+            }
+
+            #[inline]
+            fn degrees_to_radians(deg: Self) -> Self {
+                deg.to_radians()
+            }
+
+            #[inline]
+            fn radians_to_degrees(rad: Self) -> Self {
+                rad.to_degrees()
+            }
+        }
+    )
+}
+
+trig!(f32);
+trig!(f64);
diff --git a/rustc_deps/vendor/euclid/src/vector.rs b/rustc_deps/vendor/euclid/src/vector.rs
new file mode 100644
index 0000000..5fe7963
--- /dev/null
+++ b/rustc_deps/vendor/euclid/src/vector.rs
@@ -0,0 +1,1524 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::UnknownUnit;
+use approxeq::ApproxEq;
+use length::Length;
+#[cfg(feature = "mint")]
+use mint;
+use point::{TypedPoint2D, TypedPoint3D, point2, point3};
+use size::{TypedSize2D, size2};
+use scale::TypedScale;
+use trig::Trig;
+use Angle;
+use num::*;
+use num_traits::{Float, NumCast, Signed};
+use core::fmt;
+use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
+use core::marker::PhantomData;
+
+define_matrix! {
+    /// A 2d Vector tagged with a unit.
+    pub struct TypedVector2D<T, U> {
+        pub x: T,
+        pub y: T,
+    }
+}
+mint_vec!(TypedVector2D[x, y] = Vector2);
+
+/// Default 2d vector type with no unit.
+///
+/// `Vector2D` provides the same methods as `TypedVector2D`.
+pub type Vector2D<T> = TypedVector2D<T, UnknownUnit>;
+
+impl<T: Copy + Zero, U> TypedVector2D<T, U> {
+    /// Constructor, setting all components to zero.
+    #[inline]
+    pub fn zero() -> Self {
+        TypedVector2D::new(Zero::zero(), Zero::zero())
+    }
+
+    /// Convert into a 3d vector.
+    #[inline]
+    pub fn to_3d(&self) -> TypedVector3D<T, U> {
+        vec3(self.x, self.y, Zero::zero())
+    }
+}
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedVector2D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({:?},{:?})", self.x, self.y)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for TypedVector2D<T, U> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "({},{})", self.x, self.y)
+    }
+}
+
+impl<T, U> TypedVector2D<T, U> {
+    /// Constructor taking scalar values directly.
+    #[inline]
+    pub fn new(x: T, y: T) -> Self {
+        TypedVector2D {
+            x,
+            y,
+            _unit: PhantomData,
+        }
+    }
+}
+
+impl<T: Copy, U> TypedVector2D<T, U> {
+    /// Constructor taking properly typed Lengths instead of scalar values.
+    #[inline]
+    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>) -> Self {
+        vec2(x.0, y.0)
+    }
+
+    /// Create a 3d vector from this one, using the specified z value.
+    #[inline]
+    pub fn extend(&self, z: T) -> TypedVector3D<T, U> {
+        vec3(self.x, self.y, z)
+    }
+
+    /// Cast this vector into a point.
+    ///
+    /// Equivalent to adding this vector to the origin.
+    #[inline]
+    pub fn to_point(&self) -> TypedPoint2D<T, U> {
+        point2(self.x, self.y)
+    }
+
+    /// Swap x and y.
+    #[inline]
+    pub fn yx(&self) -> Self {
+        vec2(self.y, self.x)
+    }
+
+    /// Cast this vector into a size.
+    #[inline]
+    pub fn to_size(&self) -> TypedSize2D<T, U> {
+        size2(self.x, self.y)
+    }
+
+    /// Returns self.x as a Length carrying the unit.
+    #[inline]
+    pub fn x_typed(&self) -> Length<T, U> {
+        Length::new(self.x)
+    }
+
+    /// Returns self.y as a Length carrying the unit.
+    #[inline]
+    pub fn y_typed(&self) -> Length<T, U> {
+        Length::new(self.y)
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    #[inline]
+    pub fn to_untyped(&self) -> Vector2D<T> {
+        vec2(self.x, self.y)
+    }
+
+    /// Tag a unit-less value with units.
+    #[inline]
+    pub fn from_untyped(p: &Vector2D<T>) -> Self {
+        vec2(p.x, p.y)
+    }
+
+    #[inline]
+    pub fn to_array(&self) -> [T; 2] {
+        [self.x, self.y]
+    }
+}
+
+impl<T, U> TypedVector2D<T, U>
+where
+    T: Trig + Copy + Sub<T, Output = T>,
+{
+    /// Returns the angle between this vector and the x axis between -PI and PI.
+    pub fn angle_from_x_axis(&self) -> Angle<T> {
+        Angle::radians(Trig::fast_atan2(self.y, self.x))
+    }
+}
+
+impl<T, U> TypedVector2D<T, U>
+where
+    T: Copy + Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T>,
+{
+    /// Dot product.
+    #[inline]
+    pub fn dot(self, other: Self) -> T {
+        self.x * other.x + self.y * other.y
+    }
+
+    /// Returns the norm of the cross product [self.x, self.y, 0] x [other.x, other.y, 0]..
+    #[inline]
+    pub fn cross(self, other: Self) -> T {
+        self.x * other.y - self.y * other.x
+    }
+
+    #[inline]
+    pub fn normalize(self) -> Self
+    where
+        T: Float,
+    {
+        self / self.length()
+    }
+
+    /// Return the normalized vector even if the length is larger than the max value of Float.
+    #[inline]
+    pub fn robust_normalize(self) -> Self
+    where
+        T: Float,
+    {
+        let length = self.length();
+        if length.is_infinite() {
+            let scaled = self / T::max_value();
+            scaled / scaled.length()
+        } else {
+            self / length
+        }
+    }
+
+    #[inline]
+    pub fn square_length(&self) -> T {
+        self.x * self.x + self.y * self.y
+    }
+
+    #[inline]
+    pub fn length(&self) -> T
+    where
+        T: Float,
+    {
+        self.square_length().sqrt()
+    }
+}
+
+impl<T, U> TypedVector2D<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this vector and another vector.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        (*self) * one_t + other * t
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> Add for TypedVector2D<T, U> {
+    type Output = Self;
+    fn add(self, other: Self) -> Self {
+        TypedVector2D::new(self.x + other.x, self.y + other.y)
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> AddAssign for TypedVector2D<T, U> {
+    #[inline]
+    fn add_assign(&mut self, other: Self) {
+        *self = *self + other
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector2D<T, U>> for TypedVector2D<T, U> {
+    #[inline]
+    fn sub_assign(&mut self, other: Self) {
+        *self = *self - other
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedVector2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn sub(self, other: Self) -> Self {
+        vec2(self.x - other.x, self.y - other.y)
+    }
+}
+
+impl<T: Copy + Neg<Output = T>, U> Neg for TypedVector2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        vec2(-self.x, -self.y)
+    }
+}
+
+impl<T: Float, U> TypedVector2D<T, U> {
+    #[inline]
+    pub fn min(self, other: Self) -> Self {
+        vec2(self.x.min(other.x), self.y.min(other.y))
+    }
+
+    #[inline]
+    pub fn max(self, other: Self) -> Self {
+        vec2(self.x.max(other.x), self.y.max(other.y))
+    }
+
+    #[inline]
+    pub fn clamp(&self, start: Self, end: Self) -> Self {
+        self.max(start).min(end)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedVector2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        vec2(self.x * scale, self.y * scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedVector2D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        vec2(self.x / scale, self.y / scale)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for TypedVector2D<T, U> {
+    #[inline]
+    fn mul_assign(&mut self, scale: T) {
+        *self = *self * scale
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for TypedVector2D<T, U> {
+    #[inline]
+    fn div_assign(&mut self, scale: T) {
+        *self = *self / scale
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedVector2D<T, U1> {
+    type Output = TypedVector2D<T, U2>;
+    #[inline]
+    fn mul(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
+        vec2(self.x * scale.get(), self.y * scale.get())
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedVector2D<T, U2> {
+    type Output = TypedVector2D<T, U1>;
+    #[inline]
+    fn div(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
+        vec2(self.x / scale.get(), self.y / scale.get())
+    }
+}
+
+impl<T: Round, U> TypedVector2D<T, U> {
+    /// Rounds each component to the nearest integer value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    /// For example `{ -0.1, -0.8 }.round() == { 0.0, -1.0 }`.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round(&self) -> Self {
+        vec2(self.x.round(), self.y.round())
+    }
+}
+
+impl<T: Ceil, U> TypedVector2D<T, U> {
+    /// Rounds each component to the smallest integer equal or greater than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    /// For example `{ -0.1, -0.8 }.ceil() == { 0.0, 0.0 }`.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn ceil(&self) -> Self {
+        vec2(self.x.ceil(), self.y.ceil())
+    }
+}
+
+impl<T: Floor, U> TypedVector2D<T, U> {
+    /// Rounds each component to the biggest integer equal or lower than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    /// For example `{ -0.1, -0.8 }.floor() == { -1.0, -1.0 }`.
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn floor(&self) -> Self {
+        vec2(self.x.floor(), self.y.floor())
+    }
+}
+
+impl<T: NumCast + Copy, U> TypedVector2D<T, U> {
+    /// Cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating vector to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedVector2D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating vector to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector2D<NewT, U>> {
+        match (NumCast::from(self.x), NumCast::from(self.y)) {
+            (Some(x), Some(y)) => Some(TypedVector2D::new(x, y)),
+            _ => None,
+        }
+    }
+
+    // Convenience functions for common casts
+
+    /// Cast into an `f32` vector.
+    #[inline]
+    pub fn to_f32(&self) -> TypedVector2D<f32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `f64` vector.
+    #[inline]
+    pub fn to_f64(&self) -> TypedVector2D<f64, U> {
+        self.cast()
+    }
+
+    /// Cast into an `usize` vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_usize(&self) -> TypedVector2D<usize, U> {
+        self.cast()
+    }
+
+    /// Cast into an `u32` vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_u32(&self) -> TypedVector2D<u32, U> {
+        self.cast()
+    }
+
+    /// Cast into an i32 vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i32(&self) -> TypedVector2D<i32, U> {
+        self.cast()
+    }
+
+    /// Cast into an i64 vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i64(&self) -> TypedVector2D<i64, U> {
+        self.cast()
+    }
+}
+
+impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedVector2D<T, U>> for TypedVector2D<T, U> {
+    #[inline]
+    fn approx_epsilon() -> Self {
+        vec2(T::approx_epsilon(), T::approx_epsilon())
+    }
+
+    #[inline]
+    fn approx_eq(&self, other: &Self) -> bool {
+        self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y)
+    }
+
+    #[inline]
+    fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
+        self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
+    }
+}
+
+impl<T: Copy, U> Into<[T; 2]> for TypedVector2D<T, U> {
+    fn into(self) -> [T; 2] {
+        self.to_array()
+    }
+}
+
+impl<T: Copy, U> From<[T; 2]> for TypedVector2D<T, U> {
+    fn from(array: [T; 2]) -> Self {
+        vec2(array[0], array[1])
+    }
+}
+
+impl<T, U> TypedVector2D<T, U>
+where
+    T: Signed,
+{
+    pub fn abs(&self) -> Self {
+        vec2(self.x.abs(), self.y.abs())
+    }
+}
+
+define_matrix! {
+    /// A 3d Vector tagged with a unit.
+    pub struct TypedVector3D<T, U> {
+        pub x: T,
+        pub y: T,
+        pub z: T,
+    }
+}
+mint_vec!(TypedVector3D[x, y, z] = Vector3);
+
+/// Default 3d vector type with no unit.
+///
+/// `Vector3D` provides the same methods as `TypedVector3D`.
+pub type Vector3D<T> = TypedVector3D<T, UnknownUnit>;
+
+impl<T: Copy + Zero, U> TypedVector3D<T, U> {
+    /// Constructor, setting all components to zero.
+    #[inline]
+    pub fn zero() -> Self {
+        vec3(Zero::zero(), Zero::zero(), Zero::zero())
+    }
+
+    #[inline]
+    pub fn to_array_4d(&self) -> [T; 4] {
+        [self.x, self.y, self.z, Zero::zero()]
+    }
+}
+
+impl<T: fmt::Debug, U> fmt::Debug for TypedVector3D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z)
+    }
+}
+
+impl<T: fmt::Display, U> fmt::Display for TypedVector3D<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({},{},{})", self.x, self.y, self.z)
+    }
+}
+
+impl<T, U> TypedVector3D<T, U> {
+    /// Constructor taking scalar values directly.
+    #[inline]
+    pub fn new(x: T, y: T, z: T) -> Self {
+        TypedVector3D {
+            x,
+            y,
+            z,
+            _unit: PhantomData,
+        }
+    }
+}
+
+impl<T: Copy, U> TypedVector3D<T, U> {
+    /// Constructor taking properly typed Lengths instead of scalar values.
+    #[inline]
+    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>, z: Length<T, U>) -> TypedVector3D<T, U> {
+        vec3(x.0, y.0, z.0)
+    }
+
+    /// Cast this vector into a point.
+    ///
+    /// Equivalent to adding this vector to the origin.
+    #[inline]
+    pub fn to_point(&self) -> TypedPoint3D<T, U> {
+        point3(self.x, self.y, self.z)
+    }
+
+    /// Returns a 2d vector using this vector's x and y coordinates
+    #[inline]
+    pub fn xy(&self) -> TypedVector2D<T, U> {
+        vec2(self.x, self.y)
+    }
+
+    /// Returns a 2d vector using this vector's x and z coordinates
+    #[inline]
+    pub fn xz(&self) -> TypedVector2D<T, U> {
+        vec2(self.x, self.z)
+    }
+
+    /// Returns a 2d vector using this vector's x and z coordinates
+    #[inline]
+    pub fn yz(&self) -> TypedVector2D<T, U> {
+        vec2(self.y, self.z)
+    }
+
+    /// Returns self.x as a Length carrying the unit.
+    #[inline]
+    pub fn x_typed(&self) -> Length<T, U> {
+        Length::new(self.x)
+    }
+
+    /// Returns self.y as a Length carrying the unit.
+    #[inline]
+    pub fn y_typed(&self) -> Length<T, U> {
+        Length::new(self.y)
+    }
+
+    /// Returns self.z as a Length carrying the unit.
+    #[inline]
+    pub fn z_typed(&self) -> Length<T, U> {
+        Length::new(self.z)
+    }
+
+    #[inline]
+    pub fn to_array(&self) -> [T; 3] {
+        [self.x, self.y, self.z]
+    }
+
+    /// Drop the units, preserving only the numeric value.
+    #[inline]
+    pub fn to_untyped(&self) -> Vector3D<T> {
+        vec3(self.x, self.y, self.z)
+    }
+
+    /// Tag a unitless value with units.
+    #[inline]
+    pub fn from_untyped(p: &Vector3D<T>) -> Self {
+        vec3(p.x, p.y, p.z)
+    }
+
+    /// Convert into a 2d vector.
+    #[inline]
+    pub fn to_2d(&self) -> TypedVector2D<T, U> {
+        self.xy()
+    }
+}
+
+impl<T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Copy, U>
+    TypedVector3D<T, U> {
+    // Dot product.
+    #[inline]
+    pub fn dot(self, other: Self) -> T {
+        self.x * other.x + self.y * other.y + self.z * other.z
+    }
+
+    // Cross product.
+    #[inline]
+    pub fn cross(self, other: Self) -> Self {
+        vec3(
+            self.y * other.z - self.z * other.y,
+            self.z * other.x - self.x * other.z,
+            self.x * other.y - self.y * other.x,
+        )
+    }
+
+    #[inline]
+    pub fn normalize(self) -> Self
+    where
+        T: Float,
+    {
+        self / self.length()
+    }
+
+    /// Return the normalized vector even if the length is larger than the max value of Float.
+    #[inline]
+    pub fn robust_normalize(self) -> Self
+    where
+        T: Float,
+    {
+        let length = self.length();
+        if length.is_infinite() {
+            let scaled = self / T::max_value();
+            scaled / scaled.length()
+        } else {
+            self / length
+        }
+    }
+
+    #[inline]
+    pub fn square_length(&self) -> T {
+        self.x * self.x + self.y * self.y + self.z * self.z
+    }
+
+    #[inline]
+    pub fn length(&self) -> T
+    where
+        T: Float,
+    {
+        self.square_length().sqrt()
+    }
+}
+
+impl<T, U> TypedVector3D<T, U>
+where
+    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
+{
+    /// Linearly interpolate between this vector and another vector.
+    ///
+    /// `t` is expected to be between zero and one.
+    #[inline]
+    pub fn lerp(&self, other: Self, t: T) -> Self {
+        let one_t = T::one() - t;
+        (*self) * one_t + other * t
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> Add for TypedVector3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn add(self, other: Self) -> Self {
+        vec3(self.x + other.x, self.y + other.y, self.z + other.z)
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedVector3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn sub(self, other: Self) -> Self {
+        vec3(self.x - other.x, self.y - other.y, self.z - other.z)
+    }
+}
+
+impl<T: Copy + Add<T, Output = T>, U> AddAssign for TypedVector3D<T, U> {
+    #[inline]
+    fn add_assign(&mut self, other: Self) {
+        *self = *self + other
+    }
+}
+
+impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector3D<T, U>> for TypedVector3D<T, U> {
+    #[inline]
+    fn sub_assign(&mut self, other: Self) {
+        *self = *self - other
+    }
+}
+
+impl<T: Copy + Neg<Output = T>, U> Neg for TypedVector3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        vec3(-self.x, -self.y, -self.z)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedVector3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn mul(self, scale: T) -> Self {
+        Self::new(self.x * scale, self.y * scale, self.z * scale)
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedVector3D<T, U> {
+    type Output = Self;
+    #[inline]
+    fn div(self, scale: T) -> Self {
+        Self::new(self.x / scale, self.y / scale, self.z / scale)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for TypedVector3D<T, U> {
+    #[inline]
+    fn mul_assign(&mut self, scale: T) {
+        *self = *self * scale
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for TypedVector3D<T, U> {
+    #[inline]
+    fn div_assign(&mut self, scale: T) {
+        *self = *self / scale
+    }
+}
+
+impl<T: Float, U> TypedVector3D<T, U> {
+    #[inline]
+    pub fn min(self, other: Self) -> Self {
+        vec3(
+            self.x.min(other.x),
+            self.y.min(other.y),
+            self.z.min(other.z),
+        )
+    }
+
+    #[inline]
+    pub fn max(self, other: Self) -> Self {
+        vec3(
+            self.x.max(other.x),
+            self.y.max(other.y),
+            self.z.max(other.z),
+        )
+    }
+
+    #[inline]
+    pub fn clamp(&self, start: Self, end: Self) -> Self {
+        self.max(start).min(end)
+    }
+}
+
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedVector3D<T, U1> {
+    type Output = TypedVector3D<T, U2>;
+    #[inline]
+    fn mul(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
+        vec3(self.x * scale.get(), self.y * scale.get(), self.z * scale.get())
+    }
+}
+
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedVector3D<T, U2> {
+    type Output = TypedVector3D<T, U1>;
+    #[inline]
+    fn div(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
+        vec3(self.x / scale.get(), self.y / scale.get(), self.z / scale.get())
+    }
+}
+
+impl<T: Round, U> TypedVector3D<T, U> {
+    /// Rounds each component to the nearest integer value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn round(&self) -> Self {
+        vec3(self.x.round(), self.y.round(), self.z.round())
+    }
+}
+
+impl<T: Ceil, U> TypedVector3D<T, U> {
+    /// Rounds each component to the smallest integer equal or greater than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn ceil(&self) -> Self {
+        vec3(self.x.ceil(), self.y.ceil(), self.z.ceil())
+    }
+}
+
+impl<T: Floor, U> TypedVector3D<T, U> {
+    /// Rounds each component to the biggest integer equal or lower than the original value.
+    ///
+    /// This behavior is preserved for negative values (unlike the basic cast).
+    #[inline]
+    #[cfg_attr(feature = "unstable", must_use)]
+    pub fn floor(&self) -> Self {
+        vec3(self.x.floor(), self.y.floor(), self.z.floor())
+    }
+}
+
+impl<T: NumCast + Copy, U> TypedVector3D<T, U> {
+    /// Cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating vector to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedVector3D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating vector to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector3D<NewT, U>> {
+        match (
+            NumCast::from(self.x),
+            NumCast::from(self.y),
+            NumCast::from(self.z),
+        ) {
+            (Some(x), Some(y), Some(z)) => Some(vec3(x, y, z)),
+            _ => None,
+        }
+    }
+
+    // Convenience functions for common casts
+
+    /// Cast into an `f32` vector.
+    #[inline]
+    pub fn to_f32(&self) -> TypedVector3D<f32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `f64` vector.
+    #[inline]
+    pub fn to_f64(&self) -> TypedVector3D<f64, U> {
+        self.cast()
+    }
+
+    /// Cast into an `usize` vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_usize(&self) -> TypedVector3D<usize, U> {
+        self.cast()
+    }
+
+    /// Cast into an `u32` vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_u32(&self) -> TypedVector3D<u32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `i32` vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i32(&self) -> TypedVector3D<i32, U> {
+        self.cast()
+    }
+
+    /// Cast into an `i64` vector, truncating decimals if any.
+    ///
+    /// When casting from floating vector vectors, it is worth considering whether
+    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
+    /// the desired conversion behavior.
+    #[inline]
+    pub fn to_i64(&self) -> TypedVector3D<i64, U> {
+        self.cast()
+    }
+}
+
+impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedVector3D<T, U>> for TypedVector3D<T, U> {
+    #[inline]
+    fn approx_epsilon() -> Self {
+        vec3(
+            T::approx_epsilon(),
+            T::approx_epsilon(),
+            T::approx_epsilon(),
+        )
+    }
+
+    #[inline]
+    fn approx_eq(&self, other: &Self) -> bool {
+        self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) && self.z.approx_eq(&other.z)
+    }
+
+    #[inline]
+    fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
+        self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
+            && self.z.approx_eq_eps(&other.z, &eps.z)
+    }
+}
+
+impl<T: Copy, U> Into<[T; 3]> for TypedVector3D<T, U> {
+    fn into(self) -> [T; 3] {
+        self.to_array()
+    }
+}
+
+impl<T: Copy, U> From<[T; 3]> for TypedVector3D<T, U> {
+    fn from(array: [T; 3]) -> Self {
+        vec3(array[0], array[1], array[2])
+    }
+}
+
+impl<T, U> TypedVector3D<T, U>
+where
+    T: Signed,
+{
+    pub fn abs(&self) -> Self {
+        vec3(self.x.abs(), self.y.abs(), self.z.abs())
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct BoolVector2D {
+    pub x: bool,
+    pub y: bool,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct BoolVector3D {
+    pub x: bool,
+    pub y: bool,
+    pub z: bool,
+}
+
+impl BoolVector2D {
+    #[inline]
+    pub fn all(&self) -> bool {
+        self.x && self.y
+    }
+
+    #[inline]
+    pub fn any(&self) -> bool {
+        self.x || self.y
+    }
+
+    #[inline]
+    pub fn none(&self) -> bool {
+        !self.any()
+    }
+
+    #[inline]
+    pub fn and(&self, other: Self) -> Self {
+        BoolVector2D {
+            x: self.x && other.x,
+            y: self.y && other.y,
+        }
+    }
+
+    #[inline]
+    pub fn or(&self, other: Self) -> Self {
+        BoolVector2D {
+            x: self.x || other.x,
+            y: self.y || other.y,
+        }
+    }
+
+    #[inline]
+    pub fn not(&self) -> Self {
+        BoolVector2D {
+            x: !self.x,
+            y: !self.y,
+        }
+    }
+
+    #[inline]
+    pub fn select_point<T: Copy, U>(&self, a: &TypedPoint2D<T, U>, b: &TypedPoint2D<T, U>) -> TypedPoint2D<T, U> {
+        point2(
+            if self.x { a.x } else { b.x },
+            if self.y { a.y } else { b.y },
+        )
+    }
+
+    #[inline]
+    pub fn select_vector<T: Copy, U>(&self, a: &TypedVector2D<T, U>, b: &TypedVector2D<T, U>) -> TypedVector2D<T, U> {
+        vec2(
+            if self.x { a.x } else { b.x },
+            if self.y { a.y } else { b.y },
+        )
+    }
+
+    #[inline]
+    pub fn select_size<T: Copy, U>(&self, a: &TypedSize2D<T, U>, b: &TypedSize2D<T, U>) -> TypedSize2D<T, U> {
+        size2(
+            if self.x { a.width } else { b.width },
+            if self.y { a.height } else { b.height },
+        )
+    }
+}
+
+impl BoolVector3D {
+    #[inline]
+    pub fn all(&self) -> bool {
+        self.x && self.y && self.z
+    }
+
+    #[inline]
+    pub fn any(&self) -> bool {
+        self.x || self.y || self.z
+    }
+
+    #[inline]
+    pub fn none(&self) -> bool {
+        !self.any()
+    }
+
+    #[inline]
+    pub fn and(&self, other: Self) -> Self {
+        BoolVector3D {
+            x: self.x && other.x,
+            y: self.y && other.y,
+            z: self.z && other.z,
+        }
+    }
+
+    #[inline]
+    pub fn or(&self, other: Self) -> Self {
+        BoolVector3D {
+            x: self.x || other.x,
+            y: self.y || other.y,
+            z: self.z || other.z,
+        }
+    }
+
+    #[inline]
+    pub fn not(&self) -> Self {
+        BoolVector3D {
+            x: !self.x,
+            y: !self.y,
+            z: !self.z,
+        }
+    }
+
+
+    #[inline]
+    pub fn select_point<T: Copy, U>(&self, a: &TypedPoint3D<T, U>, b: &TypedPoint3D<T, U>) -> TypedPoint3D<T, U> {
+        point3(
+            if self.x { a.x } else { b.x },
+            if self.y { a.y } else { b.y },
+            if self.z { a.z } else { b.z },
+        )
+    }
+
+    #[inline]
+    pub fn select_vector<T: Copy, U>(&self, a: &TypedVector3D<T, U>, b: &TypedVector3D<T, U>) -> TypedVector3D<T, U> {
+        vec3(
+            if self.x { a.x } else { b.x },
+            if self.y { a.y } else { b.y },
+            if self.z { a.z } else { b.z },
+        )
+    }
+
+    #[inline]
+    pub fn xy(&self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    pub fn xz(&self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    pub fn yz(&self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.y,
+            y: self.z,
+        }
+    }
+}
+
+impl<T: PartialOrd, U> TypedVector2D<T, U> {
+    pub fn greater_than(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.x > other.x,
+            y: self.y > other.y,
+        }
+    }
+
+    pub fn lower_than(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.x < other.x,
+            y: self.y < other.y,
+        }
+    }
+}
+
+
+impl<T: PartialEq, U> TypedVector2D<T, U> {
+    pub fn equal(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.x == other.x,
+            y: self.y == other.y,
+        }
+    }
+
+    pub fn not_equal(&self, other: &Self) -> BoolVector2D {
+        BoolVector2D {
+            x: self.x != other.x,
+            y: self.y != other.y,
+        }
+    }
+}
+
+impl<T: PartialOrd, U> TypedVector3D<T, U> {
+    pub fn greater_than(&self, other: &Self) -> BoolVector3D {
+        BoolVector3D {
+            x: self.x > other.x,
+            y: self.y > other.y,
+            z: self.z > other.z,
+        }
+    }
+
+    pub fn lower_than(&self, other: &Self) -> BoolVector3D {
+        BoolVector3D {
+            x: self.x < other.x,
+            y: self.y < other.y,
+            z: self.z < other.z,
+        }
+    }
+}
+
+
+impl<T: PartialEq, U> TypedVector3D<T, U> {
+    pub fn equal(&self, other: &Self) -> BoolVector3D {
+        BoolVector3D {
+            x: self.x == other.x,
+            y: self.y == other.y,
+            z: self.z == other.z,
+        }
+    }
+
+    pub fn not_equal(&self, other: &Self) -> BoolVector3D {
+        BoolVector3D {
+            x: self.x != other.x,
+            y: self.y != other.y,
+            z: self.z != other.z,
+        }
+    }
+}
+
+/// Convenience constructor.
+#[inline]
+pub fn vec2<T, U>(x: T, y: T) -> TypedVector2D<T, U> {
+    TypedVector2D::new(x, y)
+}
+
+/// Convenience constructor.
+#[inline]
+pub fn vec3<T, U>(x: T, y: T, z: T) -> TypedVector3D<T, U> {
+    TypedVector3D::new(x, y, z)
+}
+
+#[inline]
+pub fn bvec2(x: bool, y: bool) -> BoolVector2D {
+    BoolVector2D { x, y }
+}
+
+#[inline]
+pub fn bvec3(x: bool, y: bool, z: bool) -> BoolVector3D {
+    BoolVector3D { x, y, z }
+}
+
+
+#[cfg(test)]
+mod vector2d {
+    use super::{Vector2D, vec2};
+    #[cfg(feature = "mint")]
+    use mint;
+    type Vec2 = Vector2D<f32>;
+
+    #[test]
+    pub fn test_scalar_mul() {
+        let p1: Vec2 = vec2(3.0, 5.0);
+
+        let result = p1 * 5.0;
+
+        assert_eq!(result, Vector2D::new(15.0, 25.0));
+    }
+
+    #[test]
+    pub fn test_dot() {
+        let p1: Vec2 = vec2(2.0, 7.0);
+        let p2: Vec2 = vec2(13.0, 11.0);
+        assert_eq!(p1.dot(p2), 103.0);
+    }
+
+    #[test]
+    pub fn test_cross() {
+        let p1: Vec2 = vec2(4.0, 7.0);
+        let p2: Vec2 = vec2(13.0, 8.0);
+        let r = p1.cross(p2);
+        assert_eq!(r, -59.0);
+    }
+
+    #[test]
+    pub fn test_normalize() {
+        let p0: Vec2 = Vec2::zero();
+        let p1: Vec2 = vec2(4.0, 0.0);
+        let p2: Vec2 = vec2(3.0, -4.0);
+        assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan());
+        assert_eq!(p1.normalize(), vec2(1.0, 0.0));
+        assert_eq!(p2.normalize(), vec2(0.6, -0.8));
+
+        let p3: Vec2 = vec2(::std::f32::MAX, ::std::f32::MAX);
+        assert_ne!(p3.normalize(), vec2(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt()));
+        assert_eq!(p3.robust_normalize(), vec2(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt()));
+    }
+
+    #[test]
+    pub fn test_min() {
+        let p1: Vec2 = vec2(1.0, 3.0);
+        let p2: Vec2 = vec2(2.0, 2.0);
+
+        let result = p1.min(p2);
+
+        assert_eq!(result, vec2(1.0, 2.0));
+    }
+
+    #[test]
+    pub fn test_max() {
+        let p1: Vec2 = vec2(1.0, 3.0);
+        let p2: Vec2 = vec2(2.0, 2.0);
+
+        let result = p1.max(p2);
+
+        assert_eq!(result, vec2(2.0, 3.0));
+    }
+    #[test]
+    pub fn test_angle_from_x_axis() {
+        use core::f32::consts::FRAC_PI_2;
+        use approxeq::ApproxEq;
+
+        let right: Vec2 = vec2(10.0, 0.0);
+        let down: Vec2 = vec2(0.0, 4.0);
+        let up: Vec2 = vec2(0.0, -1.0);
+
+        assert!(right.angle_from_x_axis().get().approx_eq(&0.0));
+        assert!(down.angle_from_x_axis().get().approx_eq(&FRAC_PI_2));
+        assert!(up.angle_from_x_axis().get().approx_eq(&-FRAC_PI_2));
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let v1 = Vec2::new(1.0, 3.0);
+        let vm: mint::Vector2<_> = v1.into();
+        let v2 = Vec2::from(vm);
+
+        assert_eq!(v1, v2);
+    }
+}
+
+#[cfg(test)]
+mod typedvector2d {
+    use super::{TypedVector2D, Vector2D, vec2};
+    use scale::TypedScale;
+
+    pub enum Mm {}
+    pub enum Cm {}
+
+    pub type Vector2DMm<T> = TypedVector2D<T, Mm>;
+    pub type Vector2DCm<T> = TypedVector2D<T, Cm>;
+
+    #[test]
+    pub fn test_add() {
+        let p1 = Vector2DMm::new(1.0, 2.0);
+        let p2 = Vector2DMm::new(3.0, 4.0);
+
+        let result = p1 + p2;
+
+        assert_eq!(result, vec2(4.0, 6.0));
+    }
+
+    #[test]
+    pub fn test_add_assign() {
+        let mut p1 = Vector2DMm::new(1.0, 2.0);
+        p1 += vec2(3.0, 4.0);
+
+        assert_eq!(p1, vec2(4.0, 6.0));
+    }
+
+    #[test]
+    pub fn test_scalar_mul() {
+        let p1 = Vector2DMm::new(1.0, 2.0);
+        let cm_per_mm = TypedScale::<f32, Mm, Cm>::new(0.1);
+
+        let result: Vector2DCm<f32> = p1 * cm_per_mm;
+
+        assert_eq!(result, vec2(0.1, 0.2));
+    }
+
+    #[test]
+    pub fn test_swizzling() {
+        let p: Vector2D<i32> = vec2(1, 2);
+        assert_eq!(p.yx(), vec2(2, 1));
+    }
+}
+
+#[cfg(test)]
+mod vector3d {
+    #[cfg(feature = "mint")]
+    use mint;
+    use super::{TypedVector3D, Vector3D, vec2, vec3};
+    use scale::TypedScale;
+
+    type Vec3 = Vector3D<f32>;
+
+    #[test]
+    pub fn test_dot() {
+        let p1: Vec3 = vec3(7.0, 21.0, 32.0);
+        let p2: Vec3 = vec3(43.0, 5.0, 16.0);
+        assert_eq!(p1.dot(p2), 918.0);
+    }
+
+    #[test]
+    pub fn test_cross() {
+        let p1: Vec3 = vec3(4.0, 7.0, 9.0);
+        let p2: Vec3 = vec3(13.0, 8.0, 3.0);
+        let p3 = p1.cross(p2);
+        assert_eq!(p3, vec3(-51.0, 105.0, -59.0));
+    }
+
+    #[test]
+    pub fn test_normalize() {
+        let p0: Vec3 = Vec3::zero();
+        let p1: Vec3 = vec3(0.0, -6.0, 0.0);
+        let p2: Vec3 = vec3(1.0, 2.0, -2.0);
+        assert!(
+            p0.normalize().x.is_nan() && p0.normalize().y.is_nan() && p0.normalize().z.is_nan()
+        );
+        assert_eq!(p1.normalize(), vec3(0.0, -1.0, 0.0));
+        assert_eq!(p2.normalize(), vec3(1.0 / 3.0, 2.0 / 3.0, -2.0 / 3.0));
+
+        let p3: Vec3 = vec3(::std::f32::MAX, ::std::f32::MAX, 0.0);
+        assert_ne!(p3.normalize(), vec3(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt(), 0.0));
+        assert_eq!(p3.robust_normalize(), vec3(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt(), 0.0));
+    }
+
+    #[test]
+    pub fn test_min() {
+        let p1: Vec3 = vec3(1.0, 3.0, 5.0);
+        let p2: Vec3 = vec3(2.0, 2.0, -1.0);
+
+        let result = p1.min(p2);
+
+        assert_eq!(result, vec3(1.0, 2.0, -1.0));
+    }
+
+    #[test]
+    pub fn test_max() {
+        let p1: Vec3 = vec3(1.0, 3.0, 5.0);
+        let p2: Vec3 = vec3(2.0, 2.0, -1.0);
+
+        let result = p1.max(p2);
+
+        assert_eq!(result, vec3(2.0, 3.0, 5.0));
+    }
+
+    #[test]
+    pub fn test_clamp() {
+        let p1: Vec3 = vec3(1.0, -1.0, 5.0);
+        let p2: Vec3 = vec3(2.0, 5.0, 10.0);
+        let p3: Vec3 = vec3(-1.0, 2.0, 20.0);
+
+        let result = p3.clamp(p1, p2);
+
+        assert_eq!(result, vec3(1.0, 2.0, 10.0));
+    }
+
+    #[test]
+    pub fn test_scalar_mul() {
+        enum Mm {}
+        enum Cm {}
+
+        let p1 = TypedVector3D::<f32, Mm>::new(1.0, 2.0, 3.0);
+        let cm_per_mm = TypedScale::<f32, Mm, Cm>::new(0.1);
+
+        let result: TypedVector3D<f32, Cm> = p1 * cm_per_mm;
+
+        assert_eq!(result, vec3(0.1, 0.2, 0.3));
+    }
+
+    #[test]
+    pub fn test_swizzling() {
+        let p: Vector3D<i32> = vec3(1, 2, 3);
+        assert_eq!(p.xy(), vec2(1, 2));
+        assert_eq!(p.xz(), vec2(1, 3));
+        assert_eq!(p.yz(), vec2(2, 3));
+    }
+
+    #[cfg(feature = "mint")]
+    #[test]
+    pub fn test_mint() {
+        let v1 = Vec3::new(1.0, 3.0, 5.0);
+        let vm: mint::Vector3<_> = v1.into();
+        let v2 = Vec3::from(vm);
+
+        assert_eq!(v1, v2);
+    }
+}
+
+#[cfg(test)]
+mod bool_vector {
+    use super::*;
+    type Vec2 = Vector2D<f32>;
+    type Vec3 = Vector3D<f32>;
+
+    #[test]
+    fn test_bvec2() {
+
+        assert_eq!(
+            Vec2::new(1.0, 2.0).greater_than(&Vec2::new(2.0, 1.0)),
+            bvec2(false, true),
+        );
+
+        assert_eq!(
+            Vec2::new(1.0, 2.0).lower_than(&Vec2::new(2.0, 1.0)),
+            bvec2(true, false),
+        );
+
+        assert_eq!(
+            Vec2::new(1.0, 2.0).equal(&Vec2::new(1.0, 3.0)),
+            bvec2(true, false),
+        );
+
+        assert_eq!(
+            Vec2::new(1.0, 2.0).not_equal(&Vec2::new(1.0, 3.0)),
+            bvec2(false, true),
+        );
+
+        assert!(bvec2(true, true).any());
+        assert!(bvec2(false, true).any());
+        assert!(bvec2(true, false).any());
+        assert!(!bvec2(false, false).any());
+        assert!(bvec2(false, false).none());
+        assert!(bvec2(true, true).all());
+        assert!(!bvec2(false, true).all());
+        assert!(!bvec2(true, false).all());
+        assert!(!bvec2(false, false).all());
+
+        assert_eq!(bvec2(true, false).not(), bvec2(false, true));
+        assert_eq!(bvec2(true, false).and(bvec2(true, true)), bvec2(true, false));
+        assert_eq!(bvec2(true, false).or(bvec2(true, true)), bvec2(true, true));
+
+        assert_eq!(
+            bvec2(true, false).select_vector(&Vec2::new(1.0, 2.0), &Vec2::new(3.0, 4.0)),
+            Vec2::new(1.0, 4.0),
+        );
+    }
+
+    #[test]
+    fn test_bvec3() {
+
+        assert_eq!(
+            Vec3::new(1.0, 2.0, 3.0).greater_than(&Vec3::new(3.0, 2.0, 1.0)),
+            bvec3(false, false, true),
+        );
+
+        assert_eq!(
+            Vec3::new(1.0, 2.0, 3.0).lower_than(&Vec3::new(3.0, 2.0, 1.0)),
+            bvec3(true, false, false),
+        );
+
+        assert_eq!(
+            Vec3::new(1.0, 2.0, 3.0).equal(&Vec3::new(3.0, 2.0, 1.0)),
+            bvec3(false, true, false),
+        );
+
+        assert_eq!(
+            Vec3::new(1.0, 2.0, 3.0).not_equal(&Vec3::new(3.0, 2.0, 1.0)),
+            bvec3(true, false, true),
+        );
+
+        assert!(bvec3(true, true, false).any());
+        assert!(bvec3(false, true, false).any());
+        assert!(bvec3(true, false, false).any());
+        assert!(!bvec3(false, false, false).any());
+        assert!(bvec3(false, false, false).none());
+        assert!(bvec3(true, true, true).all());
+        assert!(!bvec3(false, true, false).all());
+        assert!(!bvec3(true, false, false).all());
+        assert!(!bvec3(false, false, false).all());
+
+        assert_eq!(bvec3(true, false, true).not(), bvec3(false, true, false));
+        assert_eq!(bvec3(true, false, true).and(bvec3(true, true, false)), bvec3(true, false, false));
+        assert_eq!(bvec3(true, false, false).or(bvec3(true, true, false)), bvec3(true, true, false));
+
+        assert_eq!(
+            bvec3(true, false, true).select_vector(&Vec3::new(1.0, 2.0, 3.0), &Vec3::new(4.0, 5.0, 6.0)),
+            Vec3::new(1.0, 5.0, 3.0),
+        );
+    }
+
+}